From b72f8a59d6beb6c614eec65ce4fe338c745ca309 Mon Sep 17 00:00:00 2001 From: pseudo-aloha Date: Sun, 24 Sep 2023 09:39:47 +0800 Subject: [PATCH 001/307] gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 6d3150bc..514e6d7b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ /src/lib/*.so /src/lib/lib.d +/src/ext/*.so + /engine /include *.o From 741ed2ea8f06372b3556d0a78b9f1c33825e5aea Mon Sep 17 00:00:00 2001 From: pseudo-aloha Date: Sun, 24 Sep 2023 09:51:31 +0800 Subject: [PATCH 002/307] gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 514e6d7b..d1b17f4d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ /src/lib/*.so /src/lib/lib.d -/src/ext/*.so +src/ext/*.so /engine /include @@ -10,6 +10,7 @@ *.d *.a /gv +/gv.debug /lib btorinfo.log test.btor From 88389b06059ae12ad3f4789e574da77127b4a03f Mon Sep 17 00:00:00 2001 From: pseudo-aloha Date: Sun, 24 Sep 2023 10:07:08 +0800 Subject: [PATCH 003/307] gitignore --- src/ext/sim.so | Bin 817752 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 src/ext/sim.so diff --git a/src/ext/sim.so b/src/ext/sim.so deleted file mode 100755 index 89343984f82ce8d79b3ea86ce926fd73a83119d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 817752 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�ZSGzFJ9me7)G$RgZW4SZ_xCaxNMj#a61G@ra9I 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ɧ{{K7xMIETGz-4RVp3z(k?xqoX3T~Ja3Rmt_p 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ࣶPhdy$NeBoX8^w%*HcE(w&Q z4w28Grq{Qep;kT|TWHAJtQHUKMbo%*)dm6_mJqQS1cHX8lvTR3qH0!>A?bS!5c2HC zI}&oEPFXoy%7M*wMMqr1W+p-)mB(i|Mq=?dyJ?`o$qjsxo>2uoH)kLA5b1*}j}LZt zO}L1qh6z+sD-zI;IMzQw+BUKP^=(7mHgI$er&XokITCp5Ak&o9F<6;}&5V?NP-Z|9 z;^%FM-sEmR_c=sIp}&PnWF=&w7@yZhol<2xDD+*a{;@mQ-^*3Xs|Zd-Whr)Rgn2oelofxRT{JPmL=3hF zV{*E#g&bp7rd+^~nDFH%hwSsMf&2{M@41W~5*Djt8<{SU!O5Y7vdh#&QuQxOiwS~Na_cciX-uip=IrV$jV~R6oy86?uA_|3QroFjOc3YcEbjXpp7F-0Q{od}w)A8ZpEoa#DFKxK22H=ExrCzD9Psa2&J#ugK zI=L10VFK%4l{6iLx$X5XmLLeanO->k6~q^3pe~NMyFf~AO4~!2x@0P&#SpTy$wlo9evOY9bRWxE*=tT{B9IU*Q|D z5^c?(Y{x*umg#Eex-T?%c>mZPwVV_E4xys<2)t5n8XIo4$*4+*Tva@20fI`MU zl@H999-5%T>M1-JA?#d&QD?)t_LUzZ@slV-8cr;+AT|NQ8DzAyf#So-atlUl8w5jz zOzQBcLMh#hElLH%~-S3U3Mfm@1rv^L50O}jqJ&261{;v7#;L>AevH zud?x4yaZxjhx^0lnC!7(-z}!0Ngo+#D6cxeoP{#LEuj)Fq3ij$E6G0VkNL!Vj+YD|bh?B9`}y z&~i)sB6$}`m{$sKt#&SQqO!s0+~g|yh+pfX^w##!*NaO;8rdjsV)5o#%>pE`si0UP znu0BfCqQe6)EJ>M$r*`_7*05oQZ^_;GiBAe7Bt+p%1Wyp-CM*ZxN@oxgzRRm#?hsq zi?U`Kfv6><&m?)1GZ+R|y(i^GICq`-m zT3LKA!Ihk>SRo#ojmNsN@tmX-dX3iX`mHlCu5OP<&@G(?9LNt>a;>3tHuTVo`kro) zuUU*HpW`jQ-WfbcszG;pQ(|&)7!v%uLe`>_Brrbaq5>2Qae=R*M!)f*s>Fk+9G9F^ zCI65ha!VX)#5L7N6vT}_5-lsqBsPgH4b%;{Kd zrSyYHZM8OoJZU(Vjf_0o+WNqS#pDP()PpAGF-RbS^^&H?O*b=engvW+Q zJsl&j9>TP)_qVtun>I%T5swB6k_{m^Z(3^eb8wS4)Tv25GXJr=#;z|d8j*6RQZC)p zY)`z2BIB$TxwpRO*JSCH*GsVA+0xb+@d9tGR6z0`+;jtuDay95I%vygbA5+1hx?>l z4YtmJ=LjiM?q0b*1lP2QMbsuKsWUjCbG{X-&LQ2fYKT$(LyD&f?k{?d31+N0C1PyC z7A4h2EuL+;L8YGHLX-m}rK>z9SWuxF4&v(~gklYiEKslnuBP!GdSz*_8CUFnQ&Px* z(%kfxPt1@feTWb>o}>I)i&{Z@aEZ1ihm`pjqWBJ|n8*+nR$JKLbllqWB*ku-=(OhN z1l_D*wWBg^gH@l(IhTTDdlxP5mFcxxBZ`)QjY>kE;K4r}i9)gZ7{D-!KGlk>3F9!V zI;z+fVUYhab*N_WqeE|tL*Q;yLVX`*QY2cfN!gvIT#A8j8f&}-hxSEp);PO; zxq#5% zN+F=RIY3zyllf#fDup0^(K-Buv8_%i(PI5r`4xd6rv$!~)v&xAXj619dFiJltRR6Y z_rca+OT`@$yVeCD!WxRv!?Le{=j<9NwzpvtaiQk+omZ-8ypK(1B>qz!p%BdnL4;ha5-ol56hdAL>K6lHx0wgn8=6iDW;Eu%7hcZa!?kQ40I(#z8Xbzz4F7@R0f9kk(U@(xb)z$!bWy0I+efBAXJ>b`NgBqM z*3<>l6V4@v+Lrg7cl~wo!Ikb_lQ`tU={WkOr(>54l$515v3&)+p^y|%9ST--br_w@ zL>3rYr@`JPmP=A?Vxm?ltY;b&T98e?m_2vTQpx+5%iFL6R^dQOg3KnFIsx8Y)4e|3 z+~sHmwQLswIi=PrbA*GNfz##GVXK7J?2`2xlyplpXP(=z5;m>}9~Rd%$=>WVL`-J` z3zqt${-i%SaLp`EDB{2r2O>zfC4|I!cw(^)toDtEJ6ETBqe<}foc9I^SE6hk3*Rin z?Vjyk-ponIWkO~RbEZTjmrw>W6c-+NmXj|kfY|W{1>(RPYUDGrW~{O!S1hwN;PqrC z{Q`9QdIzCx(C!?|$oQ*=UU1?7pzIE(u$!#O!fwT?3diJI?`T?&5EG?MO8Rj+T8M;} zVRcvk<)xMF@qof(T^|H#u@O)tehZ-wk6%69zveyqvl%iI(a-Hlfsz+>mWu!=ZrIA% z8pxQtHekK(`Uti$>JBwV%_~?urlVc9mDweWJ!1vw9+Q$qru1_L!M$O^ripdqEC!i! zT?ez-pob_N;Y5<9Vfj?T`1)(Xzem>3#C54)wsbD^UxQIou&tRwOn~VapoaX{r(w_{ zfSI>G@xq#-ZV`bJ>l~$u8!I!@k>xHKkcNGBK%w3rYssL?OREP+>_aQG?jF3XH>8_; zb9-JBHBJ1^Y6$?(dQ7^wutiH5M!4&|X3W3}$6l%VXUrM}isO+nf%;Z_Km=}z_UcX! zz=;T!!@K*zlz3 zlE(R0mkm!Uz;fdwbq-bZMk+J(I+HQ@FEvm)^E?TN zv~!AA2gjynNAbXWzQkc^4?QF@7UXVVEI;8MXxyw@+I6?LuzKYzlB`o{CnFsfwIQ`p z4kyEXHc%(TzD#Q;8=3J$lQ3>peW0xX>DWz*{a zFp|%41l5ZuYTN4%r#DrtQ~4;RamS;fvb`lu@jO^n(9w3a&suw0v_e|oAr1sR$3a45 zoFOj7N^KfPjlW-#+m)W^KC5t%%|)t+)+vy`GPMA*BsEg^6kVyl+S<-V&BU4?yxr3vl40}`dc$4${$$SLY46nTom%A z#FiF8{wBCH(N%ejU=##rcc~!GW!z_p$eP8@OB4(2fQP%g2zcE^5DN-6@TZ8J4ky(8 zVes5xZ+C0UH@XlYAMPI2@ETMeOHE|x!y$=iB_07X3 ze(YeJQ;=#DL0B2INfyWg=!r!Z?@`7Emnz$suEO?(e)4!$|HhO<{mqBZdO)$IHGtJmYN=;vP;!ZO*~NK^G*^j0Bxj+ zB?vj-p!YnW%wW9EN1d!t3>9ID4?Ge3MZT*AQ6G{ZSvf+Fm=P+_p^P(`Eb08Qfa-Xu z6D6A1HAbbty+g!wVBlom4o^6EsLYj054CdAK8~^hl@FWaQxYD9sY@ERn@P5sKwDO0 zgYWUpjO)vNKIS`Xs*ccpHb)4zcZv_*F$I4>)21V3#S<2a?m_^DQv-5)6A_CfcrYY>n*2lG z_Ok6HDh}u*qClMAXcpjZE7o1;kE68zfNdPQ>CVv+jfB)9f8NBBj+l?yIk)Hj-Y1}@ zP7JZTJ4X4REhg(0hjP#oAz=t*3zQ7-tJHW+wZrghNYss@aDkW9r?n>Taziuun3D$#7vjyaoiCGb&L=t zIOjTc)QUP>O1y5p>6eeQxuw=FCsJ8qUbhtKloY_YOl*4zwb&#P$3j$%m{N-L*s4bT zV+!u(0_4dd80MskOQL;QEVFAhAn!Dug3Tg9@Jf|BJnLC+`wCpDV-`(5IK@lOj1+dF zIa);OU%sl}(7O0>?$TK`d@RDf;^q%5hI+--NSASp3jHRD+^h3bA4R51f*-8Dln)Jx{wcBDA}bfP-1I?mJOHr zw6{-WUjEvaV4p*doU!0qUOwz#SE7GFR=`zTC8?j6n#zFw$#AE8(0LElYC0THR3;r? zkx+T?D&;&gdPg;6KZ2P|xI6dyE-h4s*!F7NJ?Uv{VU8L=CuHK(ADLaC%q*t0rQ*~B z;c1)}{zrPLWl2PYT#Ei0;kUO*{Z45%X6AVgTEO?3nB$yer+R=BQ-bL!i|AXv2${+~ zl{-`_PC#q-<~{9W%PFnsTDuRADz>0EMpT`eNgigCo=t$}<_i`Jxdy)WN0!^jc;5IJWpGu|;)LBmkKTdlgvIw(ee4gYn+_(B+TN~zLt%r4RS1*0KXC z>Hqx^ym8RI5I3I8OmpRpD~e;y4&=b&sx&&?{+gv~>u-fg|9NPxdmF>tn&- zt=bx}ua>N-N-E6pW|&$DzO`oO_3h-*v^|>@wzNdOI(oZ^4+lUZiw8n6Z?u_s4lbj! zTditM2Ps9Ofon#LSw;1b46NPZWYmA~!S40#BjBZk4OsZd%ZF+eh^2QYAX3BkqHU9s z7(@9R((OodE{&NHBBhL1RYA@|<670G>bf|w07WmNB{^S@_&W7Mbw-J_0#ZT|Qc{%L z(RRMVgnl9GIIt3rSQ8Njjnm5UpXOt%0hopzYd0HI)M} zo$3IWpr6c+rZdTE$Jt~u0=9D26nS|?#cfWJ?G90}ycw@h%I*n=Gg0JVv%NDwctMh& z`>-@;C^+Idn*P$AqSKb8w$?ov#H7ZHM!cYUTNix)`2>kW4a(Wup8ArK~> zi;LEMlXRr0T%A5zvpRjut*+7wR%7|2+|r^Mlrl1gA>IPKlx2h8>D)|y5V`WlHlCzBLb#qtGm1*teew|97B%_{gg z366TcfQ+xfc9(70>U6)1J*_56V`+tv&j-_R>$AOUoOE$xG@e`?ZbQ;cLd`m^H-m$0 zpQ=HmLW3WY;4>4;E0}k2ID-6&D4~^gj4rlJF&(Gez!9JZL5b}mY*GrB1J@b|B~x); zM58VUj>I$wVLyLk0*MY)m-@z{=;v2MHt z@2g9Ce{iIQGDqVCd({N^NGHwXmOwmz_hCd*xe%wBB>9|l(J%~y^t)^c6*XBjf_HOf zMJJkigDxriBo{Y$r671~7-=h2FXf7#SHKDrOngKMnu+y_=vflJ0ackeu7(8^W2Wjj zD9~m_3YjLxpXSPaTSKMIYs8K$oei!LEq2(jvxYQ|noLI&WdjN%@uvtq#aeJF1Y)&M zRWNYw>z81D+8Xq)!~XIPN{%H?Mvr0=?UG8CmJSaN2FM$r01To$Ff%w=m#yFh;g9b+ zT+7+yR;U^cNi&|Ot5sbxB&{g-mNS&W&h~RdbR%<7!G4>CM)P)`j3{S`G3LNFJcwOw zYn1gSK_9KbTb>86tSl4>YDGl9fH34ewAa-{{gj;@W6EUEH(@1hCSJqmQxQ%ItGQMa zX1^`4qz13FyOcN6u@l6&EW1xgE9QPQ*nYZR_qoP6Z_yPJv);!Di`P z6hcKvCb7=g92aKJxC{D`lz&`WdnazL#NoXqgvHlcVuKb6s|+Wi=L%i0yD!@Q1=x+K zcerRCHb^F?0i-%sqL%A{lI&(82NMz>9C;=}&pGla?io(*WeM&rfg82-I=2E2mmCS$ zP%y+QZ-Nj}7r>ic%FO&qnR8x$EHqO=Bd zB(x_)31YWNQ9^L@?sT{-I29N9Up@=LjnWtxZPs0$gg<8o^l59J^jJ#$i7dag@@D38 zLU^4DbTSv>;5g1WuSwBO4#&%BaV6*ixcaj=!BwbFFal;3irni z8w)Kv(b6=YG-aBS;P=o&5NO6XyQ-hvszsItc(`~`z)2!iMBo_rA<7t4@HQ2eKDf!| zTVmp5EkHT@qY=VGV8u#0{?3^3S5iuZ!r8{-5qrXohMU9Sf(5-4Qb9us}tmfC`(QdSrC>)lNRg8erY|HNpBBz$?!i}>873~&KMO4 z9=Fj&awB?E5-A%X;S+&$PtgB=mcmxb1VeI7g;HL7J;cgE*Dl&A)t=!rI%Cd=G`N`d z8pC8r%un{aKscLNvOSgc53{knrb3aNNLwDOvMmV%jzP9pf4o7*8P;P#YITni9i-m> zvzwq2sLFR077gicTp-$N0gE8ib6ZF(tfSLWG$P@W+Xo3JF`~&Fjkd0l8K7?=@*sJs z9>8aiT#L@u$EzV4FkD=ZpPIt5N)iT`BS9ij+?;LBr@D2eP8*^AHhf6aNtf!-bRb8d zr0;tqwVFV#QlgG073_r#r5lY>rO#M;1NU}Dxz@qoT$Sl-rnv} z@8+b-S>fuiyQp2c*WY%1whlpD-tP&H6twGb8R|jKO~9=%PlZuc7>i&auc)rB&)fVF z1a%z^#|Z&%j&w>e>a+|ZCn)JgT@I{25oXREl!AtE<=bNU(_E{RvBb8h1jI+zseij$ z{N<4nNeduN(M``#fSwnQ36_nJ(wxWV)dL@HQKgQPW1)_h2iT91352E@x3cy|v%ur% zK89*mYd;F71tNbOdtXK9@QbY6nPQ?i%9Cr8;tG{`y{cfLKZeTY>^8<*F7;UqXk=i& zhCUECCYwSLm|2~2A&#@gKQK>KFLcDiVu6gP9Vao)C@qF&WN|o(LU9FjmDp%(xmhP( z0Ts@nL;GZa&XS~sbx*55tnC!)ixrnq(m9X83&;-J)jGei6C#2 zmpIs7sDuVg%ZG61qd;(PGCjW{rbGKi>$P~lovA^H3NmEk9&_Ta`rnx&ZMjv`#S z#k7m*msbtrWRY{ZG=ohQbkFpiiD!nL$rnGl;DW>8UIB1RC{ac>UAmYgs#8Im*@WPv zxI_sZQ?(^Xg)`a=RwhTi14y4zVx%a6*u@(7+UbA6BV$JN(QY|4g0b zy&}%RAvrH%0<;cjyho?4CCCQ41X>*8<01!sq>gK$HA^Z;!8$oo(H`hML&(O6SoS1z zpdO9eTXsSO9At$2XR;wA-q@9^U+UX}seslFon{j~$SmDVxcB*Qu~XF>Bp|;{AMCDg z!DBR>-sF0I&@HGCpZx9I{uJ^~ssl+9TDCtSyakS`6f1w?W}9Y_(R2Zo`fflQ>=#Xk zqTMnTYD%OLdV|CxCOB!JsskWdwa&&bxoAU#4pe0oC$mDBZV7beh*?`+CV6pB!*q`_ zH)KuR9qvhC3#!g78d5wd(#gYWpf-P`26PqT3~Cz%??)1_t6-j-*m6LC#n52fZa?vG2}Lt2I#bO=}+TCYyzuUo3vKZ>w2JUi$JAO5HNiaeHF@Qtzgv-IVAWSAQo{jUSB$#FHTvdU8*kfpJz# z55MIM1#n7SYQwVwKvn0kR)+I7{0NDr^<|X2PO*1wI;5ZhQKy?3nWQ6(cZRF&Np2IU zB~y(#pNdF18TuR&%t61|D24E~F6`4l7v!8>AB<5{TKB%X4-VpiCR45L9D_idk6DNT za4SiIr__<&G9wb)gr>?_2N+Qxr@E&j(ht%U_yA`Od)3taGNEA zu2z+^*`w~<(MFrqlUClU@;Xifyqi=VNmNcaT$Qv|p*5;pHc-h^4T-Gufj|4aoQb3Oyo0w&|WsoeuULOt2hPBsEp zP|3EI;$T}XI@+OLf?q=vK$P5!~$b5OrpeqnbkZ%jhs|EJ_;XZl= z`8q_21=8zwPV&sdvdNVyhAVLFe$jXbi$|654oXcDXNsr}_`Mw~CTnW;chx<-w>SS3 z33Od5+zPLcAiaQ0o=}vSz}D7UkdIdNh?}V%RH;GadhWkL!ayTn%OBzl1;HFTx~VxG9@?wq1idn%8}$81e61k4EDef1P@Aa)ylcy@XEQ8& zs^Dc7VMa}l_hgAxlSm2OX772TZo*pw$5ALTV;N1J{u8rdI7n+N2T{%)o0Hcx`aCbc z6s)VY7CO_UGO7pyWlZ{2M$*dC*+-|-F_M1J;B0w`CBNyIWRf8LJ+{jAz&UaUYOI>1 zSOZ8V9h=d@qd7ww_)OvkiEzJYe=*@%mjEfe@mBC!T6OWMn!hBS+oj6`umbu#*|RB1 zqf0oWUgm}+IKT)AT6YIXST32lr!TkM@`E^L-5Ym0IXd3f z(T;B#UzYM!hmYy%Zk=49VRsM>-sAP|cC6geoCeI?mgFp3b^?RS#cHit45VgR9}rOjO_7GeKit{;JWr2g`mAe9<+E)d%im8UlWfg#REh1O4ve` z?a62$xiuJWRxm+n`{lBOyY*C5;=B|jC3L}MZEZ8wkMkg^X=@38!Y3HJeD1X z!==y-Wja93=FzyfgN!%>hC(E{XTj>V{n3&3KwY88XEKPwE=YfxR@;dkq=yPpC?3T! zd4M`6w1*0spm%ZV1W&>kTW6)c%&auxrz)k2du>w2F>~QcNhpWs=maO7S6~ zC@pDLCZQSB1CDFh?Pp^#*U8r;!RXN__RrIKi5LeIGdiuJ>_QRb*I;Dz@nDGO zp%7;>Mq87;#80YPcWX97#Ez2coa%3I%Z`Z(XF!l1NjiEa3IiikZUO~faA6F19(H$K zD?CSYQ;3>DtjT9b5b9K#YNvmwRVbJicMe6!F>B(H@ z5i8^{ofPB-5=P_?&_FeaefC*HA*5EJHrX!cq=2NO7qBw!Lv1EvYWA`L<~kCRQxl5F z8j9I+AazC7PuPxI2yBd5kB7!ThEzM2Zj0fXDIG(~jM4|%maxCWY*~**;d>BsM)rCWi1ua^s zoWubOtTL`{5;u++Y>|KAL9XZ?PYH9$N{Dn*bVZb~8labZ)=vv>^xzso`qp;w{Bn04 z)x9@xXKOg-LFxJuq*OHMA(7Uh&&p+3lu@4usfOb&Hzb5mxP7?0>lh_ceu{BlVz#$s zOr0>ev?|k-(nn20Y-R0i6x0f}>VJYW5*l0y1kj2K-pk=lk zIIragR85C!>#+8a5MQQvptMZ_W2Ap#ZN)V{xMy8W7%J(Y>lC)77>h|3J7NDN<5*M{ ztI)6RR-GF0NzQaHEBmG;9u-sFL}Xi6LpCmFJGR$=T^6>OaG^Nu_oj!lmlQ$MtbFl0 zzz^3Dr-~)htAx~sQ#rB(N}$E5(8SVP;sg0|L~3R1o5C^qAmWWOW<+q-`)kYFTZFF| ziEao*&O3whTX;cP0vV;bd>qeUhg=dzl8I zhTK=9zNbc?bsNZhSi5@8Yc_la6{bzFizK~T+L@SSG@RocWR(j}obLMD7n`z&65Uotm zLqw9pzOAXPkf+?%C8=Q+9^NWWde5BdlVJGWehTe+EYr02%ti2Q!`HY>x8w zEUK6^c3iotsY3=Wg}gibS(2rwu*-X-yuWakEb15?ooJNf%xT#}a9)Jit-?y!q#kyj zg?So(JTq9{WW(MzK>UN3GxlWO*mA81!rUXP;Kpm2nw$mmgF=q zRZT2D6NXl*H$9a=M(1d3QeGbEpwuAO^+`^|QN7HG6y2|CxZ|mv>$(y)c@-U{qC#go zY#CzW(Oi7o6YJuM$rqGUj?tyg$1OgQz(0I|ng-Q-9@bud_MT_8Vp(Y;N4lsGH)kz# zi7^3Aq0uJ{fx(kmHzkU4C+)^nkuiE{3As_Mw2s1dT{(TGSk8N#z__D2#gDf4OcY>% zIXsE9$Fx&5TYVXQ$}c#B)XSmuX%WAH*KRo;p7R42cal^RPrz&RV5$R>lwnG~C+d?L zyi@=*;c`HEQlHRcy|)klK9`BdAw&(xW0k@O`H@M`&2&wuIdoBEQ%w%IB5h#%jX{^8 zsD%wcihyMN)%j)PRLEMeOlmXe94yz*9df_-{MpQ)GUvU1X>+FJj82ZtVO<4N$Z>=! zoJYf0z8Xg{Wrw*8b~Ve!Cj5l$x}XV@rJfv7%xo3Db5TOR7zs}QGO~w~a&gX#=RiZ! zrYP%9IsRe|mWgZiT|s6QwMb>Qm?yG6!>ZTMmK`vY1lw}=E13Yc$i zU*?s^`xugly!~DGa&3j=q976&IX%Zqk)G%)j({!@rCB16YuKs;>dOo}c!4@Ip=R^J z%?V7viPa$Y?T9{EeK*VqS}kV8p>JB*vSvX~_Gby5TGP>+%4I+?L}XC@dp1tbL$B?P z7N6ltxhl}4mICiL1^%t?UmsmVBBmBOh3tXN=J@WVW$&LF?(gKhXxLrIscFBm{;_j5 zn;J*xbcq{gj0X@jp6*(Uxdg75<1Z(X0;C3{q`YRqk6TfW*!dG8KehRGVg*ZCrK5AI zR4Q`jB6n1$2sr0p&|#YL?WHB-{E+qu>;P$d*gixGg0qoR-Fnq8LTLjWJheHx5%LC{ zy-JK%i0!jAP(*S{U_7SxR@f~HUm}Z~cdBLEWqC=4^?|l;dmH{9Ng86CPnJ@St}SDB z5h!}{wRqR8+?0<^ z)uIZuScytT?q>!odC!K-)XDm*62#O@&WB!cbdb}0CyG< zEr4#*o~@vV6c|mystQ03wy=FJW9vn<$tFRAv5muLY*q;~!_7W;@v?WM~&CSNKKq7|A@(LRwCMmU{B z$-GFAsOg$uuT(6we>fg@CpY&tMMo*#xTmSkds4uIzQEI%*wypl?@-@hImx{+sZ_lvV zR09gi*+v;%E|d~+1x$oq=VhOa^P`DjNxg6&Ev7seiUiBfWL3uyuS76F2dE+X<#5Yf z4g5mIi)Q|58lMeD#adIKiAcpn9s{^Okg76mzIfGSe5xeg4U5M`8ghm%qN!3VqBN0WYUzmWFo)s>|ccHj@X zTbtdj!#ye*dnC1nV%!Kd|Kj4_IOdEV5h?X5$7mKi;&Ugx>jMqYt>#&qkouCwCQ>W0 zf&zO6R|@zuNi=z;TUqaSceKBA=5U{!2ZOCMU_X$ui}z@!BLk`9#J(&){cg~^J!biM z1U&LYIv1KwqH;Y3dY~2OY_{a)d^3kzLH3b83qpW=SIaBpQO-yTS zbA;J|3B}`_81xvV3{?UFm&YunvdRq|;HmSqS&pmxwu%gm_20)_5~H=2sm|{$y`U$W)>S?BLyiy znzitu{m85ilD75-hQc}_tqclhaWs?sN^!JK_5cwQhnK-)6}$6TN*WdoLRb|lUVm;+ z>v{*xJFbonT@+G+d%~TZV59m$q$3K_nk`TXF{@t2)Gf9ylo5t}R9ALp*3KQ^Gdc`~ zZCy;Z#Z=p*W{3%w95A$(S=bjVrI=CKab3Ux@*0r5TNGQplukClXR!PbB*Vd?Yiklo1F{*zObLrny)=wF z6LAqoh1uOIVk(RG;FXPo0p$SI(2CNEYl<;4LP4iua)UGxZo^)q8%NT$GW82CcA5N< zU=E2~;4IWxi-S1^j^ja=6_T%;0A0zN)`<3%z+C}hJ)E>KqWg#p!f$qFG&IXnb2|2w zJxd*D5=A80vJ(`gG-d-IEMI@+_u4qX*|PJVr$-!M?-ogAo+JXB#fNol+$Mz;`Madm zaMCtR?OjS9l=Giqx^0oLG@Do=F7v070p!ZKVJ+7JLK8eNG40Kw3>Kqg##kyMze&E~ zLW|f8=PKBE8$+b5*HH;~h)XMR^%EknuoON%*xd!GVO>TwPj{_UfehSbcI zy*9WB8yQf|j~RSxWfaR3EET{KGY*R{kffkYXfkV-#tXKZ&<)iSM08tmc?^t$ZS4S7 zdNM+G%3W@`nInoKwM<0_!_qk)8uxXB@kqJ7KaArMHoFPf+cG&(wp$#KpUb^sE)bWO zM=m15KiWZ$@g?kSPR7#_?710Gc1NEPVVZdVOmWtz)HqC-QkykTlQLhc?HDO`aq_<$ zOP`S1LQPNk_{39^X+O zHpg^wE@X*~gF%03WjaD3*qu!@d!;FpNJQ=m*y4}I=<=w>cw!qxqj^7K>3S?Bw1-we z>_VOCwOfj(*)FI76PBdvX=*hORvIMUi2@^_oK7J_bhmqbYN<`td*K(}Cn3-MSqP5J zooWey6%Vy(FIID;rp}IbNVBoJ71NOuT$RaJ9Qmwit5#DBiyWW$tPmurdkUErN zz7z-9B%U&*FnKPNWgS1|hIfXAsi-z{eYlvLW@(sJvy>hmDg|dI4IJ2*y zX*!pXAcLj30-XVK(>*>WPL`F6w5CZX6{s1LRgdzWDBV1P#;_7CCK*l@3 zirtQBU}l_fv3`n0a#Qt zNC;YO)tpiTnw4TS$Iq68-m8G=p|^Jr`;fLUl#4SH$M}e0)thWMSh?f--g7bx8YUn0 z##=t?uRHDSIGZe2iD=X0-o^DH#BbISG?KdYr|*^0%^nnLr5nhnRf+ypqPDu*3yDdj zRKOADGO)^I7NJ=R>V%SvKVH6ZC+KmfJy?{9(0wPT?GGS3K!WI#>iuwKET-Q_CFV_h zKT@iKLD1^EZpmUFl6XSH4^!^pXxwQ5gu^WLr1MVMPh81V`7>vO{crqj}3L|Q3QEzObk?OsB{SLXUx}$@%sj~B?z6lg2 zX%}G1Ok|nmUxuSS-sbILTOu(as?W0t8YSV(fcv)RBZ?y-j$lq+{Vr&wHFSHm59oE3 z^PWN2M%q}7AuLk%XnmV<|1(KZYrvS%H0w| z))1WtqAN_ADh9EcEVgKJyqJ;eGtq^^wc%QW%C2URymF8tOKVy~@hnM=9@5-{E^lf% za~)@fs7hVK&uKOgjuRVPCk{~2lSqMFTAKF8MB}J*l+#rM3O3hkf-l$gvx?)Eh9siHSki z;!K}ZZqE=u>cU+d_Y z*I}X@sAAU)CMO)VbbT;Jx{_B(yWO4rLn?Ci&_l(9Tc?UfJWUnG*mW2^QWjwpJ%lbz z^#5ob@fs`2xz&2Yd6}^D8+4S7k`(dSYN0kPHaaTLSR(^8*WXLal&F`~$6ArhqBmWf zln(ipGqDy=PpTG55Vf-}V{@HNxah1BShLN(4H3D0z#_}(DeD10?X2*34k8K-TThE9r?Pot;_%jw4y~DLa>Eb9s+>DdDU@Pr%}; z;v9t{a^>ICVmjU!bwYt`iD{`ZM`_}4H6l64kdes|%EdA{Zf0yyF@`8-K(3kVpv>sk zR&X+*Yk1%6GX^SDlbfx8E65JXUF3h6z|{;%As?0%%j1FaTRv5TAw>Hfm17^1`6g?1 z?QI;KwBH}?9rRF7HnMX#KB4EpS?;som&g;|H?^{k9dcV%cOF{ZufVbzq$jtB*Ik5Ju5lTF72woUPQKaTGvOAL_A$>d&#nyAEWHd#SH!CzcmQ z6w?fs8r-Fz9}e9kcx!GgYeLVAvtWi5x3!Hs{1)l0D*hmU{>q60Rlx*Sym7u6TPhVE z%V=2Od(9{qK<-frM%O^CmO@S@y@a^~5HS`J&fl286tE91-j$IGsA?5Jx98qc+-^Fk z2#NqB@PO`McR1ljuBPOn&_6Gs8|c&cRE5bz3KR7H*KMvWAw^c{4!<{ z;{q)p(gXV}8|=6_@q2=tiXN8$49L>eaNs7OaL@{$V$BVzYgAD|>tWT=&s3W}(JgU? zsTr`Kt>zvHd^n=%PH%6o=cJTS=s0!k~y3ZCVgLR~cW)g&|2c zOr2s>H;4N@P{(aoY$dV7!5)DwHypNS<;ci4>0*Y}bhH z*&0s4AbYzHZ})a519$%2F8uie=uU&Jx16Dkm!gFdFjE&-Tgid^glf%d&iLSX9q}J7 za;KU~Sa=DYRLULXuG&wsB@dOL&`Bwf29<~uj#Phcvd;siFD|7qPwPC#JHc(k9#M8N z%XC>TCqTODQYl%lpm9bmfIdo9hMnY8ihU={j8t|C`0A^WO9&b9aq1OOA@Z;nJ|mUY_>MwI1pico=CGs*P8FYI}VIo~6+GHNA6 z?XZOHuAsra!(F5q92}5Fql5$n`UW@p12lUW?Ng@O(z)nTrboI{_mE2WqR7f*dTv<+ z@xm@849gJ%tz9PF){+2FB(QFc_FU^;?}?KzP-0CssFSXJ$y?923bXLLR&iGCN)4zN zvsPYEI|WIQsmqLY2!dc^u`fX{J!Z>q+RDmQ7*G#6R7_#f7|gp^M@3GWl1?~v5vmP` zo8#aSlRfC|(G6(^g?jiTXb3sOO3y_KQ7%Vd?ZL^_(GhwI-XyJ#g*Rn^Eq34-_~mM` z@$NUIXti`RNj<_w#Qx_ND{CL$6uxC0^+vADhq6S>Itp{2Ugg4(uyG)8qm$YRAFlL_ zb6|Jk*J`&++{ZjZVz|dI+NELQjbt&l(%xz2QW!6DeG6 z?Vz#XgL<8{Q8yyl{BgwrP!X9W>shuM|lkxL-#vS zKWpkq`Th(Bm4>nVO$13>7)zSvEJ4CDy>d|67#1U@WM*q~I9DU#LJv16i2{wlA+GO* zl9p)oP39)0apm0$K8pzokZLwMo?gN9yRxUFnd=w#uB7}mX zwAH7`Ii9MI(vRWRO= zB7)d#780qX+>YIqlG__?9U@Q}rT(%~Wck2F&j~s`lzC2E#WW+QE3JwsobsHg?p4BN zoT0s7g~(-Pa*&GD?M+5;icD)jFDn{uSeQm|Akf@3^(5dqDL5EJ z2;*L15#ku4rx$u?ze>cf)C|g1>l@2tvkzP=sLejKk=_C}rl;gUD6d(z5k*?0cNwQW zaK+6?aCBAdg-!+W0fpHBg$KEtH7gn3K;T|PY6$m58WUjI*yU#`NTawDjuG@v$;{f8=jCk~o=f4c z7w)4oG7+KKCB_oJm%h|i)x@b}YSvJgF_o$5j>O(TbwrSeH%ni+N@@+}wAY#3oFLWC zwYSlTd*)e&=%*;;2%Vyk9#$h)K=6|^x2e`zAk6NuG9p!eiYtgvPI;{nNAO0*Ts5@8 zd1=s1%-6zJROF-$o+I^7?5hcXi$}9ouZr;m9ZdW}Lh+qKp<1>V9ZMb~Ph_0EX6+Ov zG(SgOAdrxmjMfpT3zo}lUNwKd4kgCjqT4g|qzXB8qeCi~)-rqe;WN^U(v<07B%%ct z;v#i3qHF}+ve>yBJyOQbqKB9fv;2bcFs?Nx`8GMbS|m!~>K>>Fr4Ws3dd{h<&TZ^j zpC^&-s~M@VCc#sqZ$np=1e3}}uJOf*o*7j>84vG!<)PbE@3zD-GeyMsMMEBR>Xw#+)S zeLlbc7SBDTFCW7V*4~)COl=vJ6a=@4xGxMlt2ZwYbEB|?3;l7N;gI)$T#PEoM==5B zvn{~0t&=8{bC#18-lBE|w)zo_DSxeRlAuo}kja)81DO*5X&5G4)mP#v_; z95`o+i?&HOJFpikuCo=yM#W6WhwyiZvxJM^aG4qD3H|IQ;>-pEu6)FPH|4=vv)%mi z$i2}h#MAc&lf(X1SB2(t>xiQ8_)FZ3jEliHMm*9hrQ4g>jy%^CoCwN@RG*}ySK-A8 zY8)fr^?Pp&pg%HoH6)@yaxOtO_R5P|X2oZmE^9301en2)b#1%at4yWVFXjMU}x}A-`Pa>=bkDAzh3Xuy+ zs%AvH;Ma$RXvJx~5!@*)s@k4ZS>!jH*_h zp?DM4HV{21OV;ynMQMUz3=k71)sRD(cS&C*{F^17>yYE@zGS4K1sN+$7e`XfRSt+y_2rqm8;^b?8KA>e1HM4ygFwH`=I-)(Pyd;ws$c-q|K&t|%z_QWX-x)}OYK_X)eUA_% z6BJ{_d7O!A5-FA)7aG*y+xmbdjBSl7b#e<%$l#-GaX1m$l}k9AY1O-6`5hxXYchSf zJj7qI>9gdp&k3&^+`?2OTClkG3P{ptGVQ=1f>=F=&v%?eI; zRba97GlCX!nFO~Pp%eEfmIfbOf3K=XO~#^DS(St`Qw*pFD5whN&8?xWw8LLY%#3)d)}F&iAov#zc;pBg5DJvvS_ zh`zA`vErAu6mtO(URWe(E$(yu;z00PIpb~7gfw!+?O+yY%~|KH6gK0>H7=*X^ehgR z0#B8*b7Q)C_2$87I$$vq6d+LoPL|fDW_rh=(&K2YudRW4BovUyNlaiUYNcu`(#bed zmN~Yf^bSVdx#M1 zKGMZ}F|-rP!@_h)*HJ9k=E5FEJjeSj6lHWc5OsyAr(7O;M3~hUjd;DlLU^lB6kX1-PV1_{mX}(Qh1b zRbIaq8lc@;`}05h+5LUsz+v9b_vGOFokSu~th>&UOKhYb+s&SK4fOjl`%& ztkRJ=;>f6+#1Bfmde2}Q{^GH&_Of_8mHGDPeGiVo7f*3iVz66H$94q8Grg+wo^{CrS* ziXZp65BP9y5D0Tkn2KR}JSWHJWJF=aeiOXl3n?%8WEIo(v3$iv*yO4gM|fX_A7RSX zs>=wW&7V@MNgQuspC}8Du+Mm^knUOxY*nWn)q75aGS~JYU{hOX7_}67GV~NGBLV^q zI!lt!Ir+V)24j9n-wz27D4wtbFmGwqK_gQ&)6x(m5NG6i;9LX1!lz>+xQw?FfhXC8m^o0pc(EG^x?a{t*g z_w7v&_Xls?8SEpiu8+&!xPSGnH!hyP@BGS{`*wD=HqYF5X>#U17&+hC=NIqWzP$eU znftbTRKxk|c(gw{oZNS~4_#>MzG-h0F`D>sGDUXYeFtNhx~Y&DUdMww{)awt$FAzn zC`^YR`rGE3HOCf&)5z61ZN<}sXGR=?Ol8iB`Q#i4bP>|s<=(ir$H| z9YG{q$NE!cat>igsZ+FneN!xEhB~VFAauZ2Y*wR45+3Q5kR=c@Rk`x-%iZlyQs&CiA|#wwTj@O0mTwB?~7k$^3~JNJDDISVOM<5CcRgKKic$x zzh#0zY=wSyCK!OMm&6G+iD+9HF(}F>vq<^|x#YCD0Y|n$9pV^g3k||kLY88kv%6$^ zIg(I81Hy8to+jo>EXy<|Y1hF)AV=dW69FM5UO8xKmqdf8*#0#&-6vnmizB8ILp8+B zLYCG*bJh@|y#Xm5H6BMt(lealGVHU`$$YvFMGdtw$-wMPR6R6qEJ!x`!4krZGYgts zm}Uuh^~sf&P3O$#UxK?3EFPQ0QQhuw4PO~B^xQ@XJyCTO}Uv>VQkIV*=F z3qB{IaE`WO*DQ1Z0cNod>dke;FA{Sd)G4@{Le@Z;j@o7nCt6ubnpi3OYoTvLA#65z zb|#V#hSxN^0)D0d!OV1Kw^pfe>-6}DE_!J^Z;tWS7%N{E4I;o+32`Q0p%2q`@aM^L zdtuARP z98XZ>WqJ$Bj~9FEX2wIF69*$3loO0aP4 z$$8>dPrHaRhit1{XCAFVf@}TjfhSo%aw7hhKuTV&o*~M(MQjK{;OW$E6)913U6AS8 z6O-Z?vyhYGDD2&U;f=z-_6Ju-0y7D|IG&a9P8MaLD69H>Syr`y$~w;CfxIA^&B)+v zL^aq|>ei_mRSi`LH7l;%$dE%JZ|#J@HsKvK@apZND!C+Jv1HKcz5`j^l2v-v$1Nlg(cJLM<&7$(4^7muWeE5n z{xuo*Lw!Whvm|^qt~25pI)Oo=nJM=82{||6(_A3>O^wm}I78QB{c#2_b#*$Nn1NyD zBO8Ms*D5d(Y!w6ISTI%lLLy}=5y{$;)VB(vQ)0=7Wa%yWMchrO;q04HBhsk!AP6s| z!3vmHZ#)DyZk4#=oAxxNg!sU6SJ{1*5>hQjn{K7(Ig30>yF!M&C1U8#BB&&TO=n_d zJ+VW|L#$OC{c7^x%tHE0#jTKvO~LcxIDOkBNAr;WarA{FB1~pN{mdnFbKI zY?9$LsO zcS{bu=Oh_KVQ^L4YW3}Bo;>WimyK(yTIqe!coQ(qKZ0_VW?qZDf@Y$$_2 z5w4$zBE}r&eHkXPhJr_)<_xEz*WX(i5n<(Pe6-#v<^zFD*ElCAG1FxIQ$@wtyqJ<1 z#|BS^+5tm+$ImJ*O;gHK-GXw$TuM`;i_&^p?g`bF*oa0#!U<+To}<(eUjob-J{zu} zLCkw7o_h}IkC`G?v|)yb=M;wgZ1V0?r-!fNV?|#o9HM4B27GWeq3d zVCxK?J4C?&u2+&>fbe(S13f=I_sF5c7+*vSxpHOB>H=$+!RDZ1eN^->@=h2=HX5Z zSC#rA-iEl~G|k@n&?o2u=%p$lN22#fJp>l^2lQ|kFst_`~wVm#fA9hxQDMxoAE^kYE$yH9JJ50 zJ#zMs*U-_@LuoH_Y4zn)`HsoImk9Hg$5`LCT3d2hdut53zCV0olUKBG`c#@B80m&! zX7w?mPl&(6Ku-?X+@Z=>t)I{bM_NCER?;d5isNZ(kreFXau7B3l&E2w*1c@@o)FU&ittqmEr%E26f5=t z{i1(y5>$I%ZCNa_Q%?O7G-pF>0FNXtmKjGWXwx%}LrziW;87ExZg8-{$bggaV zIi#bM%5YRltmH9a_iePNY&Pr!+~18WftUwf*TRTcd4~`P6zdff_<~`s%MjP(9}aOf z%gShBdut%g6fC15GF1DsAkRA+8)*1Oi0!#Ngf52v|Ev~B24ya~RibIHx+1*I;(bq$ z+r>hxWmGx7phxX!3o!oitB3p7Z0A{1Y=Dz?AhGY9;r~G(KrHjsge=7eNO4?{>kvp) z;WH?;Cn+uBPU19+yo{c=Sp<_!(Q4tns|PNKs^P$d3?5cyd`JB!v-;#gy6Ppqa!F3o^LxO=-tJ#;Q) z6}`@C%UgkCQE}Ylwnz4bIQ@oHL1_iS-Kkx<6EnkEj|VepT7xM)8C3DzMNEAQ+@<69 z>2O8NRU?hVvP|AqM4^?7sjY)~3JyN-qv&zNWnFBY>J^0-Jl`xO>nynmR5$5(MpGo~ zv97R|fvak{_w0r=EGLHLMOi1{uG6r!EO%|~+y&_?MT`^fg=r5()5iGg;HEerr~*F1 zu86upirOBJ_NZwh6;9#ZOw5pqOck=2h(NK;>G8qtF74~(5wgkC4vZ~eh$&jR%{s_! z>zBGmV^q*)l963W33XP?4AdFlY~?P7QOJ=iD&7?JFDr*NC!^`t6}k!1LbM{MAO!<5 z0RWjDo5Pi>@zb`77tt$6#mS0Z#9fJx>A4D`fFudT0oble5iKc3zj?Twtw;ah0j1|` z_lCRdVnEO?`ZAz?H_lD}W?8c#+p8fo7hJ7f;pdcdOgx=5eni>qBr)TSp@e|MXy&yC zNA%o_(=fxq3$l$hL$9C=lPtv6V>>|v3D^N?UHvdY?sD>IW=>;J?6Ef<8$OehLBWoL z-a^gj*8#K04AZhu$)PC+bfTSMfDu^HD%Pla!+1cxN9Pv`Uy6vkVvA1QM$c56jr7eN zP{r8 zL4*6-EmMYIlrmGu?JejGY8NP17)nS>QEucoaQj8#AoyTD1)d95G%-xZJ(@j4#kYz4 z2yTlqbN&e^1Uvhv)yI`!S+R(;V}(R6gkW@{7Hn-MFTurr53QbuQi>)clzSQbIC2lz zCq-cZppYh0c>tIJ`pHLI=k-9(=n4?vCt0cpv=t3aQgH!9jauu&D?D9TLU1#CTqTcT zxPKk8%2u~G-Z`YU#sn8uUC;4pwH5hQxvkHcBZ{F5-uV=E$r=VVrmbDBQA{p|_OyTF#?sQ#vezo0r{+`&Yyeui zX~lb(bX<7J3Hb+1kPD&cI&7ipR(I^}X{uvK$?H4QtDQ_sVK0xw5DN<~6tlc_wCQXbewvSF4!{FYd_ zNQ2(8A`Nm>YE#Lm25F61Jh*>{6L_3)YDAdLPGsbq2!VC&O&i%XJaV?0L~;S?RMdXi zl_B;jF>#rUu2{l4mCQi?m>@qz?2>_kH6|;}M#KDSOde!PYp)qqYi@}c5{y5!dOR6m zLV`e8yvx`QrQT3^YYH2~=zy$kK9nxJkOc(VVN%95huX#5c!j(17L$3x8((WSm`oFF z9X-it;0q}4>hJU(VL|n`Z5Wi-6$Nky#aE)?Ob9f#V4pBCylx{ z3K89K8fb*1Z_RmWgY@=|DRRs*sjAK;0r~x;=0yS5hX+Wx?QV_^k&1E|V;iPM{XrS< z_`d%rGQ+mSq6!*8 z2MJg@uI)Q|D(9F*QzwiknJ*6e^BO@rd96KRg``Q5G>G;Uf|=+3UTCh?j9QU&m2nfE z#*`WBXkssntNj|jTO)zERpd0G6>G<;5=fTLMlvo1B<&B5LS(ywj0bD_sNQtsO##wt z|LP`hO*>l*{y3Kw^gVcM5oz|JnaV2Zs}^ZH2guZq3d9stpAyzLLkecYtiyl`UM<%Y z#JqQ|L~4p{aVx3}d7@zrJVo#@PBAjik*G(0&PdcNgA|7)YMyMVp{n-<_*jg5q#%N< zv{%BwRP7hyu>#_Oz>(ghDs1F01GAP;nnb*GqF;gd)S66E52lK**qpwDhy?e8fnP#} zebeYA(<45P77yS8BY?amX1S)ue&;3<1;rYdO;~717Z8ZQ3?Rv)Y$UQ&k&mZGY05xerfE0EEQG8$6E78I z1xmmxG1yfJbmr8orXqHZ2F;K;mj+3(e8h2STS#mpxkP1>GMea+_tuHIK)FjkAy;P+ z@Hoig*t)Z!B+vR&duP$GLH0e#%zJ7RE@7dZibXnbN+c7Kug2k8;3tzLd#PKM2X?Vx zREL2pH6mFUg%e$j|E!W!Yq7b|70x+}QlYVuZmR$sMHG=gY%PxI5se|StsEm&GwhPr z5UDB^w)3bzo{sjo=muHZYRD#80sA+4-NB9iAef6G)gIrXP(_HmEOaKwR7uT-lLXO= z2crXoXKGz;%hD2i4Wg|xS$W33)6TC_QF3)AJZ6?`{XFNp)E}_7j=uHp90KaDob6tI z+m-I+C$B7ZFH@t#Cl0QFp~I{T$?5VQ#dbeKDJ#9}15u|{m~c=pTwJ-|(voR&?Q1f$ z*V`y3vWuP`Xu36`vWPUFy^w})#PPDw2_p!S3<%1>LNH=Bw|7UQF?qlA?_<&tHe@PV zH_&S{m`F;ls$*?83+I8&!TOx^WjU%IOJD{KMar4FC7w6s2-M`%XYVCZb4 zv|$%;1o-sE6k%}41WElbSOEg@nw%r)Ngx&4C7?BpViB>G(Y|e^7r_~wSPkqO`>t#x zv5iXMsgnAdNV{77pNwBo`J7utdZ`;_b+wEZgf|^5-t82$k0WW8Rt^=|gM8aoTwd*y z@!L}j1(EEe0jJ7fP4ZKu)8w;%qu}x66GGGskSOI~TE0Sv1zatQktZW)LGCUDrgCY4 z#2(umI zv^RL*9fv!k$FC0dA3%>slq~6Aec;()zx(v1jVllATtE8&ifTUqJ-ze5;bi>4aKFEM zxHWhH%{U)eT6$n}IGtpF@Go!`tp_G>We*;>Ihx#@_#v(h#`|aqml-y`hi;(V^DFo5 z4)+gl+=mVYwcnN^U_9>baPxtke*b~O7?`_TO3lY;g%3!_PCL^EZ*`#WNhTy>1@FI# zOUgwi4>MK9!MzD?+VF3FX4kbt#Km~JJKV*;k*zF!XNqGqfdcrM9g;3?0GCb@#b1-@ zuFn(06lQ?ZeSMT? z<7=F^+#k8^-agvGqnwY59q;XS#)F*!@?#HS#6;;EI+tLZM7k=j8CJKrI~s*7(3kM2 zd=H8#_KiM=ih;v>B)$0NHxEbnmtdy1 zNu#>0kP&t*AR(IQXxuxXx2D5AUN~pD%hK56)7ziY7;*=3EhAnSju5f@xKHih4hOVE zT%cPn3i9lAs2$vN+ylJhrdxn>#M4uh(kokqE15eMZdO89el)l80B`~pGzvY1XK^x} zgYiIA{Vg(F;65hbKO7?otWTSQ&A`w2yW3o!RPHHA z3`evEfi7o)q{G2Y_`A2eGeS9mt9ybO8xM6l zw{;df^xrA`-@@}>%71s}J70C@+?l^67cb0z`>7u}Wv)A?<`(tI&iwP=@{KQaP8aTU zPA`7UjfQ7FfM-q>?sVoBKjofTJoVKbT>h%Qf=hhGUg8t>a&949%J{bx?kt2?7EisK z#{Vrp{<~>>dx`PwCC2xcvPO)b+`)iv{4&`jH~;(GWk=?3FEPHooSR!b@89LQJ>uWx zx!Fs+YcKI#eb?+?_4@f z-|!#s4`ATa2OXXUuKB-(*ZHyT!Hn;@ zAM?9oVNt(uH=+E(;=A2LozrJA33H8~f#m+@xvzgYLzuro&jS?wHJ*RTU4HZqF7N92 z%e(n?djr3}^yU6{di-VaWoO>}`Yr+_oq6ZfyE*_PdwJJO%|zaXNf~UH&64!$)5BDh&6kH<~Yn-(Pj=E99pD z-;em0@4|a`eZi@X`7gLf=E8&jcW>g4fW%wh!#Uippt=AQq(>+`>H-_I;#^1$_7x<}EeG2|IY9B^QTWg@xuJ`r~l3Ax#!<|H2-f-|G{a{pFcSL&%Tha-?#j;=lG9b zJO5kf`Hv4=_`8@J9{uGD|MCL8`+r^dxBTyWFMi-6u9FW&pPIYlv-GWBzhmzC4<60` z?j663k?;qN#6Qtc{0EK2e|+fTKf!`Ncm!naoWfGl|2u8&>)*WIgxcc7HpFEALPoDl$y86@8ADF|{2j+fh z4p+Z4_eXT~M{^&Z$JK}De{>#KKRW+=boG1l|DLY?{rtyo!_~)c`-$6d^%J-K+ybtC zZsGSAaP|8O@4FpW@4Njw7jgBSiywkeH2Dik3K`&?*Get;x}>HA32);%{zYg4mt=qb=)W! z(k!dNA5b{6amI)&GsKm8xExEGG* zKg*zuKS~C2i+bV6k60M1C&p;OSqO z2XFetyMO&|{PTa@{Ri~VpWXc#`scrT>EC@R{`u%jzaRgYDKFf9R>!&x#Pf9*@jn;e z0qlOqPoJK@{)umVVg8T5^uu4qf0?(6e=dCbejR5XTx|Z$^Ur_J(F^n6eEI{gl)pak z%I|z7e)!H;e)83FAUD42?8ndYU!-sRf|~(}_z+h7<@~|7o?@}j-1!dNfk^ck z_sYF82qX)=bI<(qzi`BF=^dzLbO)0B=esS--ub6^1|vV|p1EuO`A>fx%Ph$qJo8ca z%uD8<|KQ)`XOcU3=J)j(2*Q}2y~M9~Ey5{`4Gfe0uKv^K#?; z^M7_5Zv5MOK79|}zvnae$o{NYQ#g(UEAdD%aAbm5=B@^^?X{LU-?=nLeD z|KZgieU1F}EwBBckOn&P-@D+xFWBubJ$9Qr4!d9KCJ9`|TnK&49f#d|$Kf*e`(F1} z_6}qB+~Rk-XPk-X!}<#8SaXZ^5(C;xn27WeA{4FbWB%QD(Yy8%@7hb??7@Sw2`?cj zmKGG>z!N{MPk6eM+`%)S2OA;%_mWdx8pB@V*Ng7g+wm*r_f~h=p@-v3%+LOcci-k7 zzFXdXCVtmm;$3@*50T}P{sRGVSpHw?>uxP`i^&}flH9@m>YY1zk1+7p>M*it=?x4L zKLJYd#D6YxaWH_D{iMS}h{&`nzveE(WPdkCQ*2do2j5BVVA$VxZ$U`Ffnwl43&Z?6 z@r}YA43j+LrrKHfyocq_`3_ToA3FtH{?w`W67GNY6@TxQ5#QIBmF8;I~XLn zgE{=qeh%-ZDgC4lBGwOkiP!BVj_&nqvUhBgnp^xQ3Nk{U{H3Q)=8mIJzvN!|E3zj* zMZFWG5540c5z@z}bdp{k@plO8PA~q$x4OfX2iyt&H(q9B;P_Djj=z8R_dzyvPeZPJ zyMKnE;9)txr~c7t`Q!h+``d+z(_a0Sd)6J_|LHE>@!3mkoxQ}nf8gKcZT}PhE*qWf zCEm4{c=vVwVV3gzrQc_B$L;e|?v=m?%pJ!E^iH7qTlyg{3Hm#<&!-kg@dLDt3qSc+ zWjE(LZw4cN^Ix6+1~6c^!3*#6KN70EQXlBB)FyY>>_{kZ=wJA8h~zsuav zUgBMQiFd!sVUe42-(9-(+Dp7^FY)due)lMT*IwdXdx>}7>)-tv+UIZe@A7)>CEm4{ zc=#W=hha6LcR%9a<@MT2ylXG<@YgyRa7v25^x$jmIPm=r_lgi@;@Elzgu{Wa-U;CQ z!}=lrjK4$R>;7B#(4+Df5&p~b^B@afGyjhle-L0W|35DNPYezEY-i!Bc^F*cv!{eE z{BMiD142w(;QwCyf81aHaq+!(@IBh0UvclbL;g*7=?>XmV#Dku-u+$wE^qc9_;-1; z?Iqr|mmtxf(t~n3NoVnYb$8}G@&M!p2!WC*C#=9?b zR!H}*y~Mlr67SkeynAo_uD!&&_7d;fOT7Em_+5Jm9ZfI466bZ}h0g7F_&eA%x^oBM zbwQtErS4mALW6uG`0^d$^*74HcfBlq{iTIFbDhOaH>I=WHL=$+3f7=cuuIBb%M)ab zThM1PDd5`T**VOYJUM^gjSea4gEz6HyZxOG?8i5w8}i7V<`KDbSK-cWw})ZmnU|YS z(L(ICJn_o##9j1+y_P3{RUdKFh0Kb{VgBDA=Kl$qzuv+8Kf&|&H|BBUg%0MQ+`;^l zJD7iR2lLfCpXcW9uVq}!SMTWj{k1%S`Tua3KPHFy|CqZ0we#0${^1VJDY}#gFnfIk zFh{Ro_Q@U0KDh(1`J`@?10#PeqabcW@9^yHwLC#IO=pj(ffdZZMaVORe7gK1cllEB z_JvDGd8Zctn)|gw51(Fq%3nhDw3i#5)3=3R7oY2VedkMFPj2t*UA)@$BY`U0OaAOP z`(OF9f6rg?!{L&D{Q>_gPbyquQiMc$W4?2npV<6uuYl)IZ29H^QqI7X?&d&=FXRh0 z%$rBjG3I$U%>%hHu#-RUXUUWP*Zz{16fXJKKli`#lES51lHMp?Qg{H<`QQy*(iiiE zEGaxvvZU}pZVW8x_4f%RIpBD}U-FW|B`@ho|0^#kT)HLcjd)2g^vEHGpD~$F(1H-N zA`1yW*@e)XbT$j&XZt32^jG^C!6juc83ez{|H{+3zz)sf9rqc#f3|^IK2@s z&VXQefF=p@puZQFB+fYV0H*Wn9t4SGg6G~wM^ioq{Tw}z8v{%FLT|z6CEe>Uc}d}te|^ON z%BK`A-6`pfcu6om3J8XuF_{n28NEzFF#KfChTi0(3qRX8G5!C-&xj|uy3E&ck}cY^+!zL)7XBVmfkDA0C_`ybT44C|F!=8() z2lxcRLl}I*r2`+m5r3PY*?~`Z05br`3>bk60iW=Q-E|tnflqiKHwKpUPCrXt(%=y_$fEstNy>%t_8TRqdf1m_UOu% z9m(=Tmf|FeAHjKWZOO7xz!1rjY%B32iIw0qP7ZopJ&L5O+$$N`<5D|QGM*_gNh!r- zI-RshX(&tsluR5t(*`DZN+uIB!xS`Rrlk~^v>Aplr6F`$-0$E0|2=zG_oztZ%t(9x z@9h8W`*C*9`PYiymz^7kSO)P$^k%+@r3?{yW$K4c7d0Eta-IlXUxcoRyg2_K&NHe| zRgEt~*B4RdB5tKPXKLPZx>P_l4Q)2<^bCw_ZDtW0nHRCni|L{um{Jmwh4*T~%wx>c zv=Mflosr57ngYNxW~73!I%cE+g8ApI94PG?(_@U2ITFk^6_LZ;<2;*ieG$68i06c7_uFu9vUT+`i}a|ESpAC=@1og)FXHac_%64vUpmjG zefc7EeG#u_CgOt%PszTB{!v73BUhN&^a+`o+HM{nB*Mr`hr;BEawR}vtIM1WLTYC#S4 zMV}f1QI90lgn&9gKph}VEvTV>o4Rb-z=uH8rG%OgPzMO81B9ssHPrJyH3XtQmrxS| z>Hq0Rrj(VQN8bUSk0u$!mJ+qpIe$gc|DuL>(ZY4iISF z(PO(GUc^4mqFEiq?zJaE-4~5oRrN{sVN;CRj*Aw(Re}JDJg0L?t_#()C5%Kwo)4i9X_cf<$#us0Nt}nuK!vV=G6K*q$ zJg)g7bbS%S`BtZEk{}|z)CAAI$T@o#E7)r4_mSNFJ}AMv?l(Zd8z5Yl1hs|cQ*-zG z;e?vI-v9x1fFOy2(EhdUTILcSLQwbt0-gZj)SvfLKTo|D9%OYLw&5XA!9A8x69Vc0 z0d;_I>IJnK>vxEkEcKry)P#UKKtLTJOf9I*SfBc$rT#)fO$ew11k?e-)Pfr7xBadK z0%gdhgqjdg2MDMGgsBBJ)bl{)&C{`ulMUA3Y(~|1N=5JvM6I-7E*NxAf~WA6Tj` z2Mqnwj@~q+rX*yM?|$^x}G{xC)39YWdN@* z%(DJQ=>K(1@>yvlU*Bl8POsmhqU4(`rB~PK^-cQboQmGdpAuT9;^BloDtN3YqgqC>o4qt$BN+^qNC9zrTg zHU^d6vCEh1^{$>k#{HtBtk>;_0=Zp954-y{x&!NHWpbyAWLt>RzG|(C_V5M;C9JkV zMY5e^?jy(Ng8Q;%BlnX%8DwXqB43Wc7s@XNe6n96e92yg<@4pJK{sBfqH;(@n|Og+ zk|6sPLYeFvSV~`}D2B3ZCy4&3fM2!@$j4ASu7X6WYOC4`EpdJqEJ2(@X6}6@X3NQHA*USUyjhiLitYuK3QNEzRT|ZF@53z z{p^ZQM*7*CP;n!9YoAiK8il`EZ{49Hc`IM5P5Sy9P=5TLyy+y+R{z42t7=swFV53_ zk~Oc+QTR3MRFo_(+w}M{<##CG=2lE?laU2qEGFyona46{M9#-U`s~NcfJoP^*Nt0M zBulBtLcIzNO_n_=R#zcbFS%IO>iSJ8k|jp!OGsaq_^2zay-vStXE{U-Wjil)k;?k@ zdh@mrQc<#?hwoR>p(Zjq*joY_vG`|x63S8(tI3k%@*c9t z^4hV;JNY$TO8d(7DtgMjl6r?e`CnD~e;U4u9FeyuDWEzePwlhgu2z>b_$=;w8U4e| zA6Mxo8s<@Gjr@k5RuAa2-&%o@$^oV>ZD=-i=Y1Z!vrV6PKBF&Z{u16lbeoWG(>MI* z3jKEN8>m|Hh8Cw4B%6_3c>{}*6J4`Ve$8=xH>3Y|)hnoj*LDhhm99m;cksJDT0OHu ze`@9TR;ox|BTB-e%6`&$%<4UlX7uBkUuE>qYCaAHS=ciQYxT7^sYsU5s0K7)Kx%Pw zwklnPj6U!#i3T!dqrU0yGWs7fFK6_3GUt#7)9&snef?SemCSchm3QwD6;P~GS+PCv znSEKAAYGl6&t^Ae8z4qk7`^EFilcoe(Se z{}AJ1si6fjUFYye{$*-ANde+|5`TothrzR(4Xn1|KH-wEYWDwLxEXb|y6~{|$FS;S zT#S5-+1qNw;2YHij{hdcKW6ZH^`-kQz`?4gfLF?&XMj_D?&QK}8uewy&jt94jK2`z z-v>_dS3&%LV(<;>9LH1m*PuWtTy>)$)@=fwQR~%o;6E+?9maoyf+gq$SEckGfPbad zs+T!`MCm@m)2!yt3u4_7#(%(g4c~qk_zG30Ughd5S{DqyN~sn>toupB)2QAI()AhU ze?18INrN}p3g%Hg4}1&q&9z9r_Z{F3onwj$X4dhr{JFgUMc=x1Wxe@>(6Dz!~Fb33eP$; zgi8F|fmh0h52WB<22SyDql6UQ%F6tGz$@{eO!0pv#sA-@;8&sPQheNC#PQh&yi$4x zfLDsoS>|y=8S{K0#s4o;@Y`#tw_1386nLd@zmMwqttt5JDfnko@aKV3Ifnh)8Vos=^6e1tO66Nf@&BRA51USXh z&6ikrO{OnjyN7KklDq> z@{w|>zi-h@>_5K9Z5$p`nwcFL$qm6Wq!_A;XC`4yu`rd#NxkuKAs(G53=T}h!!v~< z3`Ne)!7AV+EJV)ahjY6s`-tg``govN95@}r0Cn-S8YvFIYTxkebaYOEEVE0)FoJ%?D=30_7`(;JUTZQ-ZGnM$u3v1Qqw(ceLwBUpKV-k8}$;XaBJS2afl`@ORh#!@b6sG7Q?b#|Oy7 zBCJ#zQ;9vM$^~bVb{;(3x4%1X%eCe9SgXRV?bZ}yfvq@JvRvKUUYO2LnL}F0f_fj! zRUQK{30v!y@WhFDcdi|TzM1sj`sf#Kb4SaLesPCh4BTN}Hrt;N|X*k_%bL{a0Efn~M7nGP{F+IQfT*c7LeMwV)c`8`zYVKtY^ z%}-3Ot<@I&QVHoKlmVQSZVpKwD$5||wAo<0j781`u{D#9bwYhdZ0^BMM8eE6BZL6*6yGTsV4s zdSYORkIMyV6qx! z8`AF&GKE<>hc3qR$7nuCq0On^Xx>J1KtC}y5ZC+qfy5(|)cc17<4~=E~(&=bfE*n)wN(`!~wu1=)er z+rD5g4O-)NCb;0_8I!X#)8wpkbLg_+%T0G%JNT&vqa{vMEDnt3>FA=qel$b(AcO}6 zdJO6x7{r4{e9shYoe#%2lmTOF=fUo7Owvt(R-RDrMxEZjXJ~G&)y~gGC(%ix!z#|u zQw;?qJ$898%b9QNP3Dmc3R`k787WF*vophmk4!DMpp6ZG-r&Z2D zWF>$2-Q&Z`c%XwHRBrh66v(VQQ?z&Z{E0Fl#=T;GVt^F**Yw1U%F*Mp%Hd~jw7@?~ z`5~3V3<{!o;LQ~abk4EL<;VC*du$kNA|aTeAwB^%Mru&E4Xb?!w;b}Dcqkg6G*KRa zjeO`AW+(P`i}?tFR;G2 z=l-AYpA7V6zgyf-Y>|+y8^-7Jfxhgsii_p_vMbELXINj#U){;x*?pNBhj)eHKZkpi z|DrGZ#o~U^)1{wb_}>KP>(8CE3gW&X#1?k-heh@6Kp)3JnM>T~h}^pZQT;3KVQay( z4e}=Y>C=-WE!-23`Y-NJ;Rjm*PG9!#&#}JvBQCl`7WY@cC{9vM-X8M^SL96t?RKm1pJ-!i{iu7{I&Ix~ z4qpgFPuxv`zPwj3|B%&?c!v5SUkiQWlJv`a6|b}YqvDa>mO$Rh;fLuI{hI^-k{oew zVg10HT32L5JXRLf`_lAFR^i8M%Ueu9rw*p*zx@YRudty!W}*H)Df*+2Tm4_`TwH&E z^~3zT|0S#c^-dbylS{%EcOpf9bFCdXSGs}0a)_R|XIVc9!T#F5*6M$dU#ye+q9-!m zO*HjaWO2{lVfFt;Dk|Ry^+^u8DC2Wiztw*M`{#7sfWH>}37w38blcTk{Fdv@2dw@} XK?4ZGr# Date: Sun, 24 Sep 2023 10:09:53 +0800 Subject: [PATCH 004/307] gitignore --- .gitignore | 1 + src/abc/.depend.mak | 78 ---------------------------- src/abc/.extheader.mak | 10 ---- src/bdd/.depend.mak | 36 ------------- src/bdd/.extheader.mak | 13 ----- src/cir/.depend.mak | 99 ----------------------------------- src/cir/.extheader.mak | 16 ------ src/cmd/.depend.mak | 5 -- src/cmd/.extheader.mak | 7 --- src/itp/.depend.mak | 108 --------------------------------------- src/itp/.extheader.mak | 13 ----- src/main/.depend.mak | 8 --- src/main/.extheader.mak | 1 - src/mod/.depend.mak | 32 ------------ src/mod/.extheader.mak | 7 --- src/ntk/.depend.mak | 99 ----------------------------------- src/ntk/.extheader.mak | 7 --- src/prove/.depend.mak | 67 ------------------------ src/prove/.extheader.mak | 1 - src/sim/.depend.mak | 34 ------------ src/sim/.extheader.mak | 4 -- src/util/.depend.mak | 3 -- src/util/.extheader.mak | 25 --------- src/vrf/.depend.mak | 29 ----------- src/vrf/.extheader.mak | 4 -- 25 files changed, 1 insertion(+), 706 deletions(-) delete mode 100644 src/abc/.depend.mak delete mode 100644 src/abc/.extheader.mak delete mode 100644 src/bdd/.depend.mak delete mode 100644 src/bdd/.extheader.mak delete mode 100644 src/cir/.depend.mak delete mode 100644 src/cir/.extheader.mak delete mode 100644 src/cmd/.depend.mak delete mode 100644 src/cmd/.extheader.mak delete mode 100644 src/itp/.depend.mak delete mode 100644 src/itp/.extheader.mak delete mode 100644 src/main/.depend.mak delete mode 100644 src/main/.extheader.mak delete mode 100644 src/mod/.depend.mak delete mode 100644 src/mod/.extheader.mak delete mode 100644 src/ntk/.depend.mak delete mode 100644 src/ntk/.extheader.mak delete mode 100644 src/prove/.depend.mak delete mode 100644 src/prove/.extheader.mak delete mode 100644 src/sim/.depend.mak delete mode 100644 src/sim/.extheader.mak delete mode 100644 src/util/.depend.mak delete mode 100644 src/util/.extheader.mak delete mode 100644 src/vrf/.depend.mak delete mode 100644 src/vrf/.extheader.mak diff --git a/.gitignore b/.gitignore index d1b17f4d..ef868a9e 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ test.btor *.btor *.aig .vscode +*.mak diff --git a/src/abc/.depend.mak b/src/abc/.depend.mak deleted file mode 100644 index 3db860d4..00000000 --- a/src/abc/.depend.mak +++ /dev/null @@ -1,78 +0,0 @@ -gvAbcCmd.o: gvAbcCmd.cpp gvAbcCmd.h ../../include/gvCmdMgr.h gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - gvAbcNtk.h ../../include/gvModMgr.h ../../include/gvCmdMgr.h \ - ../../include/gvMsg.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h -gvAbcMgr.o: gvAbcMgr.cpp gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - gvAbcNtk.h ../../include/bdd/cudd/cudd.h ../../include/bdd/mtr/mtr.h \ - ../../include/bdd/epd/epd.h ../../include/sat/cnf/cnf.h \ - ../../include/opt/dar/darInt.h ../../include/opt/dar/dar.h -gvAbcNtk.o: gvAbcNtk.cpp gvAbcNtk.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - ../../include/sat/cnf/cnf.h ../../include/opt/dar/darInt.h \ - ../../include/opt/dar/dar.h gvAbcMgr.h diff --git a/src/abc/.extheader.mak b/src/abc/.extheader.mak deleted file mode 100644 index dce52d3e..00000000 --- a/src/abc/.extheader.mak +++ /dev/null @@ -1,10 +0,0 @@ -abc.d: ../../include/gvAbcCmd.h ../../include/gvAbcMgr.h ../../include/gvAbcNtk.h -../../include/gvAbcCmd.h: gvAbcCmd.h - @rm -f ../../include/gvAbcCmd.h - @ln -fs ../src/abc/gvAbcCmd.h ../../include/gvAbcCmd.h -../../include/gvAbcMgr.h: gvAbcMgr.h - @rm -f ../../include/gvAbcMgr.h - @ln -fs ../src/abc/gvAbcMgr.h ../../include/gvAbcMgr.h -../../include/gvAbcNtk.h: gvAbcNtk.h - @rm -f ../../include/gvAbcNtk.h - @ln -fs ../src/abc/gvAbcNtk.h ../../include/gvAbcNtk.h diff --git a/src/bdd/.depend.mak b/src/bdd/.depend.mak deleted file mode 100644 index 09ce4e74..00000000 --- a/src/bdd/.depend.mak +++ /dev/null @@ -1,36 +0,0 @@ -bddNodeV.o: bddNodeV.cpp bddNodeV.h bddMgrV.h myHash.h -bddMgrV.o: bddMgrV.cpp bddNodeV.h bddMgrV.h myHash.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -bddCmd.o: bddCmd.cpp bddCmd.h ../../include/gvCmdMgr.h bddMgrV.h myHash.h \ - bddNodeV.h ../../include/gvMsg.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/bdd/.extheader.mak b/src/bdd/.extheader.mak deleted file mode 100644 index 7635a409..00000000 --- a/src/bdd/.extheader.mak +++ /dev/null @@ -1,13 +0,0 @@ -bdd.d: ../../include/bddMgrV.h ../../include/bddNodeV.h ../../include/bddCmd.h ../../include/myHash.h -../../include/bddMgrV.h: bddMgrV.h - @rm -f ../../include/bddMgrV.h - @ln -fs ../src/bdd/bddMgrV.h ../../include/bddMgrV.h -../../include/bddNodeV.h: bddNodeV.h - @rm -f ../../include/bddNodeV.h - @ln -fs ../src/bdd/bddNodeV.h ../../include/bddNodeV.h -../../include/bddCmd.h: bddCmd.h - @rm -f ../../include/bddCmd.h - @ln -fs ../src/bdd/bddCmd.h ../../include/bddCmd.h -../../include/myHash.h: myHash.h - @rm -f ../../include/myHash.h - @ln -fs ../src/bdd/myHash.h ../../include/myHash.h diff --git a/src/cir/.depend.mak b/src/cir/.depend.mak deleted file mode 100644 index bb1fc31f..00000000 --- a/src/cir/.depend.mak +++ /dev/null @@ -1,99 +0,0 @@ -cirAig.o: cirAig.cpp cirMgr.h cirDef.h ../../include/myHash.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirGate.h \ - ../../include/sat.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/gvModMgr.h \ - ../../include/gvCmdMgr.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/base/main/main.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/aig/ioa/ioa.h \ - ../../include/gvAbcNtk.h -cirCmd.o: cirCmd.cpp cirMgr.h cirDef.h ../../include/myHash.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirGate.h \ - ../../include/sat.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h cirCmd.h ../../include/gvCmdMgr.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h \ - ../../include/gvMsg.h -cirFraig.o: cirFraig.cpp -cirGate.o: cirGate.cpp cirGate.h cirDef.h ../../include/myHash.h \ - ../../include/sat.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - cirMgr.h ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/vec/vecInt.h ../../include/misc/vec/vecFlt.h \ - ../../include/misc/vec/vecStr.h ../../include/misc/vec/vecPtr.h \ - ../../include/misc/vec/vecVec.h ../../include/misc/vec/vecAtt.h \ - ../../include/misc/vec/vecWrd.h ../../include/misc/vec/vecBit.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/vec/vecWec.h \ - ../../include/aig/hop/hop.h ../../include/aig/gia/gia.h \ - ../../include/misc/vec/vecWec.h ../../include/misc/util/utilCex.h \ - ../../include/misc/st/st.h ../../include/misc/st/stmm.h \ - ../../include/misc/nm/nm.h ../../include/misc/mem/mem.h \ - ../../include/misc/extra/extra.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -cirMgr.o: cirMgr.cpp cirMgr.h cirDef.h ../../include/myHash.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirGate.h \ - ../../include/sat.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -cirOpt.o: cirOpt.cpp cirMgr.h cirDef.h ../../include/myHash.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirGate.h \ - ../../include/sat.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -cirSim.o: cirSim.cpp diff --git a/src/cir/.extheader.mak b/src/cir/.extheader.mak deleted file mode 100644 index 09d0ee5b..00000000 --- a/src/cir/.extheader.mak +++ /dev/null @@ -1,16 +0,0 @@ -cir.d: ../../include/cirCmd.h ../../include/cirDef.h ../../include/cirFraig.h ../../include/cirGate.h ../../include/cirMgr.h -../../include/cirCmd.h: cirCmd.h - @rm -f ../../include/cirCmd.h - @ln -fs ../src/cir/cirCmd.h ../../include/cirCmd.h -../../include/cirDef.h: cirDef.h - @rm -f ../../include/cirDef.h - @ln -fs ../src/cir/cirDef.h ../../include/cirDef.h -../../include/cirFraig.h: cirFraig.h - @rm -f ../../include/cirFraig.h - @ln -fs ../src/cir/cirFraig.h ../../include/cirFraig.h -../../include/cirGate.h: cirGate.h - @rm -f ../../include/cirGate.h - @ln -fs ../src/cir/cirGate.h ../../include/cirGate.h -../../include/cirMgr.h: cirMgr.h - @rm -f ../../include/cirMgr.h - @ln -fs ../src/cir/cirMgr.h ../../include/cirMgr.h diff --git a/src/cmd/.depend.mak b/src/cmd/.depend.mak deleted file mode 100644 index fc75d675..00000000 --- a/src/cmd/.depend.mak +++ /dev/null @@ -1,5 +0,0 @@ -gvCmdComm.o: gvCmdComm.cpp gvCmdComm.h gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/gvUsage.h ../../include/gvMsg.h ../../include/gvIntType.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h -gvCmdMgr.o: gvCmdMgr.cpp gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/cmd/.extheader.mak b/src/cmd/.extheader.mak deleted file mode 100644 index 61bd2bab..00000000 --- a/src/cmd/.extheader.mak +++ /dev/null @@ -1,7 +0,0 @@ -cmd.d: ../../include/gvCmdComm.h ../../include/gvCmdMgr.h -../../include/gvCmdComm.h: gvCmdComm.h - @rm -f ../../include/gvCmdComm.h - @ln -fs ../src/cmd/gvCmdComm.h ../../include/gvCmdComm.h -../../include/gvCmdMgr.h: gvCmdMgr.h - @rm -f ../../include/gvCmdMgr.h - @ln -fs ../src/cmd/gvCmdMgr.h ../../include/gvCmdMgr.h diff --git a/src/itp/.depend.mak b/src/itp/.depend.mak deleted file mode 100644 index 5224f0a4..00000000 --- a/src/itp/.depend.mak +++ /dev/null @@ -1,108 +0,0 @@ -gvSatMgr.o: gvSatMgr.cpp gvSatMgr.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h gvSat.h \ - SolverV.h ProofV.h SolverTypesV.h GlobalV.h FileV.h VarOrderV.h HeapV.h \ - gvBitVec.h ../../include/gvIntType.h reader.h ../../include/gvMsg.h -FileV.o: FileV.cpp FileV.h GlobalV.h -reader.o: reader.cpp reader.h -gvSat.o: gvSat.cpp gvSat.h SolverV.h ProofV.h SolverTypesV.h GlobalV.h \ - FileV.h VarOrderV.h HeapV.h gvBitVec.h ../../include/gvIntType.h \ - ../../include/gvNtk.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h -gvSatCmd.o: gvSatCmd.cpp gvSatCmd.h ../../include/gvCmdMgr.h \ - ../../include/gvMsg.h gvSatMgr.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h gvSat.h \ - SolverV.h ProofV.h SolverTypesV.h GlobalV.h FileV.h VarOrderV.h HeapV.h \ - gvBitVec.h ../../include/gvIntType.h reader.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -gvBitVec.o: gvBitVec.cpp gvBitVec.h ../../include/gvIntType.h \ - ../../include/gmpxx.h ../../include/gmp.h -ProofV.o: ProofV.cpp ProofV.h SolverTypesV.h GlobalV.h FileV.h SortV.h -SolverV.o: SolverV.cpp SolverV.h ProofV.h SolverTypesV.h GlobalV.h \ - FileV.h VarOrderV.h HeapV.h SortV.h diff --git a/src/itp/.extheader.mak b/src/itp/.extheader.mak deleted file mode 100644 index 45cf6833..00000000 --- a/src/itp/.extheader.mak +++ /dev/null @@ -1,13 +0,0 @@ -itp.d: ../../include/gvSat.h ../../include/gvSatMgr.h ../../include/gvSatCmd.h ../../include/VarOrderV.h -../../include/gvSat.h: gvSat.h - @rm -f ../../include/gvSat.h - @ln -fs ../src/itp/gvSat.h ../../include/gvSat.h -../../include/gvSatMgr.h: gvSatMgr.h - @rm -f ../../include/gvSatMgr.h - @ln -fs ../src/itp/gvSatMgr.h ../../include/gvSatMgr.h -../../include/gvSatCmd.h: gvSatCmd.h - @rm -f ../../include/gvSatCmd.h - @ln -fs ../src/itp/gvSatCmd.h ../../include/gvSatCmd.h -../../include/VarOrderV.h: VarOrderV.h - @rm -f ../../include/VarOrderV.h - @ln -fs ../src/itp/VarOrderV.h ../../include/VarOrderV.h diff --git a/src/main/.depend.mak b/src/main/.depend.mak deleted file mode 100644 index b96a8e22..00000000 --- a/src/main/.depend.mak +++ /dev/null @@ -1,8 +0,0 @@ -main.o: main.cpp ../../include/gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/gvUsage.h ../../include/gvMsg.h ../../include/gvIntType.h \ - ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ - /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ - ../../include/kernel/hashlib.h ../../include/kernel/log.h \ - ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ - ../../include/kernel/register.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/main/.extheader.mak b/src/main/.extheader.mak deleted file mode 100644 index 77e70864..00000000 --- a/src/main/.extheader.mak +++ /dev/null @@ -1 +0,0 @@ -.d: diff --git a/src/mod/.depend.mak b/src/mod/.depend.mak deleted file mode 100644 index 787aa841..00000000 --- a/src/mod/.depend.mak +++ /dev/null @@ -1,32 +0,0 @@ -gvModCmd.o: gvModCmd.cpp gvModCmd.h ../../include/gvCmdMgr.h gvModMgr.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/gvMsg.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h -gvModMgr.o: gvModMgr.cpp gvModMgr.h ../../include/gvCmdMgr.h diff --git a/src/mod/.extheader.mak b/src/mod/.extheader.mak deleted file mode 100644 index 57447686..00000000 --- a/src/mod/.extheader.mak +++ /dev/null @@ -1,7 +0,0 @@ -mod.d: ../../include/gvModMgr.h ../../include/gvModCmd.h -../../include/gvModMgr.h: gvModMgr.h - @rm -f ../../include/gvModMgr.h - @ln -fs ../src/mod/gvModMgr.h ../../include/gvModMgr.h -../../include/gvModCmd.h: gvModCmd.h - @rm -f ../../include/gvModCmd.h - @ln -fs ../src/mod/gvModCmd.h ../../include/gvModCmd.h diff --git a/src/ntk/.depend.mak b/src/ntk/.depend.mak deleted file mode 100644 index ea91cf4a..00000000 --- a/src/ntk/.depend.mak +++ /dev/null @@ -1,99 +0,0 @@ -gvNtkBdd.o: gvNtkBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ - ../../include/bddNodeV.h ../../include/bddNodeV.h ../../include/gvMsg.h \ - gvNtk.h ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h -gvNtkCmd.o: gvNtkCmd.cpp gvNtkCmd.h ../../include/gvCmdMgr.h \ - ../../include/gvMsg.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/gvModMgr.h ../../include/gvCmdMgr.h gvNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h -gvNtk.o: gvNtk.cpp gvNtk.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/gvMsg.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/ntk/.extheader.mak b/src/ntk/.extheader.mak deleted file mode 100644 index 81497bb9..00000000 --- a/src/ntk/.extheader.mak +++ /dev/null @@ -1,7 +0,0 @@ -ntk.d: ../../include/gvNtkCmd.h ../../include/gvNtk.h -../../include/gvNtkCmd.h: gvNtkCmd.h - @rm -f ../../include/gvNtkCmd.h - @ln -fs ../src/ntk/gvNtkCmd.h ../../include/gvNtkCmd.h -../../include/gvNtk.h: gvNtk.h - @rm -f ../../include/gvNtk.h - @ln -fs ../src/ntk/gvNtk.h ../../include/gvNtk.h diff --git a/src/prove/.depend.mak b/src/prove/.depend.mak deleted file mode 100644 index 4cd432ae..00000000 --- a/src/prove/.depend.mak +++ /dev/null @@ -1,67 +0,0 @@ -proveBdd.o: proveBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ - ../../include/bddNodeV.h ../../include/gvMsg.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h -proveCmd.o: proveCmd.cpp proveCmd.h ../../include/gvCmdMgr.h \ - ../../include/bddMgrV.h ../../include/myHash.h ../../include/bddNodeV.h \ - ../../include/gvMsg.h ../../include/gvNtk.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/prove/.extheader.mak b/src/prove/.extheader.mak deleted file mode 100644 index c81d4d82..00000000 --- a/src/prove/.extheader.mak +++ /dev/null @@ -1 +0,0 @@ -prove.d: diff --git a/src/sim/.depend.mak b/src/sim/.depend.mak deleted file mode 100644 index 4299e5d4..00000000 --- a/src/sim/.depend.mak +++ /dev/null @@ -1,34 +0,0 @@ -gvSimCmd.o: gvSimCmd.cpp gvSimCmd.h ../../include/gvCmdMgr.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/gvModMgr.h ../../include/gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h \ - ../../include/gvNtk.h ../../include/gvAbcMgr.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h diff --git a/src/sim/.extheader.mak b/src/sim/.extheader.mak deleted file mode 100644 index 133cb45f..00000000 --- a/src/sim/.extheader.mak +++ /dev/null @@ -1,4 +0,0 @@ -sim.d: ../../include/gvSimCmd.h -../../include/gvSimCmd.h: gvSimCmd.h - @rm -f ../../include/gvSimCmd.h - @ln -fs ../src/sim/gvSimCmd.h ../../include/gvSimCmd.h diff --git a/src/util/.depend.mak b/src/util/.depend.mak deleted file mode 100644 index f1a5d6aa..00000000 --- a/src/util/.depend.mak +++ /dev/null @@ -1,3 +0,0 @@ -myGetChar.o: myGetChar.cpp -myString.o: myString.cpp -util.o: util.cpp rnGen.h myUsage.h diff --git a/src/util/.extheader.mak b/src/util/.extheader.mak deleted file mode 100644 index d7d1cbc7..00000000 --- a/src/util/.extheader.mak +++ /dev/null @@ -1,25 +0,0 @@ -util.d: ../../include/gvMsg.h ../../include/gvUsage.h ../../include/gvIntType.h ../../include/myHashMap.h ../../include/myHashSet.h ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h -../../include/gvMsg.h: gvMsg.h - @rm -f ../../include/gvMsg.h - @ln -fs ../src/util/gvMsg.h ../../include/gvMsg.h -../../include/gvUsage.h: gvUsage.h - @rm -f ../../include/gvUsage.h - @ln -fs ../src/util/gvUsage.h ../../include/gvUsage.h -../../include/gvIntType.h: gvIntType.h - @rm -f ../../include/gvIntType.h - @ln -fs ../src/util/gvIntType.h ../../include/gvIntType.h -../../include/myHashMap.h: myHashMap.h - @rm -f ../../include/myHashMap.h - @ln -fs ../src/util/myHashMap.h ../../include/myHashMap.h -../../include/myHashSet.h: myHashSet.h - @rm -f ../../include/myHashSet.h - @ln -fs ../src/util/myHashSet.h ../../include/myHashSet.h -../../include/util.h: util.h - @rm -f ../../include/util.h - @ln -fs ../src/util/util.h ../../include/util.h -../../include/rnGen.h: rnGen.h - @rm -f ../../include/rnGen.h - @ln -fs ../src/util/rnGen.h ../../include/rnGen.h -../../include/myUsage.h: myUsage.h - @rm -f ../../include/myUsage.h - @ln -fs ../src/util/myUsage.h ../../include/myUsage.h diff --git a/src/vrf/.depend.mak b/src/vrf/.depend.mak deleted file mode 100644 index ed12a040..00000000 --- a/src/vrf/.depend.mak +++ /dev/null @@ -1,29 +0,0 @@ -gvVrfCmd.o: gvVrfCmd.cpp gvVrfCmd.h ../../include/gvCmdMgr.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/gvMsg.h ../../include/gvUsage.h ../../include/gvMsg.h \ - ../../include/gvIntType.h ../../include/gvModMgr.h \ - ../../include/gvCmdMgr.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h diff --git a/src/vrf/.extheader.mak b/src/vrf/.extheader.mak deleted file mode 100644 index bc97dd80..00000000 --- a/src/vrf/.extheader.mak +++ /dev/null @@ -1,4 +0,0 @@ -vrf.d: ../../include/gvVrfCmd.h -../../include/gvVrfCmd.h: gvVrfCmd.h - @rm -f ../../include/gvVrfCmd.h - @ln -fs ../src/vrf/gvVrfCmd.h ../../include/gvVrfCmd.h From c486fa48e10735be92ddac9963a6b8e83c432433 Mon Sep 17 00:00:00 2001 From: pseudo-aloha Date: Sun, 24 Sep 2023 10:13:20 +0800 Subject: [PATCH 005/307] gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index ef868a9e..5ad406b6 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ src/ext/*.so *.a /gv /gv.debug +/yosys-abc +/yosys-config /lib btorinfo.log test.btor From 7de3944ebae8fb142e14ab63349a4a631920b6e1 Mon Sep 17 00:00:00 2001 From: hchchiu Date: Tue, 3 Oct 2023 22:56:12 +0800 Subject: [PATCH 006/307] finish bdd structure --- src/abc/gvAbcMgr.h | 1 + src/bdd/bddCmd.cpp | 6 +- src/cir/cirAig.cpp | 80 ++++++++++++++++---- src/cir/cirBdd.cpp | 185 +++++++++++++++++++++++++++++++++++++++++++++ src/cir/cirMgr.cpp | 5 ++ src/cir/cirMgr.h | 5 +- 6 files changed, 262 insertions(+), 20 deletions(-) create mode 100644 src/cir/cirBdd.cpp diff --git a/src/abc/gvAbcMgr.h b/src/abc/gvAbcMgr.h index c8c92e71..7a09bdf0 100644 --- a/src/abc/gvAbcMgr.h +++ b/src/abc/gvAbcMgr.h @@ -22,6 +22,7 @@ extern "C" Abc_Frame_t* Abc_FrameGetGlobalFrame(); int Cmd_CommandExecute(Abc_Frame_t* pAbc, const char* sCommand); Abc_Ntk_t* Abc_FrameReadNtk(Abc_Frame_t* p); + Gia_Man_t* Wln_BlastSystemVerilog(char* pFileName, char* pTopModule, char* pDefines, int fSkipStrash, int fInvert, int fTechMap, int fVerbose); } class AbcMgr diff --git a/src/bdd/bddCmd.cpp b/src/bdd/bddCmd.cpp index ccb94edf..29d362d8 100644 --- a/src/bdd/bddCmd.cpp +++ b/src/bdd/bddCmd.cpp @@ -10,6 +10,7 @@ #include "bddMgrV.h" #include "gvMsg.h" #include "gvNtk.h" +#include "cirMgr.h" #include "util.h" #include #include @@ -731,7 +732,8 @@ BSetOrderCmd::exec(const string& option) { bddMgrV->restart(); // V3NtkHandler* const handler = v3Handler.getCurHandler(); - setBddOrder = gvNtkMgr->setBddOrder(file); + // setBddOrder = gvNtkMgr->setBddOrder(file); + setBddOrder = cirMgr->setBddOrder(file); if (!setBddOrder) gvMsg(GV_MSG_ERR) << "Set BDD Variable Order Failed !!" << endl; else gvMsg(GV_MSG_IFO) << "Set BDD Variable Order Succeed !!" << endl; @@ -766,7 +768,7 @@ BConstructCmd::exec(const string& option) { } bool isNet = false, isOutput = false; - if (myStrNCmp("-All", options[0], 2) == 0) gvNtkMgr->buildNtkBdd(); + if (myStrNCmp("-All", options[0], 2) == 0) cirMgr->buildNtkBdd(); else if (myStrNCmp("-Netid", options[0], 2) == 0) isNet = true; else if (myStrNCmp("-Output", options[0], 2) == 0) isOutput = true; else return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); diff --git a/src/cir/cirAig.cpp b/src/cir/cirAig.cpp index d0441c1e..36197c20 100644 --- a/src/cir/cirAig.cpp +++ b/src/cir/cirAig.cpp @@ -17,14 +17,15 @@ CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { CirGateV gateV; Gia_Man_t* pGia = NULL; // the gia pointer of abc Gia_Obj_t *pObj, *pObjRi, *pObjRo; // the obj element of gia - unsigned iPi = 0, iPo = 0, iRi = 0, iRo = 0; + unsigned iPi = 0, iPpi = 0, iPo = 0, iRi = 0, iRo = 0; + unsigned piNum = 0; + map PPI2RO; // abc function parameters char* pFileName = new char[100]; cout << "filename = " << fileName << endl; strcpy(pFileName, fileName.c_str()); - char* pTopModule = - NULL; // the top module can be auto detected by yosys, no need to set + char* pTopModule = NULL; // the top module can be auto detected by yosys, no need to set char* pDefines = NULL; int fBlast = 1; // blast the ntk to gia (abc's aig data structure) int fInvert = 0; @@ -38,7 +39,11 @@ CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { pGia = Gia_AigerRead(pFileName, 0, fSkipStrash, 0); else if(fileType == VERILOG) { pGia = abcMgr->get_Abc_Frame_t()->pGia; - cout << Gia_ManPoNum(pGia) << endl; + pGia = Wln_BlastSystemVerilog(pFileName,pTopModule,pDefines,fSkipStrash,fInvert,fTechMap,fVerbose); + piNum = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; // PI (PI + PPI) - (REG (PPI + CONST0) - CONST0) + // cout << Gia_ManPiNum(pGia) << endl; + // cout << Gia_ManRegNum(pGia) << endl; + cout << "PI NUM : " << piNum << endl; } // initialize the size of the containers @@ -53,9 +58,18 @@ CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { // traverse the obj's in topological order Gia_ManForEachObj(pGia, pObj, i) { if(Gia_ObjIsPi(pGia, pObj)) { - CirPiGate* gate = new CirPiGate(Gia_ObjId(pGia, pObj), 0); - _piList[iPi++] = gate; - _totGateList[Gia_ObjId(pGia, pObj)] = gate; + int gateId = Gia_ObjId(pGia, pObj); + if(gateId <= piNum){ + CirPiGate* gate = new CirPiGate(Gia_ObjId(pGia, pObj), 0); + _piList[iPi++] = gate; + _totGateList[gateId] = gate; + } + else{ + CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); + _roList[iRo++] = gate; + _totGateList[gateId] = gate; + // cout << "Fanin: " <setIn0(getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); - gate->setIn1(getGate(Gia_ObjId(pGia, Gia_ObjFanin1(pObj))), Gia_ObjFaninC1(pObj)); + int fanin0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + int fanin1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); + if(PPI2RO.count(fanin0)) + fanin0 = PPI2RO[fanin0]; + if(PPI2RO.count(fanin1)) + fanin1 = PPI2RO[fanin1]; + gate->setIn0(getGate(fanin0), Gia_ObjFaninC0(pObj)); + gate->setIn1(getGate(fanin1), Gia_ObjFaninC1(pObj)); } else if(Gia_ObjIsRo(pGia, pObj)) { - CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); - _roList[iRo++] = gate; - _totGateList[Gia_ObjId(pGia, pObj)] = gate; + int gateId = Gia_ObjId(pGia,pObj); + if(iPpi < iRo){ + cout << _roList[iPpi]->getGid() << "<->" << Gia_ObjId(pGia,pObj) << endl; + PPI2RO[gateId] = _roList[iPpi]->getGid(); + } + else{ + cout << Gia_ObjId(pGia, pObj); + PPI2RO[gateId] = 0; + } + iPpi++; + // CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); + // _roList[iRo++] = gate; + // _totGateList[Gia_ObjId(pGia, pObj)] = gate; + // cout << "RO: "<< Gia_ObjId(pGia, pObj) << endl; + // cout << "Fanin: " <setName(n); gate->setIn0(getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); - _riList[iPo++] = gate; + _riList[iRi++] = gate; _totGateList[Gia_ObjId(pGia, pObj)] = gate; + cout << "RI: "<< Gia_ObjId(pGia, pObj) << endl; + cout << "Fanin: " < " << Gia_ObjId(pGia, pObjRi)<< endl; + } - + cout << "PPI to RO: \n"; + Gia_ManForEachRo(pGia, pObj, i) { + // cout << _roList[i]->getGid() << "<->" << Gia_ObjId(pGia,pObj) << endl; + cout << i << "<->" << Gia_ObjId(pGia,pObj) << endl; + } // genConnections(); genDfsList(); // checkFloatList(); @@ -115,11 +162,12 @@ CirMgr::initCir(Gia_Man_t* pGia) { // TODO : Resize the list (PI/PO ...) // Create lists cout << "initializing..." << endl; - _numDecl[PI] = Gia_ManPiNum(pGia); + // _numDecl[PI] = Gia_ManPiNum(pGia); + _numDecl[PI] = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; _piList = new CirPiGate*[_numDecl[PI]]; _numDecl[PO] = Gia_ManPoNum(pGia); _poList = new CirPoGate*[_numDecl[PO]]; - _numDecl[LATCH] = Gia_ManRegNum(pGia); + _numDecl[LATCH] = Gia_ManRegNum(pGia) - 1; _riList = new CirRiGate*[_numDecl[LATCH]]; _roList = new CirRoGate*[_numDecl[LATCH]]; _numDecl[VARS] = Gia_ManObjNum(pGia); diff --git a/src/cir/cirBdd.cpp b/src/cir/cirBdd.cpp new file mode 100644 index 00000000..26ad8f93 --- /dev/null +++ b/src/cir/cirBdd.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** + FileName [ v3NtkBdd.cpp ] + PackageName [ v3/src/ntk ] + Synopsis [ V3 Network to BDDs. ] + Author [ Cheng-Yin Wu ] + Copyright [ Copyright(c) 2012-present LaDs(III), GIEE, NTU, Taiwan ] +****************************************************************************/ + +#ifndef V3_NTK_C +#define V3_NTK_C + +#include "bddMgrV.h" // MODIFICATION FOR SoCV BDD +#include "bddNodeV.h" // MODIFICATION FOR SoCV BDD +#include "gvMsg.h" +#include "stack" +#include "util.h" +#include "cirMgr.h" +#include "cirGate.h" + +extern BddMgrV* bddMgrV; // MODIFICATION FOR SoCV BDD + +const bool +CirMgr::setBddOrder(const bool& file) { + unsigned supportSize = getNumPIs() + 2 * getNumLATCHs(); + unsigned bddspsize = bddMgrV->getNumSupports(); + if (supportSize >= bddMgrV->getNumSupports()) { + gvMsg(GV_MSG_ERR) << "BDD Support Size is Smaller Than Current Design Required !!" << endl; + return false; + } + // build support + unsigned supportId = 1; + // build PI (primary input) + for (unsigned i = 0, n = getNumPIs(); i < n; ++i) { + CirPiGate* gate = (file) ? getPi(i) : getPi(n - i - 1); + // string netName = getNetNameFromId(nId.id); + bddMgrV->addBddNodeV(gate->getGid(), bddMgrV->getSupport(supportId)()); + // bddMgrV->addBddNodeV(gate->getName(), bddMgrV->getSupport(supportId)()); + // cout << " Name : " << netName << "-> Id : " << nId.id << endl; + // cout << "Support Id : " << supportId << "\n\n"; + // cout << " --- \n"; + cout << "PI: " << gate->getGid() << endl; + ++supportId; + } + // build InOut (Not use) + // for (unsigned i = 0, n = getInoutSize(); i < n; ++i) { + // const GVNetId& nId = (file) ? getInout(i) : getInout(n - i - 1); + // string netName = getNetNameFromId(nId.id); + // bddMgrV->addBddNodeV(nId.id, bddMgrV->getSupport(supportId)()); + // bddMgrV->addBddNodeV(netName, bddMgrV->getSupport(supportId)()); + // ++supportId; + // } + // build FF_CS (X: current state) + for (unsigned i = 0, n = getNumLATCHs(); i < n; ++i) { + CirRoGate* gate = (file) ? getRo(i) : getRo(n - i - 1); + // string netName = getNetNameFromId(nId.id); + bddMgrV->addBddNodeV(gate->getGid(), bddMgrV->getSupport(supportId)()); + // bddMgrV->addBddNodeV(gate->getName(), bddMgrV->getSupport(supportId)()); + // cout << " Name : " << netName << "-> Id : " << nId.id << endl; + // cout << "Support Id : " << supportId << "\n\n"; + // cout << " --- \n"; + cout << "RO: "<< gate->getGid() << endl; + ++supportId; + } + // build FF_NS (Y: next state) + // here we only create "CS_name + _ns" for y_i + for (unsigned i = 0, n = getNumLATCHs(); i < n; ++i) { + CirRiGate* gate = (file) ? getRi(i) : getRi(n - i - 1); + // GVNetId ri = getInputNetId(nId, 0); // get RI + // string netName = getNetNameFromId(ri.id); + bddMgrV->addBddNodeV(gate->getName(), bddMgrV->getSupport(supportId)()); + ++supportId; + } + // Constants (const0 node, id=0) + bddMgrV->addBddNodeV(_const0->getGid(), BddNodeV::_zero()); + ++supportId; + + // for (uint32_t i = 0; i < getConstSize(); ++i) { + // assert(getGateType(getConst(i)) == GV_NTK_OBJ_CONST0); + // bddMgrV->addBddNodeV(getConst(i).id, BddNodeV::_zero()); + // ++supportId; + // } + // // FF that stores const0 (take as const0 node) + // for (uint32_t i = 0; i < getFFConst0Size(); ++i) { + // assert(getGateType(getFFConst0(i)) == GV_NTK_OBJ_FF_NS); + // bddMgrV->addBddNodeV(getFFConst0(i).id, BddNodeV::_zero()); + // bddMgrV->addBddNodeV(getRoIdFromRiId(getFFConst0(i).id), + // BddNodeV::_zero()); + // ++supportId; + // } + + return true; +} + +void +CirMgr::buildNtkBdd() { + // TODO: build BDD for ntk here + // Perform DFS traversal from DFF inputs, inout, and output gates. + // Collect ordered nets to a GVNetVec + // Construct BDDs in the DFS order + + // build PO + // stack s; + // for (unsigned i = 0; i < getNumPOs(); ++i) { + // s.push(getPo(i)); + // } + // while (s.size() > 0) { + // buildBdd(s.top()); + // s.pop(); + // } + + for (unsigned i = 0; i < getNumPOs(); ++i) { + buildBdd(getPo(i)); + } + + // build next state (RI) + for (unsigned i = 0; i < getNumLATCHs(); ++i) { + // GVNetId left = getInputNetId(getFF(i), 0); // get RI + CirGate* left = getRi(i); // get RI + if (bddMgrV->getBddNodeV(left->getGid()) == (size_t)0) { + buildBdd(left); + } + BddNodeV ns = ((left->getIn0().isInv())? ~bddMgrV->getBddNodeV(left->getGid()) + : bddMgrV->getBddNodeV(left->getGid())); + // BddNodeV ns = bddMgrV->getBddNodeV(left->getGid()); + } +} + +void +CirMgr::buildBdd(CirGate* gate) { + GateList orderedGates; + clearList(orderedGates); + CirGate::setGlobalRef(); + gate->genDfsList(orderedGates); + assert(orderedGates.size() <= getNumTots()); + + // TODO: build BDD for the specified net here + CirGateV left; + CirGateV right; + for (unsigned i = 0; i < orderedGates.size(); ++i) { + if (orderedGates[i]->getType() == AIG_GATE) { + // build fanin + left = orderedGates[i]->getIn0(); + right = orderedGates[i]->getIn1(); + // leftBdd = bddMgrV->getBddNodeV(left.gateId()); + // rightBdd= bddMgrV->getBddNodeV(right.gateId()); + // if (bddMgrV->getBddNodeV(left.id) == (size_t)0) { + // buildBdd(left); + // } + // if (bddMgrV->getBddNodeV(right.id) == (size_t)0) { + // buildBdd(right); + // } + BddNodeV newNode =((left.isInv()) ? ~bddMgrV->getBddNodeV(left.gateId()) + : bddMgrV->getBddNodeV(left.gateId())) & + ((right.isInv()) ? ~bddMgrV->getBddNodeV(right.gateId()) + : bddMgrV->getBddNodeV(right.gateId())); + bddMgrV->addBddNodeV(orderedGates[i]->getGid(), newNode()); + } + // PO, RI + else if ((orderedGates[i]->getType() == RI_GATE) || (orderedGates[i]->getType() == PO_GATE)) { + // GVNetId fanin = getInputNetId(orderedNets[i], 0); + CirGateV in0 = orderedGates[i]->getIn0(); + BddNodeV newNode = (in0.isInv()) ? ~bddMgrV->getBddNodeV(in0.gateId()) : bddMgrV->getBddNodeV(in0.gateId()); + bddMgrV->addBddNodeV(orderedGates[i]->getGid(), newNode()); + } + } +} + +// Put fanins of a net (id) into a vector (nets) in topological order +void +CirMgr::dfsOrder(vector& nets) { + // if (isLatestMiscData(id)) return; + + // setLatestMiscData(id); + // // traverse fanin logics + // const GV_Ntk_Type_t type = getGateType(id); + // if ((type == GV_NTK_OBJ_FF_NS) || (type == GV_NTK_OBJ_PO)) { + // dfsOrder(getInputNetId(id, 0), nets); + // } else if (type == GV_NTK_OBJ_AIG) { + // dfsOrder(getInputNetId(id, 0), nets); + // dfsOrder(getInputNetId(id, 1), nets); + // } + // nets.push_back(id); // Record Order +} + +#endif \ No newline at end of file diff --git a/src/cir/cirMgr.cpp b/src/cir/cirMgr.cpp index 9d4cb04e..20943ec5 100644 --- a/src/cir/cirMgr.cpp +++ b/src/cir/cirMgr.cpp @@ -617,6 +617,9 @@ CirMgr::genDfsList() CirGate::setGlobalRef(); for (unsigned i = 0, n = getNumPOs(); i < n; ++i) getPo(i)->genDfsList(_dfsList); + + for (unsigned i = 0, n = getNumLATCHs() - 1; i < n; ++i) + getRi(i)->genDfsList(_dfsList); } void @@ -658,9 +661,11 @@ CirAigGate::genDfsList(GateList& gateList) { setToGlobalRef(); CirGate* g = _in0.gate(); + cout << g->getGid()<isGlobalRef()) g->genDfsList(gateList); g = _in1.gate(); + cout << g->getGid()<isGlobalRef()) g->genDfsList(gateList); gateList.push_back(this); diff --git a/src/cir/cirMgr.h b/src/cir/cirMgr.h index 7f4b21a2..7ef7d52e 100644 --- a/src/cir/cirMgr.h +++ b/src/cir/cirMgr.h @@ -109,10 +109,11 @@ class CirMgr // --- MODIFICATION FOR SoCV HW5 (START) --- void readCirFromAbc(string fileName, CirFileType fileType); void initCir(Gia_Man_t* pGia); + void buildNtkBdd(); + void buildBdd(CirGate* gate); + void dfsOrder(vector& nets); CirGate* createGate(unsigned id, GateType type); const bool setBddOrder(const bool& file); - void buildNtkBdd(); - void buildBdd(const CirGate* gate); // --- MODIFICATION FOR SoCV HW5 (END) --- private: unsigned _numDecl[TOT_PARSE_PORTS]; From 6f5c15cf643e41b91f733229a3768097d7a495f1 Mon Sep 17 00:00:00 2001 From: hchchiu Date: Fri, 13 Oct 2023 10:49:25 +0800 Subject: [PATCH 007/307] finish bdd prove --- src/cir/cirAig.cpp | 36 +++----------------- src/cir/cirBdd.cpp | 56 -------------------------------- src/cmd/gvCmdMgr.h | 2 +- src/prove/proveBdd.cpp | 74 +++++++++++++++++------------------------- src/prove/proveCmd.cpp | 17 ++++++---- 5 files changed, 47 insertions(+), 138 deletions(-) diff --git a/src/cir/cirAig.cpp b/src/cir/cirAig.cpp index 36197c20..c3c5f68d 100644 --- a/src/cir/cirAig.cpp +++ b/src/cir/cirAig.cpp @@ -68,7 +68,6 @@ CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); _roList[iRo++] = gate; _totGateList[gateId] = gate; - // cout << "Fanin: " <setIn0(getGate(fanin0), Gia_ObjFaninC0(pObj)); gate->setIn1(getGate(fanin1), Gia_ObjFaninC1(pObj)); } else if(Gia_ObjIsRo(pGia, pObj)) { int gateId = Gia_ObjId(pGia,pObj); - if(iPpi < iRo){ - cout << _roList[iPpi]->getGid() << "<->" << Gia_ObjId(pGia,pObj) << endl; - PPI2RO[gateId] = _roList[iPpi]->getGid(); - } - else{ - cout << Gia_ObjId(pGia, pObj); - PPI2RO[gateId] = 0; - } + if(iPpi < iRo) PPI2RO[gateId] = _roList[iPpi]->getGid(); + else PPI2RO[gateId] = 0; iPpi++; - // CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); - // _roList[iRo++] = gate; - // _totGateList[Gia_ObjId(pGia, pObj)] = gate; - // cout << "RO: "<< Gia_ObjId(pGia, pObj) << endl; - // cout << "Fanin: " <setIn0(getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); _riList[iRi++] = gate; _totGateList[Gia_ObjId(pGia, pObj)] = gate; - cout << "RI: "<< Gia_ObjId(pGia, pObj) << endl; - cout << "Fanin: " < " << Gia_ObjId(pGia, pObjRi)<< endl; - } - - cout << "PPI to RO: \n"; - Gia_ManForEachRo(pGia, pObj, i) { - // cout << _roList[i]->getGid() << "<->" << Gia_ObjId(pGia,pObj) << endl; - cout << i << "<->" << Gia_ObjId(pGia,pObj) << endl; - } + // genConnections(); genDfsList(); // checkFloatList(); diff --git a/src/cir/cirBdd.cpp b/src/cir/cirBdd.cpp index 26ad8f93..76b8676d 100644 --- a/src/cir/cirBdd.cpp +++ b/src/cir/cirBdd.cpp @@ -32,41 +32,19 @@ CirMgr::setBddOrder(const bool& file) { // build PI (primary input) for (unsigned i = 0, n = getNumPIs(); i < n; ++i) { CirPiGate* gate = (file) ? getPi(i) : getPi(n - i - 1); - // string netName = getNetNameFromId(nId.id); bddMgrV->addBddNodeV(gate->getGid(), bddMgrV->getSupport(supportId)()); - // bddMgrV->addBddNodeV(gate->getName(), bddMgrV->getSupport(supportId)()); - // cout << " Name : " << netName << "-> Id : " << nId.id << endl; - // cout << "Support Id : " << supportId << "\n\n"; - // cout << " --- \n"; - cout << "PI: " << gate->getGid() << endl; ++supportId; } - // build InOut (Not use) - // for (unsigned i = 0, n = getInoutSize(); i < n; ++i) { - // const GVNetId& nId = (file) ? getInout(i) : getInout(n - i - 1); - // string netName = getNetNameFromId(nId.id); - // bddMgrV->addBddNodeV(nId.id, bddMgrV->getSupport(supportId)()); - // bddMgrV->addBddNodeV(netName, bddMgrV->getSupport(supportId)()); - // ++supportId; - // } // build FF_CS (X: current state) for (unsigned i = 0, n = getNumLATCHs(); i < n; ++i) { CirRoGate* gate = (file) ? getRo(i) : getRo(n - i - 1); - // string netName = getNetNameFromId(nId.id); bddMgrV->addBddNodeV(gate->getGid(), bddMgrV->getSupport(supportId)()); - // bddMgrV->addBddNodeV(gate->getName(), bddMgrV->getSupport(supportId)()); - // cout << " Name : " << netName << "-> Id : " << nId.id << endl; - // cout << "Support Id : " << supportId << "\n\n"; - // cout << " --- \n"; - cout << "RO: "<< gate->getGid() << endl; ++supportId; } // build FF_NS (Y: next state) // here we only create "CS_name + _ns" for y_i for (unsigned i = 0, n = getNumLATCHs(); i < n; ++i) { CirRiGate* gate = (file) ? getRi(i) : getRi(n - i - 1); - // GVNetId ri = getInputNetId(nId, 0); // get RI - // string netName = getNetNameFromId(ri.id); bddMgrV->addBddNodeV(gate->getName(), bddMgrV->getSupport(supportId)()); ++supportId; } @@ -74,20 +52,6 @@ CirMgr::setBddOrder(const bool& file) { bddMgrV->addBddNodeV(_const0->getGid(), BddNodeV::_zero()); ++supportId; - // for (uint32_t i = 0; i < getConstSize(); ++i) { - // assert(getGateType(getConst(i)) == GV_NTK_OBJ_CONST0); - // bddMgrV->addBddNodeV(getConst(i).id, BddNodeV::_zero()); - // ++supportId; - // } - // // FF that stores const0 (take as const0 node) - // for (uint32_t i = 0; i < getFFConst0Size(); ++i) { - // assert(getGateType(getFFConst0(i)) == GV_NTK_OBJ_FF_NS); - // bddMgrV->addBddNodeV(getFFConst0(i).id, BddNodeV::_zero()); - // bddMgrV->addBddNodeV(getRoIdFromRiId(getFFConst0(i).id), - // BddNodeV::_zero()); - // ++supportId; - // } - return true; } @@ -99,29 +63,18 @@ CirMgr::buildNtkBdd() { // Construct BDDs in the DFS order // build PO - // stack s; - // for (unsigned i = 0; i < getNumPOs(); ++i) { - // s.push(getPo(i)); - // } - // while (s.size() > 0) { - // buildBdd(s.top()); - // s.pop(); - // } - for (unsigned i = 0; i < getNumPOs(); ++i) { buildBdd(getPo(i)); } // build next state (RI) for (unsigned i = 0; i < getNumLATCHs(); ++i) { - // GVNetId left = getInputNetId(getFF(i), 0); // get RI CirGate* left = getRi(i); // get RI if (bddMgrV->getBddNodeV(left->getGid()) == (size_t)0) { buildBdd(left); } BddNodeV ns = ((left->getIn0().isInv())? ~bddMgrV->getBddNodeV(left->getGid()) : bddMgrV->getBddNodeV(left->getGid())); - // BddNodeV ns = bddMgrV->getBddNodeV(left->getGid()); } } @@ -141,14 +94,6 @@ CirMgr::buildBdd(CirGate* gate) { // build fanin left = orderedGates[i]->getIn0(); right = orderedGates[i]->getIn1(); - // leftBdd = bddMgrV->getBddNodeV(left.gateId()); - // rightBdd= bddMgrV->getBddNodeV(right.gateId()); - // if (bddMgrV->getBddNodeV(left.id) == (size_t)0) { - // buildBdd(left); - // } - // if (bddMgrV->getBddNodeV(right.id) == (size_t)0) { - // buildBdd(right); - // } BddNodeV newNode =((left.isInv()) ? ~bddMgrV->getBddNodeV(left.gateId()) : bddMgrV->getBddNodeV(left.gateId())) & ((right.isInv()) ? ~bddMgrV->getBddNodeV(right.gateId()) @@ -157,7 +102,6 @@ CirMgr::buildBdd(CirGate* gate) { } // PO, RI else if ((orderedGates[i]->getType() == RI_GATE) || (orderedGates[i]->getType() == PO_GATE)) { - // GVNetId fanin = getInputNetId(orderedNets[i], 0); CirGateV in0 = orderedGates[i]->getIn0(); BddNodeV newNode = (in0.isInv()) ? ~bddMgrV->getBddNodeV(in0.gateId()) : bddMgrV->getBddNodeV(in0.gateId()); bddMgrV->addBddNodeV(orderedGates[i]->getGid(), newNode()); diff --git a/src/cmd/gvCmdMgr.h b/src/cmd/gvCmdMgr.h index c7e57039..8d3c259c 100644 --- a/src/cmd/gvCmdMgr.h +++ b/src/cmd/gvCmdMgr.h @@ -53,7 +53,7 @@ enum GVCmdOptionError }; const unordered_set _setupMode{GV_CMD_TYPE_REVEALED, GV_CMD_TYPE_COMMON, GV_CMD_TYPE_NETWORK, - GV_CMD_TYPE_ABC, GV_CMD_TYPE_MOD, GV_CMD_TYPE_BDD}; + GV_CMD_TYPE_ABC, GV_CMD_TYPE_MOD, GV_CMD_TYPE_BDD, GV_CMD_TYPE_PROVE}; const unordered_set _vrfMode{GV_CMD_TYPE_VERIFY, GV_CMD_TYPE_SIMULATE, GV_CMD_TYPE_COMMON, GV_CMD_TYPE_MOD, GV_CMD_TYPE_PROVE, GV_CMD_TYPE_ITP}; diff --git a/src/prove/proveBdd.cpp b/src/prove/proveBdd.cpp index 697a5197..a2adc6de 100644 --- a/src/prove/proveBdd.cpp +++ b/src/prove/proveBdd.cpp @@ -9,6 +9,8 @@ #include "bddMgrV.h" #include "gvMsg.h" #include "gvNtk.h" +#include "cirMgr.h" +#include "cirGate.h" #include "util.h" #include #include @@ -19,12 +21,12 @@ BddMgrV::buildPInitialState() { // TODO : remember to set _initState // set initial state to all zero BddNodeV newNode; - for (unsigned i = 0; i < gvNtkMgr->getFFSize(); ++i) { + for (unsigned i = 0; i < cirMgr->getNumLATCHs(); ++i) { if (i == 0) { - newNode = ite(bddMgrV->getBddNodeV(gvNtkMgr->getFF(i).id), + newNode = ite(bddMgrV->getBddNodeV(cirMgr->getRo(i)->getGid()), BddNodeV::_zero, BddNodeV::_one); } else { - newNode = ite(bddMgrV->getBddNodeV(gvNtkMgr->getFF(i).id), + newNode = ite(bddMgrV->getBddNodeV(cirMgr->getRo(i)->getGid()), BddNodeV::_zero, newNode); } } @@ -41,18 +43,12 @@ BddMgrV::buildPTransRelation() { GVNetId delta_net; // build _tri - for (unsigned i = 0; i < gvNtkMgr->getFFSize(); ++i) { + for (unsigned i = 0; i < cirMgr->getNumLATCHs(); ++i) { // next state (y)'s name - string nsStr = gvNtkMgr->getNetNameFromId( - gvNtkMgr->getInputNetId(gvNtkMgr->getFF(i), 0).id); + string nsStr = cirMgr->getRi(i)->getName(); // get BDD by name y = bddMgrV->getBddNodeV(nsStr); - delta = bddMgrV->getBddNodeV( - gvNtkMgr->getInputNetId(gvNtkMgr->getFF(i), 0).id); - delta_net = gvNtkMgr->getInputNetId(gvNtkMgr->getFF(i), 0); - if (bddMgrV->getBddNodeV(delta_net.id) == (size_t)0) { - gvNtkMgr->buildBdd(delta_net); - } + delta = bddMgrV->getBddNodeV(cirMgr->getRi(i)->getGid()); // build _tri if (i == 0) { _tri = ~(y ^ delta); @@ -63,11 +59,8 @@ BddMgrV::buildPTransRelation() { // build _tr _tr = _tri; - for (unsigned i = 0; i < gvNtkMgr->getInputSize(); ++i) { - _tr = _tr.exist(gvNtkMgr->getInput(i).id); - } - for (unsigned i = 0; i < gvNtkMgr->getInoutSize(); ++i) { - _tr = _tr.exist(gvNtkMgr->getInout(i).id); + for (unsigned i = 0; i < cirMgr->getNumPIs(); ++i) { + _tr = _tr.exist(cirMgr->getPi(i)->getGid()); } } @@ -115,15 +108,16 @@ BddMgrV::buildPImage(int level) { if (_reachStates.size() == 1) { ns = _tr & _initState; } else { - ns = _tr& restrict(_reachStates[_reachStates.size() - 1], - (~_reachStates[_reachStates.size() - 2])); + ns = _tr& restrict(_reachStates[_reachStates.size() - 1], (~_reachStates[_reachStates.size() - 2])); } // existential - for (unsigned j = 0; j < gvNtkMgr->getFFSize(); ++j) { - ns = ns.exist(gvNtkMgr->getFF(j).id); + for (unsigned j = 0; j < cirMgr->getNumLATCHs(); ++j) { + ns = ns.exist(cirMgr->getRo(j)->getGid()); } - ns = ns.nodeMove(gvNtkMgr->getFF(0).id + gvNtkMgr->getFFSize(), - gvNtkMgr->getFF(0).id, isMoved); + int from = cirMgr->getRo(0)->getGid() + cirMgr->getNumLATCHs(); + int to = cirMgr->getRo(0)->getGid(); + ns = ns.nodeMove(cirMgr->getRo(0)->getGid() + cirMgr->getNumLATCHs(), + cirMgr->getRo(0)->getGid(), isMoved); // isFixed ? if (_reachStates.size() == 0) { ns = ns | _initState; @@ -164,22 +158,16 @@ BddMgrV::runPCheckProperty(const string& name, BddNodeV monitor) { } if(numofstate != 0) numofstate++; - //cout << "This is reachable state : \n" << _reachStates[numofstate]; - //cout << "This is monitor : \n" << monitor; ns = monitor & _reachStates[numofstate]; - - //cout << "Monitor \"" << name << "\" is violated." << endl; - //cout << "Counter Example:" << endl; - ns = ns.getCube(0); counter_ex.clear(); /* === MODIFICATION FOR PROPERTY 0 IN c.v === */ if(numofstate == 0 ){ BddNodeV firstState = ns; - for (unsigned j = 0; j < gvNtkMgr->getFFSize(); ++j) { - firstState = firstState.exist(gvNtkMgr->getFF(j).id); + for (unsigned j = 0; j < cirMgr->getNumLATCHs(); ++j) { + firstState = firstState.exist(cirMgr->getRo(j)->getGid()); } - for (unsigned j = 0; j < gvNtkMgr->getInputSize(); ++j) { + for (unsigned j = 0; j < cirMgr->getNumPIs(); ++j) { if (firstState.getLeft() != BddNodeV::_zero){ if(firstState.isNegEdge()) timeframe.push_back(0); else timeframe.push_back(1); @@ -190,31 +178,29 @@ BddMgrV::runPCheckProperty(const string& name, BddNodeV monitor) { } } counter_ex.push_back(timeframe); - //cout << firstState << endl; - //cout << firstState.toString(); } /* === END OF MODIFICATION === */ timeframe.clear(); for (unsigned i = 0; i < numofstate; ++i) { // find legal current state - ns = ns.nodeMove(gvNtkMgr->getFF(0).id, - gvNtkMgr->getFF(0).id + gvNtkMgr->getFFSize(), + ns = ns.nodeMove(cirMgr->getRo(0)->getGid(), + cirMgr->getRo(0)->getGid() + cirMgr->getNumLATCHs(), isMoved); ns = _tri & ns & _reachStates[numofstate - 1 - i]; - for (unsigned j = 0; j < gvNtkMgr->getFFSize(); ++j) { - ns = ns.exist(gvNtkMgr->getFF(j).id + gvNtkMgr->getFFSize()); + for (unsigned j = 0; j < cirMgr->getNumLATCHs(); ++j) { + ns = ns.exist(cirMgr->getRo(j)->getGid() + cirMgr->getNumLATCHs()); } // find valid input value - for (unsigned j = 0; j < gvNtkMgr->getInputSize(); ++j) { - if (ns.getLeftCofactor(gvNtkMgr->getInput(j).id) != + for (unsigned j = 0; j < cirMgr->getNumPIs(); ++j) { + if (ns.getLeftCofactor(cirMgr->getPi(j)->getGid()) != BddNodeV::_zero) { - ns = ns.getLeftCofactor(gvNtkMgr->getInput(j).id); + ns = ns.getLeftCofactor(cirMgr->getPi(j)->getGid()); timeframe.push_back(1); - } else if (ns.getRightCofactor(gvNtkMgr->getInput(j).id) != + } else if (ns.getRightCofactor(cirMgr->getPi(j)->getGid()) != BddNodeV::_zero) { - ns = ns.getRightCofactor(gvNtkMgr->getInput(j).id); + ns = ns.getRightCofactor(cirMgr->getPi(j)->getGid()); timeframe.push_back(0); } else { cerr << "error in monitor" << endl; @@ -225,7 +211,7 @@ BddMgrV::runPCheckProperty(const string& name, BddNodeV monitor) { } for (unsigned i = 0; i < counter_ex.size(); ++i) { cout << i << ": "; - for (unsigned j = 0; j < gvNtkMgr->getInputSize(); ++j) { + for (unsigned j = 0; j < cirMgr->getNumPIs(); ++j) { cout << counter_ex[counter_ex.size() - 1 - i][j]; } cout << endl; diff --git a/src/prove/proveCmd.cpp b/src/prove/proveCmd.cpp index 3e61c7fd..5db0c820 100644 --- a/src/prove/proveCmd.cpp +++ b/src/prove/proveCmd.cpp @@ -13,6 +13,8 @@ #include "util.h" #include #include +#include "cirMgr.h" +#include "cirGate.h" using namespace std; @@ -199,24 +201,27 @@ PCheckPropertyCmd::exec(const string& option) { if (!myStr2Int(options[1], num) || (num < 0)) return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); if (isNet) { - if ((unsigned)num >= gvNtkMgr->getNetSize()) { + if ((unsigned)num >= cirMgr->getNumTots()) { gvMsg(GV_MSG_ERR) << "Net with Id " << num << " does NOT Exist in Current Ntk !!" << endl; return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } - netId = GVNetId::makeNetId(num); + // netId = GVNetId::makeNetId(num); } else { - if ((unsigned)num >= gvNtkMgr->getOutputSize()) { + if ((unsigned)num >= cirMgr->getNumPOs()) { gvMsg(GV_MSG_ERR) << "Output with Index " << num << " does NOT Exist in Current Ntk !!" << endl; return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } - netId = gvNtkMgr->getOutput(num); + // netId = gvNtkMgr->getOutput(num); } - BddNodeV monitor = bddMgrV->getBddNodeV(netId.id); + // BddNodeV monitor = bddMgrV->getBddNodeV(netId.id); + BddNodeV monitor = bddMgrV->getBddNodeV(cirMgr->getPo(num)->getGid()); assert(monitor()); - bddMgrV->runPCheckProperty(gvNtkMgr->getNetNameFromId(netId.id), monitor); + // bddMgrV->runPCheckProperty(gvNtkMgr->getNetNameFromId(netId.id), monitor); + string mStr = "monitor"; + bddMgrV->runPCheckProperty(mStr, monitor); return GV_CMD_EXEC_DONE; } From 5493451fee9c402a0073571be7de595c10145964 Mon Sep 17 00:00:00 2001 From: hchchiu Date: Mon, 30 Oct 2023 13:26:33 +0800 Subject: [PATCH 008/307] finish itp prove on basic testcase --- src/cir/cirAig.cpp | 41 +++++--- src/cir/cirDef.h | 15 ++- src/cir/cirGate.cpp | 9 +- src/cir/cirGate.h | 4 + src/cir/cirMgr.cpp | 24 ++--- src/cir/cirMgr.h | 19 ++-- src/itp/gvSat.cpp | 138 ++++++++++++++----------- src/itp/gvSat.h | 24 +++-- src/itp/gvSatCmd.cpp | 13 ++- src/itp/gvSatMgr.cpp | 241 ++++++++++++++++++++++++++++++------------- src/itp/gvSatMgr.h | 26 +++-- src/ntk/gvNtk.cpp | 2 + 12 files changed, 364 insertions(+), 192 deletions(-) diff --git a/src/cir/cirAig.cpp b/src/cir/cirAig.cpp index c3c5f68d..9006523c 100644 --- a/src/cir/cirAig.cpp +++ b/src/cir/cirAig.cpp @@ -110,6 +110,18 @@ CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { } } + Gia_ManForEachRiRo(pGia, pObjRi, pObjRo, i) { + if(i == getNumLATCHs()) break; + + int riGid = Gia_ObjId(pGia, pObjRi), roGid = PPI2RO[Gia_ObjId(pGia,pObjRo)]; + CirGate* riGate = getGate(riGid); + CirRoGate* roGate = static_cast(getGate(roGid)); + roGate->setIn0(riGate, false); + + // cout << Gia_ObjId(pGia, pObjRi) << endl; + // cout << Gia_ObjId(pGia, pObjRo) << " <---> "<< PPI2RO[Gia_ObjId(pGia,pObjRo)]<< endl; + // cout << " --- \n"; + } // genConnections(); genDfsList(); // checkFloatList(); @@ -135,16 +147,21 @@ void CirMgr::initCir(Gia_Man_t* pGia) { // TODO : Resize the list (PI/PO ...) // Create lists - cout << "initializing..." << endl; - // _numDecl[PI] = Gia_ManPiNum(pGia); - _numDecl[PI] = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; - _piList = new CirPiGate*[_numDecl[PI]]; - _numDecl[PO] = Gia_ManPoNum(pGia); - _poList = new CirPoGate*[_numDecl[PO]]; - _numDecl[LATCH] = Gia_ManRegNum(pGia) - 1; - _riList = new CirRiGate*[_numDecl[LATCH]]; - _roList = new CirRoGate*[_numDecl[LATCH]]; - _numDecl[VARS] = Gia_ManObjNum(pGia); - _totGateList = new CirGate*[_numDecl[VARS]]; - _numDecl[AIG] = Gia_ManAndNum(pGia); + cout << "initializing ..." << endl; + // _numDecl[PI] = Gia_ManPiNum(pGia); + // _piList = new CirPiGate*[_numDecl[PI]]; + // _numDecl[PO] = Gia_ManPoNum(pGia); + // _numDecl[LATCH] = Gia_ManRegNum(pGia) - 1; + // _poList = new CirPoGate*[_numDecl[PO]]; + // _riList = new CirRiGate*[_numDecl[LATCH]]; + // _roList = new CirRoGate*[_numDecl[LATCH]]; + // _numDecl[AIG] = Gia_ManAndNum(pGia); + // _numDecl[VARS] = Gia_ManObjNum(pGia); + // _totGateList = new CirGate*[_numDecl[VARS]]; + // _numDecl[PI] = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; + _poList.resize(Gia_ManPoNum(pGia)); + _piList.resize(Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1); + _riList.resize(Gia_ManRegNum(pGia) - 1); + _roList.resize(Gia_ManRegNum(pGia) - 1); + _totGateList.resize(Gia_ManObjNum(pGia)); } diff --git a/src/cir/cirDef.h b/src/cir/cirDef.h index 5be5eb04..d0617e2a 100644 --- a/src/cir/cirDef.h +++ b/src/cir/cirDef.h @@ -29,11 +29,16 @@ class SatSolver; typedef vector GateList; typedef vector GateVList; typedef vector IdList; -typedef CirGate** GateArray; -typedef CirPiGate** PiArray; -typedef CirPoGate** PoArray; -typedef CirRiGate** RiArray; -typedef CirRoGate** RoArray; +// typedef CirGate** GateArray; +typedef vector GateArray; +// typedef CirPiGate** PiArray; +// typedef CirPoGate** PoArray; +// typedef CirRiGate** RiArray; +// typedef CirRoGate** RoArray; +typedef vector RiArray; +typedef vector RoArray; +typedef vector PiArray; +typedef vector PoArray; typedef HashMap FECHash; typedef size_t* SimPattern; typedef vector SimVector; diff --git a/src/cir/cirGate.cpp b/src/cir/cirGate.cpp index 16340b02..5fe6c99b 100644 --- a/src/cir/cirGate.cpp +++ b/src/cir/cirGate.cpp @@ -59,7 +59,7 @@ CirPiGate::printGate() const void CirRoGate::printGate() const { - cout << setw(4) << left << getTypeStr() << _gid; + cout << setw(4) << left << getTypeStr() << _gid << " " << _in0; if (_name) cout << " (" << _name << ")"; cout << endl; } @@ -200,6 +200,13 @@ CirPoGate::setIn0(CirGate* faninGate, bool inv) { setIn0(gateV()); } +void +CirRoGate::setIn0(CirGate* faninGate, bool inv) { + CirGateV gateV = size_t(faninGate); + gateV.setInv(inv); + setIn0(gateV()); +} + void CirRiGate::setIn0(CirGate* faninGate, bool inv) { CirGateV gateV = size_t(faninGate); diff --git a/src/cir/cirGate.h b/src/cir/cirGate.h index ec53624a..a5f0f59e 100644 --- a/src/cir/cirGate.h +++ b/src/cir/cirGate.h @@ -101,6 +101,8 @@ class CirGate unsigned getLineNo() const { return _lineNo; } virtual GateType getType() const = 0; virtual string getTypeStr() const = 0; + virtual void setIn0(CirGate*, bool inv){}; + virtual void setIn1(CirGate*, bool inv){}; virtual CirGateV getIn0() const { return 0; } virtual CirGateV getIn1() const { return 0; } virtual CirGate* getIn0Gate() const { return 0; } @@ -271,6 +273,8 @@ class CirRoGate : public CirGate void setName(char *s) { _name = s; } char* getName() const { return _name; } bool isRo() const { return true; } + void setIn0(size_t i) { _in0 = i; } + void setIn0(CirGate* faninGate, bool inv = false); // Methods about circuit construction void genDfsList(vector&); diff --git a/src/cir/cirMgr.cpp b/src/cir/cirMgr.cpp index 20943ec5..a3641b60 100644 --- a/src/cir/cirMgr.cpp +++ b/src/cir/cirMgr.cpp @@ -244,12 +244,12 @@ CirMgr::readCircuit(const string& fileName) void CirMgr::deleteCircuit() { - if (_totGateList) - for (unsigned i = 1, n = getNumTots(); i < n; ++i) - if (_totGateList[i]) delete _totGateList[i]; - if (_piList) { delete []_piList; _piList = 0; } - if (_poList) { delete []_poList; _poList = 0; } - if (_totGateList) { delete []_totGateList; _totGateList = 0; } + // if (_totGateList) + // for (unsigned i = 1, n = getNumTots(); i < n; ++i) + // if (_totGateList[i]) delete _totGateList[i]; + if (!_piList.empty()) { _piList.clear(); } + if (!_poList.empty()) { _poList.clear(); } + // if (!_totGateList.empty()) { _totGateList.clear(); } if (_fanoutInfo) { delete []_fanoutInfo; _fanoutInfo = 0; } clearList(_undefList); clearList(_floatList); @@ -309,13 +309,13 @@ CirMgr::parseHeader(ifstream& cirin) // } // Create lists - _piList = new CirPiGate*[_numDecl[PI]]; - _poList = new CirPoGate*[_numDecl[PO]]; - _riList = new CirRiGate*[_numDecl[LATCH]]; - _roList = new CirRoGate*[_numDecl[LATCH]]; + // _piList = new CirPiGate*[_numDecl[PI]]; + // _poList = new CirPoGate*[_numDecl[PO]]; + // _riList = new CirRiGate*[_numDecl[LATCH]]; + // _roList = new CirRoGate*[_numDecl[LATCH]]; // +1 for const unsigned numTots = getNumTots(); - _totGateList = new CirGate*[numTots]; + // _totGateList = new CirGate*[numTots]; for (unsigned i = 0; i < numTots; ++i) _totGateList[i] = 0; _fanoutInfo = new GateList[numTots]; @@ -618,7 +618,7 @@ CirMgr::genDfsList() for (unsigned i = 0, n = getNumPOs(); i < n; ++i) getPo(i)->genDfsList(_dfsList); - for (unsigned i = 0, n = getNumLATCHs() - 1; i < n; ++i) + for (unsigned i = 0, n = getNumLATCHs(); i < n; ++i) getRi(i)->genDfsList(_dfsList); } diff --git a/src/cir/cirMgr.h b/src/cir/cirMgr.h index 7ef7d52e..b8957dda 100644 --- a/src/cir/cirMgr.h +++ b/src/cir/cirMgr.h @@ -51,10 +51,14 @@ class CirMgr void setFlag(CirMgrFlag f) const { _flag |= f; } void unsetFlag(CirMgrFlag f) const { _flag &= ~f; } void resetFlag() const { _flag = 0; } - unsigned getNumPIs() const { return _numDecl[PI]; } - unsigned getNumPOs() const { return _numDecl[PO]; } - unsigned getNumLATCHs() const { return _numDecl[LATCH]; } - unsigned getNumTots() const { return _numDecl[VARS] + _numDecl[PO] + 1; } + // unsigned getNumPIs() const { return _numDecl[PI]; } + // unsigned getNumPOs() const { return _numDecl[PO]; } + unsigned getNumPIs() const { return _piList.size(); } + unsigned getNumPOs() const { return _poList.size(); } + unsigned getNumLATCHs() const { return _riList.size(); } + unsigned getNumTots() const { return _totGateList.size(); } + // unsigned getNumLATCHs() const { return _numDecl[LATCH]; } + // unsigned getNumTots() const { return _numDecl[VARS] + _numDecl[PO] + 1; } CirPiGate* getPi(unsigned i) const { return _piList[i]; } CirPoGate* getPo(unsigned i) const { return _poList[i]; } CirRiGate* getRi(unsigned i) const { return _riList[i]; } @@ -106,15 +110,16 @@ class CirMgr bool createMiter(CirMgr*, CirMgr*); static CirGate *_const0; - // --- MODIFICATION FOR SoCV HW5 (START) --- + // --- MODIFICATION FOR SoCV HW5 --- void readCirFromAbc(string fileName, CirFileType fileType); void initCir(Gia_Man_t* pGia); void buildNtkBdd(); void buildBdd(CirGate* gate); void dfsOrder(vector& nets); - CirGate* createGate(unsigned id, GateType type); + void addTotGate(CirGate* gate){_totGateList.push_back(gate);}; const bool setBddOrder(const bool& file); - // --- MODIFICATION FOR SoCV HW5 (END) --- + CirGate* createGate(unsigned id, GateType type); + // --- MODIFICATION FOR SoCV HW5 --- private: unsigned _numDecl[TOT_PARSE_PORTS]; mutable unsigned _flag; diff --git a/src/itp/gvSat.cpp b/src/itp/gvSat.cpp index 09073227..01dc25a8 100644 --- a/src/itp/gvSat.cpp +++ b/src/itp/gvSat.cpp @@ -10,18 +10,22 @@ #define SAT_C #include "gvSat.h" +#include "cirMgr.h" +#include "cirGate.h" #include #include -GVSatSolver::GVSatSolver(GVNtkMgr* ntk) : _ntk(ntk) { +GVSatSolver::GVSatSolver(GVNtkMgr* ntk) : _ntk(NULL) { _solver = new SolverV(); _solver->proof = new Proof(); _assump.clear(); _curVar = 0; _solver->newVar(); ++_curVar; - _ntkData = new vector[ntk->getNetSize()]; - for (uint32_t i = 0; i < ntk->getNetSize(); ++i) _ntkData[i].clear(); + // _ntkData = new vector[ntk->getNetSize()]; + // for (uint32_t i = 0; i < ntk->getNetSize(); ++i) _ntkData[i].clear(); + _ntkData = new vector[cirMgr->getNumTots()]; + for (uint32_t i = 0; i < cirMgr->getNumTots(); ++i) _ntkData[i].clear(); } GVSatSolver::~GVSatSolver() { @@ -60,15 +64,17 @@ GVSatSolver::assertProperty(const size_t& var, const bool& invert) { } void -GVSatSolver::assumeProperty(const GVNetId& id, const bool& invert, const uint32_t& depth) { - const Var var = getVerifyData(id, depth); - _assump.push(mkLit(var, invert ^ id.cp)); +GVSatSolver::assumeProperty(const CirGate* gate, const bool& invert, const uint32_t& depth) { + const Var var = getVerifyData(gate, depth); + // _assump.push(mkLit(var, invert ^ id.cp)); + _assump.push(mkLit(var, invert)); } void -GVSatSolver::assertProperty(const GVNetId& id, const bool& invert, const uint32_t& depth) { - const Var var = getVerifyData(id, depth); - _solver->addUnit(mkLit(var, invert ^ id.cp)); +GVSatSolver::assertProperty(const CirGate* gate, const bool& invert, const uint32_t& depth) { + const Var var = getVerifyData(gate, depth); + // _solver->addUnit(mkLit(var, invert ^ id.cp)); + _solver->addUnit(mkLit(var, invert)); } const bool @@ -89,11 +95,12 @@ GVSatSolver::assump_solve() { } const GVBitVecX -GVSatSolver::getDataValue(const GVNetId& id, const uint32_t& depth) const { - Var var = getVerifyData(id, depth); +GVSatSolver::getDataValue(const CirGate* gate, const uint32_t& depth) const { + Var var = getVerifyData(gate, depth); uint32_t i, width = 1; GVBitVecX value(width); - if (isGVNetInverted(id)) { + // Modification for cir structure + if (false) { for (i = 0; i < width; ++i) if (gv_l_True == _solver->model[var + i]) value.set0(i); else value.set1(i); @@ -112,14 +119,15 @@ GVSatSolver::getDataValue(const size_t& var) const { const size_t GVSatSolver::getFormula(const GVNetId& id, const uint32_t& depth) { - Var var = getVerifyData(id, depth); - return (id.fanin0Cp ? getNegVar(var) : getPosVar(var)); + // Var var = getVerifyData(id, depth); + // return (id.fanin0Cp ? getNegVar(var) : getPosVar(var)); } void GVSatSolver::resizeNtkData(const uint32_t& num) { - vector* tmp = new vector[_ntk->getNetSize()]; - for (uint32_t i = 0, j = (_ntk->getNetSize() - num); i < j; ++i) tmp[i] = _ntkData[i]; + // vector* tmp = new vector[_ntk->getNetSize()]; + vector* tmp = new vector[cirMgr->getNumTots()]; + for (uint32_t i = 0, j = cirMgr->getNumTots() - num; i < j; ++i) tmp[i] = _ntkData[i]; delete[] _ntkData; _ntkData = tmp; } @@ -133,35 +141,39 @@ GVSatSolver::newVar() { } const Var -GVSatSolver::getVerifyData(const GVNetId& id, const uint32_t& depth) const { - if (depth >= _ntkData[getGVNetIndex(id)].size()) return 0; - else return _ntkData[getGVNetIndex(id)][depth]; +GVSatSolver::getVerifyData(const CirGate* gate, const uint32_t& depth) const { + if (depth >= _ntkData[gate->getGid()].size()) return 0; + else return _ntkData[gate->getGid()][depth]; } void -GVSatSolver::add_FALSE_Formula(const GVNetId& out, const uint32_t& depth) { - const uint32_t index = getGVNetIndex(out); +GVSatSolver::add_FALSE_Formula(const CirGate* gate, const uint32_t& depth) { + // const uint32_t index = getGVNetIndex(out); + const uint32_t index = gate->getGid(); _ntkData[index].push_back(newVar()); _solver->addUnit(mkLit(_ntkData[index].back(), true)); } void -GVSatSolver::add_PI_Formula(const GVNetId& out, const uint32_t& depth) { - const uint32_t index = getGVNetIndex(out); +GVSatSolver::add_PI_Formula(const CirGate* gate, const uint32_t& depth) { + // const uint32_t index = getGVNetIndex(out); + const uint32_t index = gate->getGid(); _ntkData[index].push_back(newVar()); } void -GVSatSolver::add_FF_Formula(const GVNetId& out, const uint32_t& depth) { - const uint32_t index = getGVNetIndex(out); +GVSatSolver::add_FF_Formula(const CirGate* gate, const uint32_t& depth) { + // const uint32_t index = getGVNetIndex(out); + const uint32_t index = gate->getGid(); // assert(depth == _ntkData[index].size()); if (depth) { // Build FF I/O Relation - const GVNetId in1 = _ntk->getInputNetId(out, 0); - const Var var1 = getVerifyData(in1, depth - 1); + // const GVNetId in1 = _ntk->getInputNetId(out, 0); + CirGateV in0 = gate->getIn0(); + const Var var1 = getVerifyData(in0.gate(), depth - 1); - if (out.fanin0Cp) { + if (in0.isInv()) { // a <-> b _ntkData[index].push_back(newVar()); Lit a = mkLit(_ntkData[index].back()); @@ -183,20 +195,23 @@ GVSatSolver::add_FF_Formula(const GVNetId& out, const uint32_t& depth) { } void -GVSatSolver::add_AND_Formula(const GVNetId& out, const uint32_t& depth) { - const uint32_t index = getGVNetIndex(out); +GVSatSolver::add_AND_Formula(const CirGate* gate, const uint32_t& depth) { + // const uint32_t index = getGVNetIndex(out); + const uint32_t index = gate->getGid(); _ntkData[index].push_back(newVar()); const Var& var = _ntkData[index].back(); // Build AND I/O Relation - const GVNetId in1 = _ntk->getInputNetId(out, 0); - const GVNetId in2 = _ntk->getInputNetId(out, 1); - const Var var1 = getVerifyData(in1, depth); - const Var var2 = getVerifyData(in2, depth); + // const GVNetId in1 = _ntk->getInputNetId(out, 0); + // const GVNetId in2 = _ntk->getInputNetId(out, 1); + const CirGateV in0 = gate->getIn0(); + const CirGateV in1 = gate->getIn1(); + const Var var0 = getVerifyData(in0.gate(), depth); + const Var var1 = getVerifyData(in1.gate(), depth); Lit y = mkLit(var); - Lit a = mkLit(var1, out.fanin0Cp); - Lit b = mkLit(var2, out.fanin1Cp); + Lit a = mkLit(var0, in0.isInv()); + Lit b = mkLit(var1, in1.isInv()); vec lits; lits.clear(); @@ -216,43 +231,44 @@ GVSatSolver::add_AND_Formula(const GVNetId& out, const uint32_t& depth) { } void -GVSatSolver::addBoundedVerifyData(const GVNetId& id, const uint32_t& depth) { - if (existVerifyData(id, depth)) return; - addBoundedVerifyDataRecursively(id, depth); +GVSatSolver::addBoundedVerifyData(const CirGate* gate, const uint32_t& depth) { + if (existVerifyData(gate, depth)) return; + addBoundedVerifyDataRecursively(gate, depth); } void -GVSatSolver::addBoundedVerifyDataRecursively(const GVNetId& id, const uint32_t& depth) { - const GV_Ntk_Type_t type = gvNtkMgr->getGateType(id); - if (existVerifyData(id, depth)) return; - if (GV_NTK_OBJ_PI == type) add_PI_Formula(id, depth); - else if (GV_NTK_OBJ_FF_CS == type || GV_NTK_OBJ_FF_NS == type) { +GVSatSolver::addBoundedVerifyDataRecursively(const CirGate* gate, const uint32_t& depth) { + GateType type = gate->getType(); + if (existVerifyData(gate, depth)) return; + if (type == PI_GATE) add_PI_Formula(gate, depth); + else if (RO_GATE == type || RI_GATE == type) { uint32_t newDepth = depth; if (depth) { - if (GV_NTK_OBJ_FF_NS == type) newDepth -= 1; - addBoundedVerifyDataRecursively(_ntk->getInputNetId(id, 0), newDepth); + if (type == RI_GATE) newDepth -= 1; + addBoundedVerifyDataRecursively(gate->getIn0Gate(), newDepth); } - add_FF_Formula(id, depth); - } else if (GV_NTK_OBJ_AIG >= type) { - // if (GV_NTK_OBJ_PO == type) { - // addBoundedVerifyDataRecursively(_ntk->getInputNetId(id, 0), depth); - // add_FF_Formula(id, depth); - // } else - if (GV_NTK_OBJ_AIG == type) { - addBoundedVerifyDataRecursively(_ntk->getInputNetId(id, 0), depth); - addBoundedVerifyDataRecursively(_ntk->getInputNetId(id, 1), depth); - add_AND_Formula(id, depth); + add_FF_Formula(gate, depth); + } + else{ + if (type == PO_GATE) { + addBoundedVerifyDataRecursively(gate->getIn0Gate(), depth); + add_FF_Formula(gate, depth); + } else if (type == AIG_GATE) { + addBoundedVerifyDataRecursively(gate->getIn0Gate(), depth); + addBoundedVerifyDataRecursively(gate->getIn1Gate(), depth); + add_AND_Formula(gate, depth); } else { - add_FALSE_Formula(id, depth); + add_FALSE_Formula(gate, depth); } - } else { - assert(0); } + // } else { + // // assert(0); + // } } const bool -GVSatSolver::existVerifyData(const GVNetId& id, const uint32_t& depth) { - return getVerifyData(id, depth); +GVSatSolver::existVerifyData(const CirGate* gate, const uint32_t& depth) { + return getVerifyData(gate, depth); } #endif diff --git a/src/itp/gvSat.h b/src/itp/gvSat.h index 77a73601..c0c1f004 100644 --- a/src/itp/gvSat.h +++ b/src/itp/gvSat.h @@ -12,6 +12,8 @@ #include "SolverV.h" #include "gvBitVec.h" #include "gvNtk.h" +#include "cirGate.h" +#include "cirMgr.h" #include #include #include @@ -32,8 +34,8 @@ class GVSatSolver void assumeRelease(); void assumeProperty(const size_t&, const bool&); void assertProperty(const size_t&, const bool&); - void assumeProperty(const GVNetId& id, const bool& invert, const uint32_t& depth); - void assertProperty(const GVNetId& id, const bool& invert, const uint32_t& depth); + void assumeProperty(const CirGate* gate, const bool& invert, const uint32_t& depth); + void assertProperty(const CirGate* gate, const bool& invert, const uint32_t& depth); const bool simplify(); const bool solve(); const bool assump_solve(); @@ -41,7 +43,7 @@ class GVSatSolver // Network to Solver Functions const size_t getFormula(const GVNetId&, const uint32_t&); - const GVBitVecX getDataValue(const GVNetId&, const uint32_t&) const; + const GVBitVecX getDataValue(const CirGate*, const uint32_t&) const; const bool getDataValue(const size_t&) const; // Variable Interface Functions inline const size_t reserveFormula() { return getPosVar(newVar()); } @@ -49,19 +51,19 @@ class GVSatSolver inline const size_t getNegFormula(const size_t& v) const { return (v ^ 1ul); } // Gate Formula to Solver Functions - void add_FALSE_Formula(const GVNetId&, const uint32_t&); - void add_PI_Formula(const GVNetId&, const uint32_t&); - void add_FF_Formula(const GVNetId&, const uint32_t&); - void add_AND_Formula(const GVNetId&, const uint32_t&); + void add_FALSE_Formula(const CirGate*, const uint32_t&); + void add_PI_Formula(const CirGate*, const uint32_t&); + void add_FF_Formula(const CirGate*, const uint32_t&); + void add_AND_Formula(const CirGate*, const uint32_t&); - void addBoundedVerifyData(const GVNetId&, const uint32_t&); - const bool existVerifyData(const GVNetId&, const uint32_t&); + void addBoundedVerifyData(const CirGate*, const uint32_t&); + const bool existVerifyData(const CirGate*, const uint32_t&); void resizeNtkData(const uint32_t& num); private: const Var newVar(); - const Var getVerifyData(const GVNetId&, const uint32_t&) const; - void addBoundedVerifyDataRecursively(const GVNetId&, const uint32_t&); + const Var getVerifyData(const CirGate*, const uint32_t&) const; + void addBoundedVerifyDataRecursively(const CirGate*, const uint32_t&); inline const Var getOriVar(const size_t& v) const { return (Var)(v >> 1ul); } inline const size_t getPosVar(const Var& v) const { return (((size_t)v) << 1ul); } diff --git a/src/itp/gvSatCmd.cpp b/src/itp/gvSatCmd.cpp index c5139ec3..9156d959 100644 --- a/src/itp/gvSatCmd.cpp +++ b/src/itp/gvSatCmd.cpp @@ -9,6 +9,8 @@ #include "gvSatCmd.h" #include "gvMsg.h" #include "gvSatMgr.h" +#include "cirMgr.h" +#include "cirGate.h" #include "util.h" #include #include @@ -41,6 +43,7 @@ SATVerifyItpCmd::exec(const string& option) { int num = 0; GVNetId netId; + CirGate* gate; if (!myStr2Int(options[1], num) || (num < 0)) return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); if (isNet) { if ((unsigned)num >= gvNtkMgr->getNetSize()) { @@ -54,12 +57,13 @@ SATVerifyItpCmd::exec(const string& option) { return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } netId = gvNtkMgr->getOutput(num); + gate = cirMgr->getPo(num); } // get PO's input, since the PO is actually a redundant node and should be removed GVNetId redundantNode = gvNtkMgr->getGVNetId(netId.id); GVNetId monitor = gvNtkMgr->getInputNetId(redundantNode, 0); - satMgr->verifyPropertyItp(gvNtkMgr->getNetNameFromId(redundantNode.id), monitor); - + // satMgr->verifyPropertyItp(gvNtkMgr->getNetNameFromId(redundantNode.id), monitor); + satMgr->verifyPropertyItp("monitor", gate->getIn0Gate()); return GV_CMD_EXEC_DONE; } @@ -93,6 +97,7 @@ SATVerifyBmcCmd::exec(const string& option) { int num = 0; GVNetId netId; + CirGate* gate; if (!myStr2Int(options[1], num) || (num < 0)) return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); if (isNet) { if ((unsigned)num >= gvNtkMgr->getNetSize()) { @@ -106,11 +111,13 @@ SATVerifyBmcCmd::exec(const string& option) { return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } netId = gvNtkMgr->getOutput(num); + gate = cirMgr->getPo(num); } // get PO's input, since the PO is actually a redundant node and should be removed GVNetId redundantNode = gvNtkMgr->getGVNetId(netId.id); GVNetId monitor = gvNtkMgr->getInputNetId(redundantNode, 0); - satMgr->verifyPropertyBmc(gvNtkMgr->getNetNameFromId(redundantNode.id), monitor); + // satMgr->verifyPropertyBmc(gvNtkMgr->getNetNameFromId(redundantNode.id), monitor); + satMgr->verifyPropertyBmc("monitor", gate->getIn0Gate()); return GV_CMD_EXEC_DONE; } diff --git a/src/itp/gvSatMgr.cpp b/src/itp/gvSatMgr.cpp index 86a00a1f..d4e303b5 100644 --- a/src/itp/gvSatMgr.cpp +++ b/src/itp/gvSatMgr.cpp @@ -9,6 +9,8 @@ #include "gvSatMgr.h" #include "gvMsg.h" #include "reader.h" +#include "cirMgr.h" +#include "cirGate.h" #include #include #include @@ -17,7 +19,7 @@ using namespace std; void -SATMgr::verifyPropertyItp(const string& name, const GVNetId& monitor) { +SATMgr::verifyPropertyItp(const string& name, const CirGate* monitor) { // Initialize // duplicate the network, so you can modified // the ntk for the proving property without @@ -39,7 +41,7 @@ SATMgr::verifyPropertyItp(const string& name, const GVNetId& monitor) { } void -SATMgr::verifyPropertyBmc(const string& name, const GVNetId& monitor) { +SATMgr::verifyPropertyBmc(const string& name, const CirGate* monitor) { // Initialize // duplicate the network, so you can modified // the ntk for the proving property without @@ -61,12 +63,13 @@ SATMgr::verifyPropertyBmc(const string& name, const GVNetId& monitor) { } void -SATMgr::indBmc(const GVNetId& monitor, SatProofRes& pRes) { +SATMgr::indBmc(const CirGate* monitor, SatProofRes& pRes) { GVSatSolver* gvSatSolver = pRes.getSatSolver(); bind(gvSatSolver); uint32_t i = 0; - GVNetId I = buildInitState(); + // GVNetId I = buildInitState(); + CirGate* I = buildInitState(); gvSatSolver->addBoundedVerifyData(I, i); gvSatSolver->assertProperty(I, false, i); @@ -87,20 +90,30 @@ SATMgr::indBmc(const GVNetId& monitor, SatProofRes& pRes) { } void -SATMgr::itpUbmc(const GVNetId& monitor, SatProofRes& pRes) { +SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { + GVSatSolver* gvSatSolver = pRes.getSatSolver(); bind(gvSatSolver); size_t num_clauses = getNumClauses(); bool proved = false; gvSatSolver->assumeRelease(); - GVNetId S, R, R_prime, tmp1, tmp2, tmp3, tmp4; + // GVNetId S, R, R_prime, tmp1, tmp2, tmp3, tmp4; + CirGate* S; + CirGate* R; + CirGate* R_prime; + CirGate* tmp1; + CirGate* tmp2; + CirGate* tmp3; + CirGate* tmp4; + CirGate* tmp5; // TODO : finish your own Interpolation-based property checking // PART I: // Build Initial State - GVNetId I = buildInitState(); + // GVNetId I = buildInitState(); + CirGate* I = buildInitState(); // PART II: // Take care the first timeframe (i.e. Timeframe 0 ) // Check if monitor is violated at timeframe 0 @@ -119,15 +132,15 @@ SATMgr::itpUbmc(const GVNetId& monitor, SatProofRes& pRes) { num_clauses = getNumClauses(); gvSatSolver->assertProperty(monitor, true, i); - for (size_t j = 0; j < gvNtkMgr->getFFSize(); ++j) { - gvSatSolver->addBoundedVerifyData(gvNtkMgr->getFF(j), i); - mapVar2Net(gvSatSolver->getVerifyData(gvNtkMgr->getFF(j), i), gvNtkMgr->getFF(j)); + for (size_t j = 0; j < cirMgr->getNumLATCHs(); ++j) { + gvSatSolver->addBoundedVerifyData(cirMgr->getRo(j), i); + mapVar2Net(gvSatSolver->getVerifyData(cirMgr->getRo(j), i), cirMgr->getRo(j)); } i++; // i = 1 // map gvSatSolver vars to latch nets for (size_t j = 0; j < gvNtkMgr->getFFSize(); ++j) { - gvSatSolver->addBoundedVerifyData(gvNtkMgr->getFF(j), i); - mapVar2Net(gvSatSolver->getVerifyData(gvNtkMgr->getFF(j), i), gvNtkMgr->getFF(j)); + gvSatSolver->addBoundedVerifyData(cirMgr->getRo(j), i); + mapVar2Net(gvSatSolver->getVerifyData(cirMgr->getRo(j), i), cirMgr->getRo(j)); } num_clauses = getNumClauses(); @@ -138,8 +151,8 @@ SATMgr::itpUbmc(const GVNetId& monitor, SatProofRes& pRes) { num_clauses = getNumClauses(); for (size_t j = 0; j < gvNtkMgr->getFFSize(); ++j) { - gvSatSolver->addBoundedVerifyData(gvNtkMgr->getFF(j), i); - mapVar2Net(gvSatSolver->getVerifyData(gvNtkMgr->getFF(j), i), gvNtkMgr->getFF(j)); + gvSatSolver->addBoundedVerifyData(cirMgr->getRo(j), i); + mapVar2Net(gvSatSolver->getVerifyData(cirMgr->getRo(j), i), cirMgr->getRo(j)); } num_clauses = getNumClauses(); @@ -198,20 +211,39 @@ SATMgr::itpUbmc(const GVNetId& monitor, SatProofRes& pRes) { } else num_clauses = getNumClauses(); S = getItp(); // see if Si or Ri-1 equals to Ri - tmp2 = ~gvNtkMgr->createNet(); - tmp3 = ~gvNtkMgr->createNet(); - tmp4 = ~gvNtkMgr->createNet(); - R_prime = ~gvNtkMgr->createNet(); - gvSatSolver->resizeNtkData(4); - - gvNtkMgr->createGVAndGate(R_prime, ~R, ~S); // or(R, S) - gvNtkMgr->createGVAndGate(tmp2, ~R, R_prime); - gvNtkMgr->createGVAndGate(tmp3, R, ~R_prime); - gvNtkMgr->createGVAndGate(tmp4, tmp2, tmp3); // tmp4 = R xor R_prime - - gvSatSolver->addBoundedVerifyData(tmp4, 0); + // tmp2 = ~gvNtkMgr->createNet(); + // tmp3 = ~gvNtkMgr->createNet(); + // tmp4 = ~gvNtkMgr->createNet(); + // R_prime = ~gvNtkMgr->createNet(); + tmp1 = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmp1); + tmp2 = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmp2); + tmp3 = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmp3); + tmp4 = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmp4); + tmp5 = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmp5); + R_prime = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(R_prime); + gvSatSolver->resizeNtkData(6); + + // gvNtkMgr->createGVAndGate(R_prime, ~R, ~S); // or(R, S) + // Equal to ... + tmp1->setIn0(R, true); tmp1->setIn1(S, true); + R_prime->setIn0(tmp1, true); R_prime->setIn1(cirMgr->_const0, true); + // gvNtkMgr->createGVAndGate(tmp2, ~R, R_prime); + // Equal to ... + tmp2->setIn0(R, true); tmp2->setIn1(R_prime,false); + // gvNtkMgr->createGVAndGate(tmp3, R, ~R_prime); + // Equal to ... + tmp3->setIn0(R, false); tmp3->setIn1(R_prime, true); + // gvNtkMgr->createGVAndGate(tmp4, tmp2, tmp3); // tmp4 = R xor R_prime + // Equal to ... + tmp4->setIn0(tmp2, true); tmp4->setIn1(tmp3, true); + // INV + tmp5->setIn0(tmp4, true); tmp5->setIn1(cirMgr->_const0, true); + + // gvSatSolver->addBoundedVerifyData(tmp4, 0); + gvSatSolver->addBoundedVerifyData(tmp5, 0); gvSatSolver->assumeRelease(); - gvSatSolver->assumeProperty(tmp4, false, 0); // assume R xor R_prime is true + // gvSatSolver->assumeProperty(tmp4, false, 0); // assume R xor R_prime is true + gvSatSolver->assumeProperty(tmp5, false, 0); // assume R xor R_prime is true gvSatSolver->simplify(); if (!gvSatSolver->assump_solve()) // USAT { @@ -270,11 +302,11 @@ SATMgr::markOffsetClause(const ClauseId& cid) { } void -SATMgr::mapVar2Net(const Var& var, const GVNetId& net) { +SATMgr::mapVar2Net(const Var& var, CirGate* net) { _var2Net[var] = net; } -GVNetId +CirGate* SATMgr::getItp() const { assert(_ptrMinisat); assert(_ptrMinisat->_solver->proof); @@ -291,7 +323,8 @@ SATMgr::getItp() const { _ptrMinisat->_solver->proof->save(proofName.c_str()); // bulding ITP - GVNetId netId = buildItp(proofName); + // GVNetId netId = buildItp(proofName); + CirGate* netId = buildItp(proofName); // delete proof log unlink(proofName.c_str()); @@ -493,41 +526,61 @@ SATMgr::retrieveProof(Reader& rdr, vector& clausePos, vectorgetConst(0)); + I = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(I); + in2 = new CirConstGate(cirMgr->_const0->getGid()); I->setIn0(cirMgr->_const0, true); // iteratively and adn all the PI's negation with otthers - for (size_t i = 0; i < gvNtkMgr->getFFSize(); ++i) { - I = gvNtkMgr->createNet(); - in1 = ~gvNtkMgr->getFF(i); - gvNtkMgr->createGVAndGate(I, in1, in2); - in2 = I; + for (size_t i = 0; i < cirMgr->getNumLATCHs(); ++i) { + I->setIn1(cirMgr->getRo(i), true); + if(i + 1 != cirMgr->getNumLATCHs()){ + in1 = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(in1); + in1->setIn0(I, false); + I = in1; + } } // resize solver data to ntk size - _ptrMinisat->resizeNtkData(gvNtkMgr->getFFSize()); + // _ptrMinisat->resizeNtkData(gvNtkMgr->getFFSize()); + _ptrMinisat->resizeNtkData(cirMgr->getNumLATCHs()); + // GateList orderedGates; + // CirGate::setGlobalRef(); + // I->genDfsList(orderedGates); return I; } // build the McMillan Interpolant -GVNetId +CirGate* SATMgr::buildItp(const string& proofName) const { Reader rdr; // records - map claItpLookup; + // map claItpLookup; + map claItpLookup; vector clausePos; vector usedClause; // ntk - uint32_t netSize = gvNtkMgr->getNetSize(); + // uint32_t netSize = gvNtkMgr->getNetSize(); + uint32_t netSize = cirMgr->getNumTots(); // temperate variables - GVNetId nId, nId1, nId2; + // GVNetId nId, nId1, nId2; + CirGate* nId; + CirGate* nId1; + CirGate* nId2; int i, cid, tmp, idx, tmp_cid; // const 1 & const 0 - GVNetId CONST0, CONST1; - CONST0 = gvNtkMgr->getConst(0); - CONST1 = ~CONST0; + // GVNetId CONST0, CONST1; + // CONST0 = gvNtkMgr->getConst(0); + // CONST1 = ~CONST0; + CirGate* CONST0 = cirMgr->_const0; + CirGate* CONST1 = new CirAigGate(cirMgr->getNumTots(),0); + cirMgr->addTotGate(CONST1); + CONST1->setIn0(cirMgr->_const0, true); CONST1->setIn1(cirMgr->_const0, true); rdr.open(proofName.c_str()); retrieveProof(rdr, clausePos, usedClause); @@ -549,8 +602,23 @@ SATMgr::buildItp(const string& proofName) const { assert(_var2Net.find(idx >> 1) != _var2Net.end()); nId = (_var2Net.find(idx >> 1))->second; nId1 = (_var2Net.find(idx >> 1))->second; - if ((idx & 1) == 1) nId1 = ~nId1; - if ((idx & 1) == 1) nId = ~nId; + // Not Sure ... + if ((idx & 1) == 1) { + CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(tmpId); + tmpId->setIn0(nId1, true); + tmpId->setIn1(cirMgr->_const0, true); + nId1 = tmpId; + // nId1 = ~nId1; + } + if ((idx & 1) == 1) { + CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(tmpId); + tmpId->setIn0(nId, true); + tmpId->setIn1(cirMgr->_const0, true); + // nId = ~nId; + nId = tmpId; + } while (1) { tmp = rdr.get64(); if (tmp == 0) break; @@ -558,11 +626,29 @@ SATMgr::buildItp(const string& proofName) const { if (_varGroup[idx >> 1] == COMMON) { assert(_var2Net.find(idx >> 1) != _var2Net.end()); nId2 = (_var2Net.find(idx >> 1))->second; - if ((idx & 1) == 1) nId2 = ~nId2; + // NOT SURE ... + if ((idx & 1) == 1) { + CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(tmpId); + tmpId->setIn0(nId2, true); + tmpId->setIn1(cirMgr->_const0, true); + // nId2 = ~nId2; + nId2 = tmpId; + } // or - nId = ~gvNtkMgr->createNet(); - gvNtkMgr->createGVAndGate(nId, ~nId1, ~nId2); - nId1 = nId; + // nId = ~gvNtkMgr->createNet(); + // gvNtkMgr->createGVAndGate(nId, ~nId1, ~nId2); + // nId1 = nId; + nId = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(nId); + nId->setIn0(nId1, true); + nId->setIn1(nId2, true); + // not finish or gate !! + CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(tmpId); + tmpId->setIn0(nId, true); + tmpId->setIn1(cirMgr->_const0, true); + nId1 = tmpId; } } } else { @@ -599,9 +685,18 @@ SATMgr::buildItp(const string& proofName) const { nId1 = nId; } else { // or - nId = ~gvNtkMgr->createNet(); - gvNtkMgr->createGVAndGate(nId, ~nId1, ~nId2); - nId1 = nId; + // nId = ~gvNtkMgr->createNet(); + // gvNtkMgr->createGVAndGate(nId, ~nId1, ~nId2); + // nId1 = nId; + nId = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(nId); + nId->setIn0(nId1, true); + nId->setIn1(nId2, true); + CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(tmpId); + tmpId->setIn0(nId, true); + tmpId->setIn1(cirMgr->_const0, true); + nId1 = tmpId; } } else { // Build AND Gate. if (nId1 == CONST0 || nId2 == CONST0) { @@ -615,8 +710,13 @@ SATMgr::buildItp(const string& proofName) const { nId1 = nId; } else { // and - nId = gvNtkMgr->createNet(); - gvNtkMgr->createGVAndGate(nId, nId1, nId2); + // nId = gvNtkMgr->createNet(); + // gvNtkMgr->createGVAndGate(nId, nId1, nId2); + // nId1 = nId; + nId = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(nId); + nId->setIn0(nId1, false); + nId->setIn1(nId2, false); nId1 = nId; } } @@ -629,7 +729,8 @@ SATMgr::buildItp(const string& proofName) const { cid = usedClause[usedClause.size() - 1]; nId = claItpLookup[cid]; - _ptrMinisat->resizeNtkData(gvNtkMgr->getNetSize() - netSize); // resize Solver data to ntk size + // _ptrMinisat->resizeNtkData(gvNtkMgr->getNetSize() - netSize); // resize Solver data to ntk size + _ptrMinisat->resizeNtkData(cirMgr->getNumTots() - netSize); // resize Solver data to ntk size return nId; } @@ -648,24 +749,24 @@ SatProofRes::reportResult(const string& name) const { } void -SatProofRes::reportCex(const GVNetId& monitor, const GVNtkMgr* const ntk) const { +SatProofRes::reportCex(const CirGate* monitor, const GVNtkMgr* const ntk) const { assert(_satSolver != 0); // Output Pattern Value (PI + PIO) GVBitVecX dataValue; for (uint32_t i = 0; i <= _fired; ++i) { gvMsg(GV_MSG_IFO) << i << ": "; - for (int j = ntk->getInoutSize() - 1; j >= 0; --j) { - if (_satSolver->existVerifyData(ntk->getInout(j), i)) { - dataValue = _satSolver->getDataValue(ntk->getInout(j), i); - gvMsg(GV_MSG_IFO) << dataValue[0]; - } else { - gvMsg(GV_MSG_IFO) << 'x'; - } - } - for (int j = ntk->getInputSize() - 1; j >= 0; --j) { - if (_satSolver->existVerifyData(ntk->getInput(j), i)) { - dataValue = _satSolver->getDataValue(ntk->getInput(j), i); + // for (int j = ntk->getInoutSize() - 1; j >= 0; --j) { + // if (_satSolver->existVerifyData(ntk->getInout(j), i)) { + // dataValue = _satSolver->getDataValue(ntk->getInout(j), i); + // gvMsg(GV_MSG_IFO) << dataValue[0]; + // } else { + // gvMsg(GV_MSG_IFO) << 'x'; + // } + // } + for (int j = cirMgr->getNumPIs() - 1; j >= 0; --j) { + if (_satSolver->existVerifyData(cirMgr->getPi(j), i)) { + dataValue = _satSolver->getDataValue(cirMgr->getPi(j), i); gvMsg(GV_MSG_IFO) << dataValue[0]; } else { gvMsg(GV_MSG_IFO) << 'x'; diff --git a/src/itp/gvSatMgr.h b/src/itp/gvSatMgr.h index e54bf0ed..882f162e 100644 --- a/src/itp/gvSatMgr.h +++ b/src/itp/gvSatMgr.h @@ -17,6 +17,8 @@ #include // #include "SolverTypesV.h" #include "reader.h" +#include "cirMgr.h" +#include "cirGate.h" class GVNetId; typedef int ClauseId; @@ -47,7 +49,7 @@ class SatProofRes GVSatSolver* getSatSolver() const { return _satSolver; } void reportResult(const string&) const; - void reportCex(const GVNetId&, const GVNtkMgr* const) const; + void reportCex(const CirGate*, const GVNtkMgr* const) const; private: uint32_t _proved; @@ -63,11 +65,11 @@ class SATMgr ~SATMgr() { reset(); } // entry point for SoCV SAT property checking - void verifyPropertyItp(const string& name, const GVNetId& monitor); - void verifyPropertyBmc(const string& name, const GVNetId& monitor); + void verifyPropertyItp(const string& name, const CirGate* monitor); + void verifyPropertyBmc(const string& name, const CirGate* monitor); // Various proof engines - void indBmc(const GVNetId&, SatProofRes&); - void itpUbmc(const GVNetId&, SatProofRes&); + void indBmc(const CirGate*, SatProofRes&); + void itpUbmc(const CirGate*, SatProofRes&); // bind with a solver to get proof info. void bind(GVSatSolver* ptrMinisat); @@ -77,9 +79,10 @@ class SATMgr void markOnsetClause(const ClauseId& cid); void markOffsetClause(const ClauseId& cid); // map var to V3Net (PPI) - void mapVar2Net(const Var& var, const GVNetId& net); + void mapVar2Net(const Var& var, CirGate* net); // please be sure that you call these function right after a UNSAT solving - GVNetId getItp() const; + // GVNetId getItp() const; + CirGate* getItp() const; vector getUNSATCore() const; // get number of clauses (the latest clause id + 1) int getNumClauses() const { return _ptrMinisat->getNumClauses(); } @@ -91,8 +94,10 @@ class SATMgr private: // helper functions to get proof info. - GVNetId buildInitState() const; - GVNetId buildItp(const string& proofName) const; + // GVNetId buildInitState() const; + CirGate* buildInitState() const; + // GVNetId buildItp(const string& proofName) const; + CirGate* buildItp(const string& proofName) const; void retrieveProof(Reader& rdr, vector& clausePos, vector& usedClause) const; void retrieveProof(Reader& rdr, vector& unsatCore) const; @@ -100,9 +105,10 @@ class SATMgr GVSatSolver* _ptrMinisat; // The duplicated V3Ntk GVNtkMgr* _ntk; + CirMgr* _cirNtk; // to handle interpolation - map _var2Net; // mapping common variables to net + map _var2Net; // mapping common variables to net vector _isClauseOn; // record onset clauses // will be determined in retrieveProof, you don't need to take care about this! mutable vector _isClaOnDup; // duplication & extension of _isClauseOn diff --git a/src/ntk/gvNtk.cpp b/src/ntk/gvNtk.cpp index 452833d0..bcba938d 100644 --- a/src/ntk/gvNtk.cpp +++ b/src/ntk/gvNtk.cpp @@ -6,6 +6,8 @@ Copyright [ ] ****************************************************************************/ #include "gvNtk.h" +#include "cirMgr.h" +#include "cirGate.h" #include "base/abc/abc.h" #include "gvMsg.h" #include "map" From 9dd406b3aa003c5c67f8e7461569e97b40d2e476 Mon Sep 17 00:00:00 2001 From: hchchiu Date: Wed, 1 Nov 2023 02:14:40 +0800 Subject: [PATCH 009/307] finish itp prove on hwmcc testcase --- src/cir/cirAig.cpp | 76 +++++++++++++++++++++++++++++++++++--------- src/cir/cirMgr.cpp | 4 +-- src/cir/cirMgr.h | 2 +- src/itp/gvSat.cpp | 1 + src/itp/gvSatCmd.cpp | 18 ++++++++--- src/itp/gvSatMgr.cpp | 61 ++++++++++++++++++++++++----------- 6 files changed, 121 insertions(+), 41 deletions(-) diff --git a/src/cir/cirAig.cpp b/src/cir/cirAig.cpp index 9006523c..54d535d2 100644 --- a/src/cir/cirAig.cpp +++ b/src/cir/cirAig.cpp @@ -35,19 +35,21 @@ CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { int c, fVerbose = 1; // set verbose to 1 to see which yosys command is used int i, *pWire; - if(fileType == AIGER) + if(fileType == AIGER){ pGia = Gia_AigerRead(pFileName, 0, fSkipStrash, 0); + piNum = Gia_ManPiNum(pGia); + } else if(fileType == VERILOG) { pGia = abcMgr->get_Abc_Frame_t()->pGia; pGia = Wln_BlastSystemVerilog(pFileName,pTopModule,pDefines,fSkipStrash,fInvert,fTechMap,fVerbose); piNum = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; // PI (PI + PPI) - (REG (PPI + CONST0) - CONST0) // cout << Gia_ManPiNum(pGia) << endl; // cout << Gia_ManRegNum(pGia) << endl; - cout << "PI NUM : " << piNum << endl; + // cout << "PI NUM : " << piNum << endl; } // initialize the size of the containers - initCir(pGia); + initCir(pGia, fileType); // increment the global travel id for circuit traversing usage Gia_ManIncrementTravId(pGia); @@ -77,20 +79,42 @@ CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { _totGateList[Gia_ObjId(pGia, pObj)] = gate; } else if(Gia_ObjIsAnd(pObj)) { + bool inv0 = false, inv1 = false; CirAigGate *gate = new CirAigGate(Gia_ObjId(pGia, pObj), 0); _totGateList[Gia_ObjId(pGia, pObj)] = gate; int fanin0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); int fanin1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); - if(PPI2RO.count(fanin0)) fanin0 = PPI2RO[fanin0]; - if(PPI2RO.count(fanin1)) fanin1 = PPI2RO[fanin1]; + if(PPI2RO.count(fanin0)) { + // fanin0 = PPI2RO[fanin0]; + // if(fanin0 == 0) inv0 = true; + } + if(PPI2RO.count(fanin1)) { + // fanin1 = PPI2RO[fanin1]; + // if(fanin1 == 0) inv1 = true; + } gate->setIn0(getGate(fanin0), Gia_ObjFaninC0(pObj)); gate->setIn1(getGate(fanin1), Gia_ObjFaninC1(pObj)); } else if(Gia_ObjIsRo(pGia, pObj)) { int gateId = Gia_ObjId(pGia,pObj); - if(iPpi < iRo) PPI2RO[gateId] = _roList[iPpi]->getGid(); - else PPI2RO[gateId] = 0; - iPpi++; + if(fileType == VERILOG){ + if(iPpi < iRo) PPI2RO[gateId] = _roList[iPpi]->getGid(); + else PPI2RO[gateId] = 0; + iPpi++; + } + else if(fileType == AIGER){ + if(iRo < _roList.size()){ + CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); + _roList[iRo++] = gate; + _totGateList[gateId] = gate; + } + else{ + CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); + _roList[iRo++] = gate; + _totGateList[gateId] = gate; + // PPI2RO[gateId] = 0; + } + } } else if(Gia_ObjIsRi(pGia, pObj)) { CirRiGate *gate = new CirRiGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); @@ -113,20 +137,37 @@ CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { Gia_ManForEachRiRo(pGia, pObjRi, pObjRo, i) { if(i == getNumLATCHs()) break; - int riGid = Gia_ObjId(pGia, pObjRi), roGid = PPI2RO[Gia_ObjId(pGia,pObjRo)]; + int riGid = Gia_ObjId(pGia, pObjRi), roGid = 0; + // int roGid = PPI2RO[Gia_ObjId(pGia,pObjRo)]; + // int roGid = Gia_ObjId(pGia,pObjRo); + if(fileType == VERILOG) roGid = PPI2RO[Gia_ObjId(pGia,pObjRo)]; + else if(fileType == AIGER) roGid = Gia_ObjId(pGia,pObjRo); CirGate* riGate = getGate(riGid); CirRoGate* roGate = static_cast(getGate(roGid)); roGate->setIn0(riGate, false); // cout << Gia_ObjId(pGia, pObjRi) << endl; - // cout << Gia_ObjId(pGia, pObjRo) << " <---> "<< PPI2RO[Gia_ObjId(pGia,pObjRo)]<< endl; + // cout << Gia_ObjId(pGia, pObjRo) << endl;//<< " <---> "<< PPI2RO[Gia_ObjId(pGia,pObjRo)]<< endl; // cout << " --- \n"; } + // DEBUG + // CirGate* riGate = getGate(1034); + // CirRoGate* roGate = static_cast(getGate(136)); + // roGate->setIn0(riGate, false); + // genConnections(); genDfsList(); // checkFloatList(); // checkUnusedList(); + // DEBUG + for(int i = 0; i < _totGateList.size(); ++i){ + CirGate* g = _totGateList[i]; + // if (g->getType() == RI_GATE || g->getType() == PO_GATE) isPrint = true; + if(g) g->printGate(); + } + _poList[0]->printGate(); + } CirGate* @@ -144,7 +185,7 @@ CirMgr::createGate(unsigned id, GateType type) { } void -CirMgr::initCir(Gia_Man_t* pGia) { +CirMgr::initCir(Gia_Man_t* pGia,const CirFileType& fileType) { // TODO : Resize the list (PI/PO ...) // Create lists cout << "initializing ..." << endl; @@ -160,8 +201,13 @@ CirMgr::initCir(Gia_Man_t* pGia) { // _totGateList = new CirGate*[_numDecl[VARS]]; // _numDecl[PI] = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; _poList.resize(Gia_ManPoNum(pGia)); - _piList.resize(Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1); - _riList.resize(Gia_ManRegNum(pGia) - 1); - _roList.resize(Gia_ManRegNum(pGia) - 1); - _totGateList.resize(Gia_ManObjNum(pGia)); + int piNum = Gia_ManPiNum(pGia); + int regNum = Gia_ManRegNum(pGia); + if(fileType == VERILOG) _piList.resize(Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1); + else if(fileType == AIGER) _piList.resize(Gia_ManPiNum(pGia)) ; + // _riList.resize(Gia_ManRegNum(pGia) - 1); + // _roList.resize(Gia_ManRegNum(pGia) - 1); + _riList.resize(Gia_ManRegNum(pGia)); + _roList.resize(Gia_ManRegNum(pGia)); + _totGateList.resize(Gia_ManObjNum(pGia)); } diff --git a/src/cir/cirMgr.cpp b/src/cir/cirMgr.cpp index a3641b60..cafe4779 100644 --- a/src/cir/cirMgr.cpp +++ b/src/cir/cirMgr.cpp @@ -661,11 +661,11 @@ CirAigGate::genDfsList(GateList& gateList) { setToGlobalRef(); CirGate* g = _in0.gate(); - cout << g->getGid()<getGid()<isGlobalRef()) g->genDfsList(gateList); g = _in1.gate(); - cout << g->getGid()<getGid()<isGlobalRef()) g->genDfsList(gateList); gateList.push_back(this); diff --git a/src/cir/cirMgr.h b/src/cir/cirMgr.h index b8957dda..4ddb1088 100644 --- a/src/cir/cirMgr.h +++ b/src/cir/cirMgr.h @@ -112,7 +112,7 @@ class CirMgr static CirGate *_const0; // --- MODIFICATION FOR SoCV HW5 --- void readCirFromAbc(string fileName, CirFileType fileType); - void initCir(Gia_Man_t* pGia); + void initCir(Gia_Man_t* pGia, const CirFileType& type); void buildNtkBdd(); void buildBdd(CirGate* gate); void dfsOrder(vector& nets); diff --git a/src/itp/gvSat.cpp b/src/itp/gvSat.cpp index 01dc25a8..9c266536 100644 --- a/src/itp/gvSat.cpp +++ b/src/itp/gvSat.cpp @@ -258,6 +258,7 @@ GVSatSolver::addBoundedVerifyDataRecursively(const CirGate* gate, const uint32_t addBoundedVerifyDataRecursively(gate->getIn1Gate(), depth); add_AND_Formula(gate, depth); } else { + // CONST_GATE add_FALSE_Formula(gate, depth); } } diff --git a/src/itp/gvSatCmd.cpp b/src/itp/gvSatCmd.cpp index 9156d959..9501a56a 100644 --- a/src/itp/gvSatCmd.cpp +++ b/src/itp/gvSatCmd.cpp @@ -52,18 +52,26 @@ SATVerifyItpCmd::exec(const string& option) { } netId = GVNetId::makeNetId(num); } else { - if ((unsigned)num >= gvNtkMgr->getOutputSize()) { + if ((unsigned)num >= cirMgr->getNumPOs()) { gvMsg(GV_MSG_ERR) << "Output with Index " << num << " does NOT Exist in Current Ntk !!" << endl; return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } - netId = gvNtkMgr->getOutput(num); + // netId = gvNtkMgr->getOutput(num); gate = cirMgr->getPo(num); } // get PO's input, since the PO is actually a redundant node and should be removed - GVNetId redundantNode = gvNtkMgr->getGVNetId(netId.id); - GVNetId monitor = gvNtkMgr->getInputNetId(redundantNode, 0); + // GVNetId redundantNode = gvNtkMgr->getGVNetId(netId.id); + // GVNetId monitor = gvNtkMgr->getInputNetId(redundantNode, 0); // satMgr->verifyPropertyItp(gvNtkMgr->getNetNameFromId(redundantNode.id), monitor); - satMgr->verifyPropertyItp("monitor", gate->getIn0Gate()); + + CirGate* monitor = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(monitor); + monitor->setIn0(gate->getIn0Gate(), gate->getIn0().isInv()); + monitor->setIn1(cirMgr->_const0, true); + satMgr->verifyPropertyItp("monitor", monitor); + + // Ref + // satMgr->verifyPropertyItp("monitor", gate->getIn0Gate()); + return GV_CMD_EXEC_DONE; } diff --git a/src/itp/gvSatMgr.cpp b/src/itp/gvSatMgr.cpp index d4e303b5..c424e284 100644 --- a/src/itp/gvSatMgr.cpp +++ b/src/itp/gvSatMgr.cpp @@ -121,10 +121,13 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { // Mark the added clauses ( up to now ) to onset uint32_t i = 0, k = 0; gvSatSolver->addBoundedVerifyData(I, i); + num_clauses = getNumClauses(); gvSatSolver->assumeProperty(I, false, i); gvSatSolver->addBoundedVerifyData(monitor, i); + num_clauses = getNumClauses(); gvSatSolver->assumeProperty(monitor, false, i); gvSatSolver->simplify(); + num_clauses = getNumClauses(); if (gvSatSolver->assump_solve()) { pRes.setFired(i); return; @@ -136,9 +139,9 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { gvSatSolver->addBoundedVerifyData(cirMgr->getRo(j), i); mapVar2Net(gvSatSolver->getVerifyData(cirMgr->getRo(j), i), cirMgr->getRo(j)); } - i++; // i = 1 + i++; // i = 2 // map gvSatSolver vars to latch nets - for (size_t j = 0; j < gvNtkMgr->getFFSize(); ++j) { + for (size_t j = 0; j < cirMgr->getNumLATCHs(); ++j) { gvSatSolver->addBoundedVerifyData(cirMgr->getRo(j), i); mapVar2Net(gvSatSolver->getVerifyData(cirMgr->getRo(j), i), cirMgr->getRo(j)); } @@ -150,7 +153,7 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { } num_clauses = getNumClauses(); - for (size_t j = 0; j < gvNtkMgr->getFFSize(); ++j) { + for (size_t j = 0; j < cirMgr->getNumLATCHs(); ++j) { gvSatSolver->addBoundedVerifyData(cirMgr->getRo(j), i); mapVar2Net(gvSatSolver->getVerifyData(cirMgr->getRo(j), i), cirMgr->getRo(j)); } @@ -639,16 +642,28 @@ SATMgr::buildItp(const string& proofName) const { // nId = ~gvNtkMgr->createNet(); // gvNtkMgr->createGVAndGate(nId, ~nId1, ~nId2); // nId1 = nId; - nId = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(nId); - nId->setIn0(nId1, true); - nId->setIn1(nId2, true); - // not finish or gate !! + // --- CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmpId); - tmpId->setIn0(nId, true); - tmpId->setIn1(cirMgr->_const0, true); - nId1 = tmpId; + tmpId->setIn0(nId1, true); + tmpId->setIn1(nId2, true); + // not finish or gate !! + nId = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(nId); + nId->setIn0(tmpId, true); + nId->setIn1(cirMgr->_const0, true); + nId1 = nId; + + // nId = new CirAigGate(cirMgr->getNumTots(), 0); + // cirMgr->addTotGate(nId); + // nId->setIn0(nId1, true); + // nId->setIn1(nId2, true); + // // not finish or gate !! + // CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); + // cirMgr->addTotGate(tmpId); + // tmpId->setIn0(nId, true); + // tmpId->setIn1(cirMgr->_const0, true); + // nId1 = tmpId; } } } else { @@ -688,15 +703,25 @@ SATMgr::buildItp(const string& proofName) const { // nId = ~gvNtkMgr->createNet(); // gvNtkMgr->createGVAndGate(nId, ~nId1, ~nId2); // nId1 = nId; - nId = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(nId); - nId->setIn0(nId1, true); - nId->setIn1(nId2, true); CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmpId); - tmpId->setIn0(nId, true); - tmpId->setIn1(cirMgr->_const0, true); - nId1 = tmpId; + tmpId->setIn0(nId1,true); + tmpId->setIn1(nId2, true); + nId = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(nId); + nId->setIn0(tmpId,true); + nId->setIn1(cirMgr->_const0, true); + nId1 = nId; + // --- + // nId = new CirAigGate(cirMgr->getNumTots(), 0); + // cirMgr->addTotGate(nId); + // nId->setIn0(nId1, true); + // nId->setIn1(nId2, true); + // CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); + // cirMgr->addTotGate(tmpId); + // tmpId->setIn0(nId, true); + // tmpId->setIn1(cirMgr->_const0, true); + // nId1 = tmpId; } } else { // Build AND Gate. if (nId1 == CONST0 || nId2 == CONST0) { From 58187d5d94fa45ed4779e6f242b4cdbd6114d50b Mon Sep 17 00:00:00 2001 From: hchchiu Date: Sun, 5 Nov 2023 00:50:17 +0800 Subject: [PATCH 010/307] fix constant one issue --- src/cir/cirAig.cpp | 4 ++++ src/cir/cirMgr.h | 1 + src/itp/gvSatCmd.cpp | 3 ++- src/itp/gvSatMgr.cpp | 37 +++++++++++++++++++++++-------------- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/cir/cirAig.cpp b/src/cir/cirAig.cpp index 54d535d2..025f5c08 100644 --- a/src/cir/cirAig.cpp +++ b/src/cir/cirAig.cpp @@ -150,6 +150,10 @@ CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { // cout << Gia_ObjId(pGia, pObjRo) << endl;//<< " <---> "<< PPI2RO[Gia_ObjId(pGia,pObjRo)]<< endl; // cout << " --- \n"; } + // DEBUG + _const1 = new CirAigGate(getNumTots(), 0 ); addTotGate(_const1); + _const1->setIn0(_const0, true); _const1->setIn1(_const0, true); + // DEBUG // CirGate* riGate = getGate(1034); // CirRoGate* roGate = static_cast(getGate(136)); diff --git a/src/cir/cirMgr.h b/src/cir/cirMgr.h index 4ddb1088..0ce7f08e 100644 --- a/src/cir/cirMgr.h +++ b/src/cir/cirMgr.h @@ -111,6 +111,7 @@ class CirMgr static CirGate *_const0; // --- MODIFICATION FOR SoCV HW5 --- + CirGate *_const1; void readCirFromAbc(string fileName, CirFileType fileType); void initCir(Gia_Man_t* pGia, const CirFileType& type); void buildNtkBdd(); diff --git a/src/itp/gvSatCmd.cpp b/src/itp/gvSatCmd.cpp index 9501a56a..5af8a116 100644 --- a/src/itp/gvSatCmd.cpp +++ b/src/itp/gvSatCmd.cpp @@ -66,7 +66,8 @@ SATVerifyItpCmd::exec(const string& option) { CirGate* monitor = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(monitor); monitor->setIn0(gate->getIn0Gate(), gate->getIn0().isInv()); - monitor->setIn1(cirMgr->_const0, true); + // monitor->setIn1(cirMgr->_const0, true); + monitor->setIn1(cirMgr->_const1, false); satMgr->verifyPropertyItp("monitor", monitor); // Ref diff --git a/src/itp/gvSatMgr.cpp b/src/itp/gvSatMgr.cpp index c424e284..54dd5128 100644 --- a/src/itp/gvSatMgr.cpp +++ b/src/itp/gvSatMgr.cpp @@ -186,11 +186,14 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { markOffsetClause(j); } num_clauses = getNumClauses(); - + k = 0; R = I; S = getItp(); for (; k < pRes.getMaxDepth(); ++k) { + // DEBUG + cout << "[LOG] "<< "i = " << i << " k = " << k << endl; + gvSatSolver->assumeRelease(); gvSatSolver->addBoundedVerifyData(S, 0); gvSatSolver->assumeProperty(S, false, 0); @@ -229,7 +232,7 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { // gvNtkMgr->createGVAndGate(R_prime, ~R, ~S); // or(R, S) // Equal to ... tmp1->setIn0(R, true); tmp1->setIn1(S, true); - R_prime->setIn0(tmp1, true); R_prime->setIn1(cirMgr->_const0, true); + R_prime->setIn0(tmp1, true); R_prime->setIn1(cirMgr->_const1, false); //R_prime->setIn1(cirMgr->_const0, true); // gvNtkMgr->createGVAndGate(tmp2, ~R, R_prime); // Equal to ... tmp2->setIn0(R, true); tmp2->setIn1(R_prime,false); @@ -240,7 +243,7 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { // Equal to ... tmp4->setIn0(tmp2, true); tmp4->setIn1(tmp3, true); // INV - tmp5->setIn0(tmp4, true); tmp5->setIn1(cirMgr->_const0, true); + tmp5->setIn0(tmp4, true); tmp5->setIn1(cirMgr->_const1, false); //tmp5->setIn1(cirMgr->_const0, true); // gvSatSolver->addBoundedVerifyData(tmp4, 0); gvSatSolver->addBoundedVerifyData(tmp5, 0); @@ -538,7 +541,7 @@ SATMgr::buildInitState() const { CirGate* in2; // and const 1 with the first latch I = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(I); - in2 = new CirConstGate(cirMgr->_const0->getGid()); I->setIn0(cirMgr->_const0, true); + in2 = new CirConstGate(cirMgr->_const0->getGid()); I->setIn0(cirMgr->_const1, false); // I->setIn0(cirMgr->_const0, true); // iteratively and adn all the PI's negation with otthers for (size_t i = 0; i < cirMgr->getNumLATCHs(); ++i) { I->setIn1(cirMgr->getRo(i), true); @@ -581,9 +584,10 @@ SATMgr::buildItp(const string& proofName) const { // CONST0 = gvNtkMgr->getConst(0); // CONST1 = ~CONST0; CirGate* CONST0 = cirMgr->_const0; - CirGate* CONST1 = new CirAigGate(cirMgr->getNumTots(),0); - cirMgr->addTotGate(CONST1); - CONST1->setIn0(cirMgr->_const0, true); CONST1->setIn1(cirMgr->_const0, true); + CirGate* CONST1 = cirMgr->_const1; + // CirGate* CONST1 = new CirAigGate(cirMgr->getNumTots(),0); + // cirMgr->addTotGate(CONST1); + // CONST1->setIn0(cirMgr->_const0, true); CONST1->setIn1(cirMgr->_const0, true); rdr.open(proofName.c_str()); retrieveProof(rdr, clausePos, usedClause); @@ -610,7 +614,8 @@ SATMgr::buildItp(const string& proofName) const { CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmpId); tmpId->setIn0(nId1, true); - tmpId->setIn1(cirMgr->_const0, true); + // tmpId->setIn1(cirMgr->_const0, true); + tmpId->setIn1(CONST1, false); nId1 = tmpId; // nId1 = ~nId1; } @@ -618,7 +623,8 @@ SATMgr::buildItp(const string& proofName) const { CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmpId); tmpId->setIn0(nId, true); - tmpId->setIn1(cirMgr->_const0, true); + // tmpId->setIn1(cirMgr->_const0, true); + tmpId->setIn1(CONST1, false); // nId = ~nId; nId = tmpId; } @@ -634,7 +640,8 @@ SATMgr::buildItp(const string& proofName) const { CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmpId); tmpId->setIn0(nId2, true); - tmpId->setIn1(cirMgr->_const0, true); + // tmpId->setIn1(cirMgr->_const0, true); + tmpId->setIn1(CONST1, false); // nId2 = ~nId2; nId2 = tmpId; } @@ -647,13 +654,13 @@ SATMgr::buildItp(const string& proofName) const { cirMgr->addTotGate(tmpId); tmpId->setIn0(nId1, true); tmpId->setIn1(nId2, true); - // not finish or gate !! nId = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(nId); nId->setIn0(tmpId, true); - nId->setIn1(cirMgr->_const0, true); + // nId->setIn1(cirMgr->_const0, true); + nId->setIn1(CONST1, false); nId1 = nId; - + // --- // nId = new CirAigGate(cirMgr->getNumTots(), 0); // cirMgr->addTotGate(nId); // nId->setIn0(nId1, true); @@ -703,6 +710,7 @@ SATMgr::buildItp(const string& proofName) const { // nId = ~gvNtkMgr->createNet(); // gvNtkMgr->createGVAndGate(nId, ~nId1, ~nId2); // nId1 = nId; + // --- CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmpId); tmpId->setIn0(nId1,true); @@ -710,7 +718,8 @@ SATMgr::buildItp(const string& proofName) const { nId = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(nId); nId->setIn0(tmpId,true); - nId->setIn1(cirMgr->_const0, true); + // nId->setIn1(cirMgr->_const0, true); + nId->setIn1(CONST1, false); nId1 = nId; // --- // nId = new CirAigGate(cirMgr->getNumTots(), 0); From 96e787aa6cecef6a16a87bdb733bbca2dcc425e3 Mon Sep 17 00:00:00 2001 From: hchchiu Date: Fri, 24 Nov 2023 05:21:00 +0800 Subject: [PATCH 011/307] Remove log message --- src/abc/gvAbcMgr.h | 3 +- src/cir/cirAig.cpp | 344 ++++++++++++++++++++++--------------- src/cir/cirBdd.cpp | 52 ++---- src/cir/cirCmd.cpp | 375 +++++++++++++++++++---------------------- src/cir/cirMgr.cpp | 19 ++- src/cir/cirMgr.h | 20 ++- src/cmd/gvCmdMgr.cpp | 22 +-- src/itp/gvSatCmd.cpp | 2 +- src/itp/gvSatMgr.cpp | 150 ++++------------- src/ntk/gvNtkCmd.cpp | 4 - src/prove/proveCmd.cpp | 2 +- 11 files changed, 466 insertions(+), 527 deletions(-) diff --git a/src/abc/gvAbcMgr.h b/src/abc/gvAbcMgr.h index 7a09bdf0..aad2a128 100644 --- a/src/abc/gvAbcMgr.h +++ b/src/abc/gvAbcMgr.h @@ -22,9 +22,10 @@ extern "C" Abc_Frame_t* Abc_FrameGetGlobalFrame(); int Cmd_CommandExecute(Abc_Frame_t* pAbc, const char* sCommand); Abc_Ntk_t* Abc_FrameReadNtk(Abc_Frame_t* p); - Gia_Man_t* Wln_BlastSystemVerilog(char* pFileName, char* pTopModule, char* pDefines, int fSkipStrash, int fInvert, int fTechMap, int fVerbose); + Gia_Man_t* Wln_BlastSystemVerilog(char* pFileName, char* pTopModule, char* pDefines, int fSkipStrash, int fInvert, int fTechMap, int fVerbose); } + class AbcMgr { public: diff --git a/src/cir/cirAig.cpp b/src/cir/cirAig.cpp index 025f5c08..b0cb4f41 100644 --- a/src/cir/cirAig.cpp +++ b/src/cir/cirAig.cpp @@ -5,144 +5,186 @@ Author [ Chung-Yang (Ric) Huang ] Copyright [ ] ****************************************************************************/ -#include #include +#include + +#include + #include "base/abc/abc.h" -#include "gvModMgr.h" #include "gvAbcMgr.h" +#include "gvModMgr.h" +#include "kernel/yosys.h" +#include "util.h" + +USING_YOSYS_NAMESPACE + +string gateName(const string& name, const int& bit) { + return name + "[" + to_string(bit) + "]"; +} + +void parseAigMapping(Gia_Man_t* pGia, map& id2Name) { + string buffer; + ifstream mapFile; + int idx, bit; + string name; + + mapFile.open(".map.txt"); + assert(mapFile.is_open()); + while (mapFile) { + if (!(mapFile >> buffer)) break; + // input + if (buffer == "input") { + mapFile >> buffer; + myStr2Int(buffer, idx); + mapFile >> buffer; + myStr2Int(buffer, bit); + mapFile >> buffer; + name = buffer; + id2Name[Gia_ObjId(pGia, Gia_ManPi(pGia, idx))] = gateName(name, bit); + } + // output + else if (buffer == "output") { + mapFile >> buffer; + myStr2Int(buffer, idx); + mapFile >> buffer; + myStr2Int(buffer, bit); + mapFile >> buffer; + name = buffer; + id2Name[Gia_ObjId(pGia, Gia_ManPo(pGia, idx))] = gateName(name, bit); + } + // FF + else if (buffer == "latch") { + mapFile >> buffer; + myStr2Int(buffer, idx); + mapFile >> buffer; + myStr2Int(buffer, bit); + mapFile >> buffer; + name = buffer; + id2Name[Gia_ObjId(pGia, Gia_ObjRiToRo(pGia, Gia_ManRi(pGia, idx)))] = gateName(name, bit); + id2Name[Gia_ObjId(pGia, Gia_ManRi(pGia, idx))] = gateName(name, bit) + "_ns"; + } + } +} + +void buildNameMapping(const string& fileName, Gia_Man_t* pGia, map& id2Name) { + run_pass("read_verilog " + fileName + "; hierarchy -auto-top; flatten; proc; techmap; setundef -zero; aigmap; write_aiger -map .map.txt ._temp_.aig"); + parseAigMapping(pGia, id2Name); +} -void -CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { - // TODO : Convert abc ntk to gv aig ntk +void CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { CirGateV gateV; - Gia_Man_t* pGia = NULL; // the gia pointer of abc - Gia_Obj_t *pObj, *pObjRi, *pObjRo; // the obj element of gia + Gia_Man_t* pGia = NULL; // the gia pointer of abc + Gia_Obj_t *pObj, *pObjRi, *pObjRo; // the obj element of gia unsigned iPi = 0, iPpi = 0, iPo = 0, iRi = 0, iRo = 0; unsigned piNum = 0; - map PPI2RO; + map PPI2RO; + map id2Name; // abc function parameters char* pFileName = new char[100]; cout << "filename = " << fileName << endl; strcpy(pFileName, fileName.c_str()); - char* pTopModule = NULL; // the top module can be auto detected by yosys, no need to set - char* pDefines = NULL; - int fBlast = 1; // blast the ntk to gia (abc's aig data structure) - int fInvert = 0; - int fTechMap = 1; - int fSkipStrash = 0; - int fCollapse = 0; - int c, fVerbose = 1; // set verbose to 1 to see which yosys command is used - int i, *pWire; - - if(fileType == AIGER){ + char* pTopModule = NULL; // the top module can be auto detected by yosys, no need to set + char* pDefines = NULL; + int fBlast = 1; // blast the ntk to gia (abc's aig data structure) + int fInvert = 0; + int fTechMap = 1; + int fSkipStrash = 0; + int fCollapse = 0; + int c, fVerbose = 0; // set verbose to 1 to see which yosys command is used + int i, *pWire; + + if (fileType == AIGER) pGia = Gia_AigerRead(pFileName, 0, fSkipStrash, 0); - piNum = Gia_ManPiNum(pGia); - } - else if(fileType == VERILOG) { - pGia = abcMgr->get_Abc_Frame_t()->pGia; - pGia = Wln_BlastSystemVerilog(pFileName,pTopModule,pDefines,fSkipStrash,fInvert,fTechMap,fVerbose); - piNum = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; // PI (PI + PPI) - (REG (PPI + CONST0) - CONST0) - // cout << Gia_ManPiNum(pGia) << endl; - // cout << Gia_ManRegNum(pGia) << endl; - // cout << "PI NUM : " << piNum << endl; + else if (fileType == VERILOG) + pGia = Wln_BlastSystemVerilog(pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fVerbose); + + if (!pGia) { + cerr << "Cannot open design \"" << fileName << "\"!!" << endl; + return; } + if (fileType == VERILOG) buildNameMapping(fileName, pGia, id2Name); // initialize the size of the containers initCir(pGia, fileType); // increment the global travel id for circuit traversing usage Gia_ManIncrementTravId(pGia); - // since we don't want to traverse the constant node, set the TravId of the // constant node to be as the global one Gia_ObjSetTravIdCurrent(pGia, Gia_ManConst0(pGia)); // traverse the obj's in topological order Gia_ManForEachObj(pGia, pObj, i) { - if(Gia_ObjIsPi(pGia, pObj)) { + if (Gia_ObjIsPi(pGia, pObj)) { int gateId = Gia_ObjId(pGia, pObj); - if(gateId <= piNum){ + if (gateId <= _piList.size()) { CirPiGate* gate = new CirPiGate(Gia_ObjId(pGia, pObj), 0); _piList[iPi++] = gate; _totGateList[gateId] = gate; - } - else{ + } else { CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); _roList[iRo++] = gate; _totGateList[gateId] = gate; } - } - else if(Gia_ObjIsPo(pGia, pObj)) { - CirPoGate *gate = new CirPoGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); + } else if (Gia_ObjIsPo(pGia, pObj)) { + string poName = ""; + CirPoGate* gate = new CirPoGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); + poName = (id2Name.count(gate->getGid())) ? id2Name[gate->getGid()] : to_string(Gia_ObjId(pGia, pObj)); + char* n = new char[poName.size() + 1]; + strcpy(n, poName.c_str()); + gate->setName(n); gate->setIn0(getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); _poList[iPo++] = gate; _totGateList[Gia_ObjId(pGia, pObj)] = gate; - } - else if(Gia_ObjIsAnd(pObj)) { - bool inv0 = false, inv1 = false; - CirAigGate *gate = new CirAigGate(Gia_ObjId(pGia, pObj), 0); - _totGateList[Gia_ObjId(pGia, pObj)] = gate; + } else if (Gia_ObjIsAnd(pObj)) { + CirAigGate* gate = new CirAigGate(Gia_ObjId(pGia, pObj), 0); int fanin0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); int fanin1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); - if(PPI2RO.count(fanin0)) { - // fanin0 = PPI2RO[fanin0]; - // if(fanin0 == 0) inv0 = true; - } - if(PPI2RO.count(fanin1)) { - // fanin1 = PPI2RO[fanin1]; - // if(fanin1 == 0) inv1 = true; - } + if (PPI2RO.count(fanin0)) fanin0 = PPI2RO[fanin0]; + if (PPI2RO.count(fanin1)) fanin1 = PPI2RO[fanin1]; gate->setIn0(getGate(fanin0), Gia_ObjFaninC0(pObj)); gate->setIn1(getGate(fanin1), Gia_ObjFaninC1(pObj)); - } - else if(Gia_ObjIsRo(pGia, pObj)) { - int gateId = Gia_ObjId(pGia,pObj); - if(fileType == VERILOG){ - if(iPpi < iRo) PPI2RO[gateId] = _roList[iPpi]->getGid(); - else PPI2RO[gateId] = 0; + _totGateList[Gia_ObjId(pGia, pObj)] = gate; + } else if (Gia_ObjIsRo(pGia, pObj)) { + int gateId = Gia_ObjId(pGia, pObj); + if (fileType == VERILOG) { + PPI2RO[gateId] = 0; + if (iPpi < iRo) PPI2RO[gateId] = _roList[iPpi]->getGid(); iPpi++; + } else if (fileType == AIGER) { + CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); + _roList[iRo++] = gate; + _totGateList[gateId] = gate; } - else if(fileType == AIGER){ - if(iRo < _roList.size()){ - CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); - _roList[iRo++] = gate; - _totGateList[gateId] = gate; - } - else{ - CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); - _roList[iRo++] = gate; - _totGateList[gateId] = gate; - // PPI2RO[gateId] = 0; - } - } - } - else if(Gia_ObjIsRi(pGia, pObj)) { - CirRiGate *gate = new CirRiGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); - string str = to_string(Gia_ObjId(pGia, pObj)); str = str + "_ns"; - char *n = new char[str.size()+1]; strcpy(n, str.c_str()); + } else if (Gia_ObjIsRi(pGia, pObj)) { + CirRiGate* gate = new CirRiGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); + string str = to_string(Gia_ObjId(pGia, pObj)); + str = str + "_ns"; + char* n = new char[str.size() + 1]; + strcpy(n, str.c_str()); gate->setName(n); gate->setIn0(getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); _riList[iRi++] = gate; _totGateList[Gia_ObjId(pGia, pObj)] = gate; - } - else if(Gia_ObjIsConst0(pObj)) { + } else if (Gia_ObjIsConst0(pObj)) { _totGateList[0] = CirMgr::_const0; - } - else { - assert(true); + } else { cout << "not defined gate type" << endl; + assert(true); } } - + Gia_ManForEachRiRo(pGia, pObjRi, pObjRo, i) { - if(i == getNumLATCHs()) break; + if (i == getNumLATCHs()) break; int riGid = Gia_ObjId(pGia, pObjRi), roGid = 0; // int roGid = PPI2RO[Gia_ObjId(pGia,pObjRo)]; // int roGid = Gia_ObjId(pGia,pObjRo); - if(fileType == VERILOG) roGid = PPI2RO[Gia_ObjId(pGia,pObjRo)]; - else if(fileType == AIGER) roGid = Gia_ObjId(pGia,pObjRo); - CirGate* riGate = getGate(riGid); + if (fileType == VERILOG) + roGid = PPI2RO[Gia_ObjId(pGia, pObjRo)]; + else if (fileType == AIGER) + roGid = Gia_ObjId(pGia, pObjRo); + CirGate* riGate = getGate(riGid); CirRoGate* roGate = static_cast(getGate(roGid)); roGate->setIn0(riGate, false); @@ -150,68 +192,96 @@ CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { // cout << Gia_ObjId(pGia, pObjRo) << endl;//<< " <---> "<< PPI2RO[Gia_ObjId(pGia,pObjRo)]<< endl; // cout << " --- \n"; } - // DEBUG - _const1 = new CirAigGate(getNumTots(), 0 ); addTotGate(_const1); - _const1->setIn0(_const0, true); _const1->setIn1(_const0, true); + // CONST1 Gate + _const1 = new CirAigGate(getNumTots(), 0); + addTotGate(_const1); + _const1->setIn0(_const0, true); + _const1->setIn1(_const0, true); - // DEBUG - // CirGate* riGate = getGate(1034); - // CirRoGate* roGate = static_cast(getGate(136)); - // roGate->setIn0(riGate, false); - - // genConnections(); genDfsList(); - // checkFloatList(); - // checkUnusedList(); // DEBUG - for(int i = 0; i < _totGateList.size(); ++i){ - CirGate* g = _totGateList[i]; - // if (g->getType() == RI_GATE || g->getType() == PO_GATE) isPrint = true; - if(g) g->printGate(); + // for (int i = 0; i < _totGateList.size(); ++i) { + // CirGate* g = _totGateList[i]; + // // if (g->getType() == RI_GATE || g->getType() == PO_GATE) isPrint = true; + // if (g) g->printGate(); + // } + // _poList[0]->printGate(); +} + +void CirMgr::initCir(Gia_Man_t* pGia, const CirFileType& fileType) { + // Create lists + cout << "initializing ..." << endl; + int piNum = 0, regNum = 0, poNum = 0, totNum = 0; + if (fileType == VERILOG) { + piNum = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; + regNum = Gia_ManRegNum(pGia) - 1; + } else if (fileType == AIGER) { + piNum = Gia_ManPiNum(pGia); + regNum = Gia_ManRegNum(pGia); } - _poList[0]->printGate(); + poNum = Gia_ManPoNum(pGia); + totNum = Gia_ManObjNum(pGia); + _piList.resize(piNum); + _riList.resize(regNum); + _roList.resize(regNum); + _poList.resize(poNum); + _totGateList.resize(totNum); } -CirGate* -CirMgr::createGate(unsigned id, GateType type) { - CirGate* gate = _totGateList[id]; - unsigned l = 0; - switch (type) { - case PI_GATE: gate = new CirPiGate(id, l); break; - case AIG_GATE: gate = new CirAigGate(id, l); break; - //case LATCH: gate = new CirRoGate(litId/2, lineNo+1); break; - default: cerr << "Error: Unknown gate type (" << type << ")!!\n"; - exit(-1); - } - return gate; +// CirGate* +// CirMgr::createGate(const GateType& type){ +// // CirGate* gate = _totGateList[id]; +// CirGate* gate; +// unsigned l = 0, id = getNumTots(); +// cirMgr->addTotGate(gate); +// switch (type) { +// case PI_GATE: gate = new CirPiGate(id, l); break; +// case AIG_GATE: gate = new CirAigGate(id, l); break; +// //case LATCH: gate = new CirRoGate(litId/2, lineNo+1); break; +// default: cerr << "Error: Unknown gate type (" << type << ")!!\n"; +// exit(-1); +// } +// return gate; +// } + +CirGate* CirMgr::createNotGate(CirGate* in0) { + CirGate* notGate = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(notGate); + notGate->setIn0(in0, true); + notGate->setIn1(_const1, false); + return notGate; } -void -CirMgr::initCir(Gia_Man_t* pGia,const CirFileType& fileType) { - // TODO : Resize the list (PI/PO ...) - // Create lists - cout << "initializing ..." << endl; - // _numDecl[PI] = Gia_ManPiNum(pGia); - // _piList = new CirPiGate*[_numDecl[PI]]; - // _numDecl[PO] = Gia_ManPoNum(pGia); - // _numDecl[LATCH] = Gia_ManRegNum(pGia) - 1; - // _poList = new CirPoGate*[_numDecl[PO]]; - // _riList = new CirRiGate*[_numDecl[LATCH]]; - // _roList = new CirRoGate*[_numDecl[LATCH]]; - // _numDecl[AIG] = Gia_ManAndNum(pGia); - // _numDecl[VARS] = Gia_ManObjNum(pGia); - // _totGateList = new CirGate*[_numDecl[VARS]]; - // _numDecl[PI] = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; - _poList.resize(Gia_ManPoNum(pGia)); - int piNum = Gia_ManPiNum(pGia); - int regNum = Gia_ManRegNum(pGia); - if(fileType == VERILOG) _piList.resize(Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1); - else if(fileType == AIGER) _piList.resize(Gia_ManPiNum(pGia)) ; - // _riList.resize(Gia_ManRegNum(pGia) - 1); - // _roList.resize(Gia_ManRegNum(pGia) - 1); - _riList.resize(Gia_ManRegNum(pGia)); - _roList.resize(Gia_ManRegNum(pGia)); - _totGateList.resize(Gia_ManObjNum(pGia)); +CirGate* CirMgr::createAndGate(CirGate* in0, CirGate* in1) { + CirGate* andGate = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(andGate); + andGate->setIn0(in0, false); + andGate->setIn1(in1, false); + return andGate; +} + +CirGate* CirMgr::createOrGate(CirGate* in0, CirGate* in1) { + CirGate* tmpGate = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(tmpGate); + tmpGate->setIn0(in0, true); + tmpGate->setIn1(in1, true); + return createNotGate(tmpGate); +} + +CirGate* CirMgr::createXorGate(CirGate* in0, CirGate* in1) { + CirGate* tmpGate0 = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(tmpGate0); + CirGate* tmpGate1 = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(tmpGate1); + CirGate* tmpGate2 = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(tmpGate2); + tmpGate0->setIn0(in0, true); + tmpGate0->setIn1(in1, false); + tmpGate1->setIn0(in0, false); + tmpGate1->setIn1(in1, true); + tmpGate2->setIn0(tmpGate0, true); + tmpGate2->setIn1(tmpGate1, true); + return createNotGate(tmpGate2); } diff --git a/src/cir/cirBdd.cpp b/src/cir/cirBdd.cpp index 76b8676d..804f3af5 100644 --- a/src/cir/cirBdd.cpp +++ b/src/cir/cirBdd.cpp @@ -9,20 +9,20 @@ #ifndef V3_NTK_C #define V3_NTK_C -#include "bddMgrV.h" // MODIFICATION FOR SoCV BDD -#include "bddNodeV.h" // MODIFICATION FOR SoCV BDD +#include "bddMgrV.h" // MODIFICATION FOR SoCV BDD +#include "bddNodeV.h" // MODIFICATION FOR SoCV BDD +#include "cirGate.h" +#include "cirMgr.h" #include "gvMsg.h" #include "stack" #include "util.h" -#include "cirMgr.h" -#include "cirGate.h" -extern BddMgrV* bddMgrV; // MODIFICATION FOR SoCV BDD +extern BddMgrV* bddMgrV; // MODIFICATION FOR SoCV BDD const bool CirMgr::setBddOrder(const bool& file) { unsigned supportSize = getNumPIs() + 2 * getNumLATCHs(); - unsigned bddspsize = bddMgrV->getNumSupports(); + unsigned bddspsize = bddMgrV->getNumSupports(); if (supportSize >= bddMgrV->getNumSupports()) { gvMsg(GV_MSG_ERR) << "BDD Support Size is Smaller Than Current Design Required !!" << endl; return false; @@ -31,7 +31,7 @@ CirMgr::setBddOrder(const bool& file) { unsigned supportId = 1; // build PI (primary input) for (unsigned i = 0, n = getNumPIs(); i < n; ++i) { - CirPiGate* gate = (file) ? getPi(i) : getPi(n - i - 1); + CirPiGate* gate = (file) ? getPi(i) : getPi(n - i - 1); bddMgrV->addBddNodeV(gate->getGid(), bddMgrV->getSupport(supportId)()); ++supportId; } @@ -55,8 +55,7 @@ CirMgr::setBddOrder(const bool& file) { return true; } -void -CirMgr::buildNtkBdd() { +void CirMgr::buildNtkBdd() { // TODO: build BDD for ntk here // Perform DFS traversal from DFF inputs, inout, and output gates. // Collect ordered nets to a GVNetVec @@ -69,17 +68,15 @@ CirMgr::buildNtkBdd() { // build next state (RI) for (unsigned i = 0; i < getNumLATCHs(); ++i) { - CirGate* left = getRi(i); // get RI + CirGate* left = getRi(i); // get RI if (bddMgrV->getBddNodeV(left->getGid()) == (size_t)0) { buildBdd(left); } - BddNodeV ns = ((left->getIn0().isInv())? ~bddMgrV->getBddNodeV(left->getGid()) - : bddMgrV->getBddNodeV(left->getGid())); + BddNodeV ns = ((left->getIn0().isInv()) ? ~bddMgrV->getBddNodeV(left->getGid()) : bddMgrV->getBddNodeV(left->getGid())); } } -void -CirMgr::buildBdd(CirGate* gate) { +void CirMgr::buildBdd(CirGate* gate) { GateList orderedGates; clearList(orderedGates); CirGate::setGlobalRef(); @@ -94,10 +91,10 @@ CirMgr::buildBdd(CirGate* gate) { // build fanin left = orderedGates[i]->getIn0(); right = orderedGates[i]->getIn1(); - BddNodeV newNode =((left.isInv()) ? ~bddMgrV->getBddNodeV(left.gateId()) - : bddMgrV->getBddNodeV(left.gateId())) & - ((right.isInv()) ? ~bddMgrV->getBddNodeV(right.gateId()) - : bddMgrV->getBddNodeV(right.gateId())); + BddNodeV newNode = ((left.isInv()) ? ~bddMgrV->getBddNodeV(left.gateId()) + : bddMgrV->getBddNodeV(left.gateId())) & + ((right.isInv()) ? ~bddMgrV->getBddNodeV(right.gateId()) + : bddMgrV->getBddNodeV(right.gateId())); bddMgrV->addBddNodeV(orderedGates[i]->getGid(), newNode()); } // PO, RI @@ -109,21 +106,4 @@ CirMgr::buildBdd(CirGate* gate) { } } -// Put fanins of a net (id) into a vector (nets) in topological order -void -CirMgr::dfsOrder(vector& nets) { - // if (isLatestMiscData(id)) return; - - // setLatestMiscData(id); - // // traverse fanin logics - // const GV_Ntk_Type_t type = getGateType(id); - // if ((type == GV_NTK_OBJ_FF_NS) || (type == GV_NTK_OBJ_PO)) { - // dfsOrder(getInputNetId(id, 0), nets); - // } else if (type == GV_NTK_OBJ_AIG) { - // dfsOrder(getInputNetId(id, 0), nets); - // dfsOrder(getInputNetId(id, 1), nets); - // } - // nets.push_back(id); // Record Order -} - -#endif \ No newline at end of file +#endif diff --git a/src/cir/cirCmd.cpp b/src/cir/cirCmd.cpp index 0bdf3dc2..5d2bfb86 100644 --- a/src/cir/cirCmd.cpp +++ b/src/cir/cirCmd.cpp @@ -6,242 +6,218 @@ Copyright [ Copyleft(c) 2008-present LaDs(III), GIEE, NTU, Taiwan ] ****************************************************************************/ +#include "cirCmd.h" + #include -#include #include -#include "cirMgr.h" +#include + #include "cirGate.h" -#include "cirCmd.h" -#include "util.h" +#include "cirMgr.h" #include "gvMsg.h" +#include "util.h" using namespace std; extern CirMgr* cirMgr; extern int effLimit; -bool -GVinitCirCmd() -{ - return (gvCmdMgr->regCmd("CIRRead", 4, new CirReadCmd) && - gvCmdMgr->regCmd("CIRPrint", 4, new CirPrintCmd) && - gvCmdMgr->regCmd("CIRGate", 4, new CirGateCmd)); - // gvCmdMgr->regCmd("CIRSWeep", 5, new CirSweepCmd) && - // gvCmdMgr->regCmd("CIROPTimize", 6, new CirOptCmd) && - // gvCmdMgr->regCmd("CIRSTRash", 6, new CirStrashCmd) && - // gvCmdMgr->regCmd("CIRSIMulate", 6, new CirSimCmd) && - // gvCmdMgr->regCmd("CIRFraig", 4, new CirFraigCmd) && - // gvCmdMgr->regCmd("CIRWrite", 4, new CirWriteCmd) && - // gvCmdMgr->regCmd("CIRMiter", 4, new CirMiterCmd) && - // gvCmdMgr->regCmd("CIREFFort", 6, new CirEffortCmd)); +bool GVinitCirCmd() { + return (gvCmdMgr->regCmd("CIRRead", 4, new CirReadCmd) && + gvCmdMgr->regCmd("CIRPrint", 4, new CirPrintCmd) && + gvCmdMgr->regCmd("CIRGate", 4, new CirGateCmd)); + // gvCmdMgr->regCmd("CIRSWeep", 5, new CirSweepCmd) && + // gvCmdMgr->regCmd("CIROPTimize", 6, new CirOptCmd) && + // gvCmdMgr->regCmd("CIRSTRash", 6, new CirStrashCmd) && + // gvCmdMgr->regCmd("CIRSIMulate", 6, new CirSimCmd) && + // gvCmdMgr->regCmd("CIRFraig", 4, new CirFraigCmd) && + // gvCmdMgr->regCmd("CIRWrite", 4, new CirWriteCmd) && + // gvCmdMgr->regCmd("CIRMiter", 4, new CirMiterCmd) && + // gvCmdMgr->regCmd("CIREFFort", 6, new CirEffortCmd)); } -enum CirCmdState -{ - // Order matters! Do not change the order!! - CIRINIT, - CIRREAD, - CIROPT, - CIRSTRASH, - CIRSIMULATE, - CIRFRAIG, - // dummy end - CIRCMDTOT +enum CirCmdState { + // Order matters! Do not change the order!! + CIRINIT, + CIRREAD, + CIROPT, + CIRSTRASH, + CIRSIMULATE, + CIRFRAIG, + // dummy end + CIRCMDTOT }; static CirCmdState curCmd = CIRINIT; //---------------------------------------------------------------------- -// CIRRead <(string fileName)> [-Replace] +// CIRRead <-Verilog | -Aiger> <(string fileName)> [-Replace] //---------------------------------------------------------------------- -GVCmdExecStatus -CirReadCmd::exec(const string& option) -{ - // check option - vector options; - GVCmdExec::lexOptions(option, options); - CirFileType fileType = VERILOG; - - if (options.empty()) - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, ""); - - bool doReplace = false; - string fileName; - for (size_t i = 0, n = options.size(); i < n; ++i) { - if (myStrNCmp("-Replace", options[i], 2) == 0) { - if (doReplace) return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA,options[i]); - doReplace = true; - } - else if (myStrNCmp("-Aiger", options[i], 1) == 0) { - fileType = AIGER; - } - else { - if (fileName.size()) - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); - fileName = options[i]; - } - } - - if (cirMgr != 0) { - if (doReplace) { - cerr << "Note: original circuit is replaced..." << endl; - curCmd = CIRINIT; - delete cirMgr; cirMgr = 0; - } - else { - cerr << "Error: circuit already exists!!" << endl; - return GV_CMD_EXEC_ERROR; - } - } - cirMgr = new CirMgr; - cirMgr->readCirFromAbc(fileName, fileType); - - // curCmd = CIRREAD; - - return GV_CMD_EXEC_DONE; +GVCmdExecStatus CirReadCmd::exec(const string& option) { + // check option + vector options; + GVCmdExec::lexOptions(option, options); + CirFileType fileType = VERILOG; + + if (options.empty()) + return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, ""); + + bool doReplace = false; + string fileName; + for (size_t i = 0, n = options.size(); i < n; ++i) { + if (myStrNCmp("-Replace", options[i], 2) == 0) { + if (doReplace) return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[i]); + doReplace = true; + } else if (myStrNCmp("-Verilog", options[i], 1) == 0) { + fileType = VERILOG; + } else if (myStrNCmp("-Aiger", options[i], 1) == 0) { + fileType = AIGER; + } else { + if (fileName.size()) + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); + fileName = options[i]; + } + } + + if (cirMgr != 0) { + if (doReplace) { + cerr << "Note: original circuit is replaced..." << endl; + curCmd = CIRINIT; + delete cirMgr; + cirMgr = 0; + } else { + cerr << "Error: circuit already exists!!" << endl; + return GV_CMD_EXEC_ERROR; + } + } + cirMgr = new CirMgr; + cirMgr->readCirFromAbc(fileName, fileType); + // curCmd = CIRREAD; + + return GV_CMD_EXEC_DONE; } -void -CirReadCmd::usage(const bool& verbose) const -{ - gvMsg(GV_MSG_IFO) << "Usage: CIRRead <(string fileName)> [-Replace]" << endl; +void CirReadCmd::usage(const bool& verbose) const { + gvMsg(GV_MSG_IFO) << "Usage: CIRRead <-Verilog | -Aiger> <(string fileName)> [-Replace]" << endl; } -void -CirReadCmd::help() const -{ - cout << setw(15) << left << "CIRRead: " - << "read in a circuit and construct the netlist" << endl; +void CirReadCmd::help() const { + cout << setw(15) << left << "CIRRead: read in a circuit and construct the netlist" << endl; } //---------------------------------------------------------------------- // CIRPrint [-Summary | -Netlist | -PI | -PO | -FLoating | -FECpairs] //---------------------------------------------------------------------- GVCmdExecStatus -CirPrintCmd::exec(const string& option) -{ - // check option - string token; - GVCmdExec::lexSingleOption(option, token); - - if (!cirMgr) { - cerr << "Error: circuit is not yet constructed!!" << endl; - return GV_CMD_EXEC_ERROR; - } - if (token.empty() || myStrNCmp("-Summary", token, 2) == 0) - cirMgr->printSummary(); - else if (myStrNCmp("-Netlist", token, 2) == 0) - cirMgr->printNetlist(); - else if (myStrNCmp("-PI", token, 3) == 0) - cirMgr->printPIs(); - else if (myStrNCmp("-PO", token, 3) == 0) - cirMgr->printPOs(); - else if (myStrNCmp("-FLoating", token, 3) == 0) - cirMgr->printFloatGates(); - else if (myStrNCmp("-FECpairs", token, 4) == 0) - cirMgr->printFECPairs(); - else - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); - - return GV_CMD_EXEC_DONE; +CirPrintCmd::exec(const string& option) { + // check option + string token; + GVCmdExec::lexSingleOption(option, token); + + if (!cirMgr) { + cerr << "Error: circuit is not yet constructed!!" << endl; + return GV_CMD_EXEC_ERROR; + } + if (token.empty() || myStrNCmp("-Summary", token, 2) == 0) + cirMgr->printSummary(); + else if (myStrNCmp("-Netlist", token, 2) == 0) + cirMgr->printNetlist(); + else if (myStrNCmp("-PI", token, 3) == 0) + cirMgr->printPIs(); + else if (myStrNCmp("-PO", token, 3) == 0) + cirMgr->printPOs(); + else if (myStrNCmp("-FLoating", token, 3) == 0) + cirMgr->printFloatGates(); + else if (myStrNCmp("-FECpairs", token, 4) == 0) + cirMgr->printFECPairs(); + else + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); + + return GV_CMD_EXEC_DONE; } -void -CirPrintCmd::usage(const bool& verbose) const -{ - gvMsg(GV_MSG_IFO) << "Usage: CIRPrint [-Summary | -Netlist | -PI | -PO | -FLoating " - << "| -FECpairs]" << endl; +void CirPrintCmd::usage(const bool& verbose) const { + gvMsg(GV_MSG_IFO) << "Usage: CIRPrint [-Summary | -Netlist | -PI | -PO | -FLoating | -FECpairs]" << endl; } -void -CirPrintCmd::help() const -{ - cout << setw(15) << left << "CIRPrint: " << "print circuit\n"; +void CirPrintCmd::help() const { + cout << setw(15) << left << "CIRPrint: print circuit\n "; } //---------------------------------------------------------------------- // CIRGate <<(int gateId)> [<-FANIn | -FANOut><(int level)>]> //---------------------------------------------------------------------- GVCmdExecStatus -CirGateCmd::exec(const string& option) -{ - if (!cirMgr) { - cerr << "Error: circuit has not been read!!" << endl; - return GV_CMD_EXEC_ERROR; - } - - // check option - vector options; - GVCmdExec::lexOptions(option, options); - - if (options.empty()) - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, ""); - - int gateId = -1, level = 0; - bool doFanin = false, doFanout = false; - CirGate* thisGate = 0; - for (size_t i = 0, n = options.size(); i < n; ++i) { - bool checkLevel = false; - if (myStrNCmp("-FANIn", options[i], 5) == 0) { - if (doFanin || doFanout) - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); - doFanin = true; - checkLevel = true; - } - else if (myStrNCmp("-FANOut", options[i], 5) == 0) { - if (doFanin || doFanout) - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); - doFanout = true; - checkLevel = true; - } - else if (!thisGate) { - if (!myStr2Int(options[i], gateId) || gateId < 0) +CirGateCmd::exec(const string& option) { + if (!cirMgr) { + cerr << "Error: circuit has not been read!!" << endl; + return GV_CMD_EXEC_ERROR; + } + + // check option + vector options; + GVCmdExec::lexOptions(option, options); + + if (options.empty()) + return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, ""); + + int gateId = -1, level = 0; + bool doFanin = false, doFanout = false; + CirGate* thisGate = 0; + for (size_t i = 0, n = options.size(); i < n; ++i) { + bool checkLevel = false; + if (myStrNCmp("-FANIn", options[i], 5) == 0) { + if (doFanin || doFanout) + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); + doFanin = true; + checkLevel = true; + } else if (myStrNCmp("-FANOut", options[i], 5) == 0) { + if (doFanin || doFanout) + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); + doFanout = true; + checkLevel = true; + } else if (!thisGate) { + if (!myStr2Int(options[i], gateId) || gateId < 0) + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); + thisGate = cirMgr->getGate(gateId); + if (!thisGate) { + cerr << "Error: Gate(" << gateId << ") not found!!" << endl; + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); + } + } else if (thisGate) + return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[i]); + else return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); - thisGate = cirMgr->getGate(gateId); - if (!thisGate) { - cerr << "Error: Gate(" << gateId << ") not found!!" << endl; - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); - } - } - else if (thisGate) - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[i]); - else - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); - if (checkLevel) { - if (++i == n) - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, options[i-1]); - if (!myStr2Int(options[i], level) || level < 0) - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); - checkLevel = true; - } - } - - if (!thisGate) { - cerr << "Error: Gate id is not specified!!" << endl; - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, options.back()); - } - - if (doFanin) - thisGate->reportFanin(level); - else if (doFanout) - thisGate->reportFanout(level); - else - thisGate->reportGate(); - - return GV_CMD_EXEC_DONE; + if (checkLevel) { + if (++i == n) + return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, options[i - 1]); + if (!myStr2Int(options[i], level) || level < 0) + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); + checkLevel = true; + } + } + + if (!thisGate) { + cerr << "Error: Gate id is not specified!!" << endl; + return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, options.back()); + } + + if (doFanin) + thisGate->reportFanin(level); + else if (doFanout) + thisGate->reportFanout(level); + else + thisGate->reportGate(); + + return GV_CMD_EXEC_DONE; } -void -CirGateCmd::usage(const bool& verbose) const -{ - gvMsg(GV_MSG_IFO) << "Usage: CIRGate <<(int gateId)> [<-FANIn | -FANOut><(int level)>]>" - << endl; +void CirGateCmd::usage(const bool& verbose) const { + gvMsg(GV_MSG_IFO) << "Usage: CIRGate <<(int gateId)> [<-FANIn | -FANOut><(int level)>]>" << endl; } -void -CirGateCmd::help() const -{ - cout << setw(15) << left << "CIRGate: " << "report a gate\n"; +void CirGateCmd::help() const { + cout << setw(15) << left << "CIRGate: report a gate\n"; } // //---------------------------------------------------------------------- @@ -430,7 +406,7 @@ CirGateCmd::help() const // cirMgr->fileSim(patternFile); // cirMgr->setSimLog(0); // curCmd = CIRSIMULATE; - + // return GV_CMD_EXEC_DONE; // } @@ -512,7 +488,7 @@ CirGateCmd::help() const // ofstream outfile; // for (size_t i = 0, n = options.size(); i < n; ++i) { // if (myStrNCmp("-Output", options[i], 2) == 0) { -// if (hasFile) +// if (hasFile) // return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[i]); // if (++i == n) // return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, options[i-1]); @@ -591,12 +567,12 @@ CirGateCmd::help() const // cerr << "Error: numbers of PIs are different!!" << endl; // delete cm[0]; delete cm[1]; cirMgr = 0; // return GV_CMD_EXEC_ERROR; -// } +// } // if (cm[0]->getNumPOs() != cm[1]->getNumPOs()) { // cerr << "Error: numbers of POs are different!!" << endl; // delete cm[0]; delete cm[1]; cirMgr = 0; // return GV_CMD_EXEC_ERROR; -// } +// } // cirMgr = new CirMgr; // if (!cirMgr->createMiter(cm[0], cm[1])) { @@ -647,13 +623,12 @@ CirGateCmd::help() const // void // CirEffortCmd::usage(const bool& verbose) const -// { +// { // gvMsg(GV_MSG_IFO) << "Usage: CIREFFort <(int effortLimit)>" << endl; // } // void // CirEffortCmd::help() const -// { +// { // cout << setw(15) << left << "CIREFFort: " << "set SAT proof effort\n"; // } - diff --git a/src/cir/cirMgr.cpp b/src/cir/cirMgr.cpp index cafe4779..45252b45 100644 --- a/src/cir/cirMgr.cpp +++ b/src/cir/cirMgr.cpp @@ -747,19 +747,20 @@ CirMgr::printSummary() const cout << endl; cout << "Circuit Statistics" << endl << "==================" << endl; - unsigned tot = 0; - tot += _numDecl[PI]; + unsigned tot = _totGateList.size(); + unsigned sum = 0; + sum += _piList.size(); cout << " " << setw(7) << left << "PI" - << setw(7) << right << _numDecl[PI] << endl; - tot += _numDecl[PO]; + << setw(7) << right << _piList.size() << endl; + sum += _poList.size(); cout << " " << setw(7) << left << "PO" - << setw(7) << right << _numDecl[PO] << endl; - tot += _numDecl[LATCH]; + << setw(7) << right << _poList.size() << endl; + sum += _roList.size(); cout << " " << setw(7) << left << "LATCH" - << setw(7) << right << _numDecl[LATCH] << endl; - tot += _numDecl[AIG]; + << setw(7) << right << _roList.size() << endl; + // tot += _numDecl[AIG]; cout << " " << setw(7) << left << "AIG" - << setw(7) << right << _numDecl[AIG] << endl; + << setw(7) << right << tot - sum << endl; cout << "------------------" << endl; cout << " Total " << setw(7) << right << tot << endl; } diff --git a/src/cir/cirMgr.h b/src/cir/cirMgr.h index 0ce7f08e..29a7e3b9 100644 --- a/src/cir/cirMgr.h +++ b/src/cir/cirMgr.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -105,22 +106,25 @@ class CirMgr void writeGate(ostream&, CirGate*) const; // Member functions about flags - // for hidden command bool createMiter(CirMgr*, CirMgr*); static CirGate *_const0; - // --- MODIFICATION FOR SoCV HW5 --- - CirGate *_const1; - void readCirFromAbc(string fileName, CirFileType fileType); + // MODIFICATION FOR SOCV HOMEWORK void initCir(Gia_Man_t* pGia, const CirFileType& type); - void buildNtkBdd(); void buildBdd(CirGate* gate); - void dfsOrder(vector& nets); + void buildNtkBdd(); + void readCirFromAbc(string fileName, CirFileType fileType); void addTotGate(CirGate* gate){_totGateList.push_back(gate);}; + // void parseAigMapping(Gia_Man_t* pGia, map& id2Name); const bool setBddOrder(const bool& file); - CirGate* createGate(unsigned id, GateType type); - // --- MODIFICATION FOR SoCV HW5 --- + // CirGate* createGate(const GateType& type); + CirGate* createNotGate(CirGate* in0); + CirGate* createAndGate(CirGate* in0, CirGate* in1); + CirGate* createOrGate(CirGate* in0, CirGate* in1); + CirGate* createXorGate(CirGate* in0, CirGate* in1); + CirGate* _const1; + private: unsigned _numDecl[TOT_PARSE_PORTS]; mutable unsigned _flag; diff --git a/src/cmd/gvCmdMgr.cpp b/src/cmd/gvCmdMgr.cpp index 402363b2..7c426676 100644 --- a/src/cmd/gvCmdMgr.cpp +++ b/src/cmd/gvCmdMgr.cpp @@ -266,17 +266,17 @@ GVCmdMgr::execOneCmd() { // Check command types if (e) { GVCmdType cmdType = e->getGVCmdType(); - if (getPrompt().find("vrf") != string::npos) { - if (_vrfMode.find(cmdType) == _vrfMode.end()) { - cout << "Please switch to \"SETUP MODE\" !!" << endl; - return GV_CMD_EXEC_NOP; - } - } else { - if (_setupMode.find(cmdType) == _setupMode.end()) { - cout << "Please switch to \"VRF MODE\" !!" << endl; - return GV_CMD_EXEC_NOP; - } - } + // if (getPrompt().find("vrf") != string::npos) { + // if (_vrfMode.find(cmdType) == _vrfMode.end()) { + // cout << "Please switch to \"SETUP MODE\" !!" << endl; + // return GV_CMD_EXEC_NOP; + // } + // } else { + // if (_setupMode.find(cmdType) == _setupMode.end()) { + // cout << "Please switch to \"VRF MODE\" !!" << endl; + // return GV_CMD_EXEC_NOP; + // } + // } } if (e) return e->exec(option); diff --git a/src/itp/gvSatCmd.cpp b/src/itp/gvSatCmd.cpp index 5af8a116..6f63d2d1 100644 --- a/src/itp/gvSatCmd.cpp +++ b/src/itp/gvSatCmd.cpp @@ -68,7 +68,7 @@ SATVerifyItpCmd::exec(const string& option) { monitor->setIn0(gate->getIn0Gate(), gate->getIn0().isInv()); // monitor->setIn1(cirMgr->_const0, true); monitor->setIn1(cirMgr->_const1, false); - satMgr->verifyPropertyItp("monitor", monitor); + satMgr->verifyPropertyItp(gate->getName(), monitor); // Ref // satMgr->verifyPropertyItp("monitor", gate->getIn0Gate()); diff --git a/src/itp/gvSatMgr.cpp b/src/itp/gvSatMgr.cpp index 54dd5128..1122608b 100644 --- a/src/itp/gvSatMgr.cpp +++ b/src/itp/gvSatMgr.cpp @@ -191,8 +191,9 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { R = I; S = getItp(); for (; k < pRes.getMaxDepth(); ++k) { + // DEBUG - cout << "[LOG] "<< "i = " << i << " k = " << k << endl; + // cout << "[LOG] "<< "i = " << i << " k = " << k << endl; gvSatSolver->assumeRelease(); gvSatSolver->addBoundedVerifyData(S, 0); @@ -217,38 +218,14 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { } else num_clauses = getNumClauses(); S = getItp(); // see if Si or Ri-1 equals to Ri - // tmp2 = ~gvNtkMgr->createNet(); - // tmp3 = ~gvNtkMgr->createNet(); - // tmp4 = ~gvNtkMgr->createNet(); - // R_prime = ~gvNtkMgr->createNet(); - tmp1 = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmp1); - tmp2 = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmp2); - tmp3 = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmp3); - tmp4 = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmp4); - tmp5 = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(tmp5); - R_prime = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(R_prime); - gvSatSolver->resizeNtkData(6); - - // gvNtkMgr->createGVAndGate(R_prime, ~R, ~S); // or(R, S) - // Equal to ... - tmp1->setIn0(R, true); tmp1->setIn1(S, true); - R_prime->setIn0(tmp1, true); R_prime->setIn1(cirMgr->_const1, false); //R_prime->setIn1(cirMgr->_const0, true); - // gvNtkMgr->createGVAndGate(tmp2, ~R, R_prime); - // Equal to ... - tmp2->setIn0(R, true); tmp2->setIn1(R_prime,false); - // gvNtkMgr->createGVAndGate(tmp3, R, ~R_prime); - // Equal to ... - tmp3->setIn0(R, false); tmp3->setIn1(R_prime, true); - // gvNtkMgr->createGVAndGate(tmp4, tmp2, tmp3); // tmp4 = R xor R_prime - // Equal to ... - tmp4->setIn0(tmp2, true); tmp4->setIn1(tmp3, true); - // INV - tmp5->setIn0(tmp4, true); tmp5->setIn1(cirMgr->_const1, false); //tmp5->setIn1(cirMgr->_const0, true); - - // gvSatSolver->addBoundedVerifyData(tmp4, 0); + + unsigned gateSize = cirMgr->getNumTots(); + R_prime = cirMgr->createOrGate(R,S); + tmp5 = cirMgr->createXorGate(R,R_prime); + gvSatSolver->resizeNtkData(cirMgr->getNumTots() - gateSize); + gvSatSolver->addBoundedVerifyData(tmp5, 0); gvSatSolver->assumeRelease(); - // gvSatSolver->assumeProperty(tmp4, false, 0); // assume R xor R_prime is true gvSatSolver->assumeProperty(tmp5, false, 0); // assume R xor R_prime is true gvSatSolver->simplify(); if (!gvSatSolver->assump_solve()) // USAT @@ -566,28 +543,19 @@ CirGate* SATMgr::buildItp(const string& proofName) const { Reader rdr; // records - // map claItpLookup; map claItpLookup; vector clausePos; vector usedClause; // ntk - // uint32_t netSize = gvNtkMgr->getNetSize(); uint32_t netSize = cirMgr->getNumTots(); // temperate variables - // GVNetId nId, nId1, nId2; CirGate* nId; CirGate* nId1; CirGate* nId2; int i, cid, tmp, idx, tmp_cid; // const 1 & const 0 - // GVNetId CONST0, CONST1; - // CONST0 = gvNtkMgr->getConst(0); - // CONST1 = ~CONST0; CirGate* CONST0 = cirMgr->_const0; CirGate* CONST1 = cirMgr->_const1; - // CirGate* CONST1 = new CirAigGate(cirMgr->getNumTots(),0); - // cirMgr->addTotGate(CONST1); - // CONST1->setIn0(cirMgr->_const0, true); CONST1->setIn1(cirMgr->_const0, true); rdr.open(proofName.c_str()); retrieveProof(rdr, clausePos, usedClause); @@ -609,25 +577,8 @@ SATMgr::buildItp(const string& proofName) const { assert(_var2Net.find(idx >> 1) != _var2Net.end()); nId = (_var2Net.find(idx >> 1))->second; nId1 = (_var2Net.find(idx >> 1))->second; - // Not Sure ... - if ((idx & 1) == 1) { - CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(tmpId); - tmpId->setIn0(nId1, true); - // tmpId->setIn1(cirMgr->_const0, true); - tmpId->setIn1(CONST1, false); - nId1 = tmpId; - // nId1 = ~nId1; - } - if ((idx & 1) == 1) { - CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(tmpId); - tmpId->setIn0(nId, true); - // tmpId->setIn1(cirMgr->_const0, true); - tmpId->setIn1(CONST1, false); - // nId = ~nId; - nId = tmpId; - } + if ((idx & 1) == 1) nId1 = cirMgr->createNotGate(nId1); + if ((idx & 1) == 1) nId = cirMgr->createNotGate(nId); while (1) { tmp = rdr.get64(); if (tmp == 0) break; @@ -635,42 +586,14 @@ SATMgr::buildItp(const string& proofName) const { if (_varGroup[idx >> 1] == COMMON) { assert(_var2Net.find(idx >> 1) != _var2Net.end()); nId2 = (_var2Net.find(idx >> 1))->second; - // NOT SURE ... - if ((idx & 1) == 1) { - CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(tmpId); - tmpId->setIn0(nId2, true); - // tmpId->setIn1(cirMgr->_const0, true); - tmpId->setIn1(CONST1, false); - // nId2 = ~nId2; - nId2 = tmpId; - } + if ((idx & 1) == 1) nId2 = cirMgr->createNotGate(nId2); // or // nId = ~gvNtkMgr->createNet(); // gvNtkMgr->createGVAndGate(nId, ~nId1, ~nId2); // nId1 = nId; // --- - CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(tmpId); - tmpId->setIn0(nId1, true); - tmpId->setIn1(nId2, true); - nId = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(nId); - nId->setIn0(tmpId, true); - // nId->setIn1(cirMgr->_const0, true); - nId->setIn1(CONST1, false); + nId = cirMgr->createOrGate(nId1, nId2); nId1 = nId; - // --- - // nId = new CirAigGate(cirMgr->getNumTots(), 0); - // cirMgr->addTotGate(nId); - // nId->setIn0(nId1, true); - // nId->setIn1(nId2, true); - // // not finish or gate !! - // CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); - // cirMgr->addTotGate(tmpId); - // tmpId->setIn0(nId, true); - // tmpId->setIn1(cirMgr->_const0, true); - // nId1 = tmpId; } } } else { @@ -711,26 +634,19 @@ SATMgr::buildItp(const string& proofName) const { // gvNtkMgr->createGVAndGate(nId, ~nId1, ~nId2); // nId1 = nId; // --- - CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(tmpId); - tmpId->setIn0(nId1,true); - tmpId->setIn1(nId2, true); - nId = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(nId); - nId->setIn0(tmpId,true); - // nId->setIn1(cirMgr->_const0, true); - nId->setIn1(CONST1, false); - nId1 = nId; - // --- - // nId = new CirAigGate(cirMgr->getNumTots(), 0); - // cirMgr->addTotGate(nId); - // nId->setIn0(nId1, true); - // nId->setIn1(nId2, true); // CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); // cirMgr->addTotGate(tmpId); - // tmpId->setIn0(nId, true); - // tmpId->setIn1(cirMgr->_const0, true); - // nId1 = tmpId; + // tmpId->setIn0(nId1,true); + // tmpId->setIn1(nId2, true); + // nId = new CirAigGate(cirMgr->getNumTots(), 0); + // cirMgr->addTotGate(nId); + // nId->setIn0(tmpId,true); + // // nId->setIn1(cirMgr->_const0, true); + // nId->setIn1(CONST1, false); + // nId1 = nId; + // --- + nId = cirMgr->createOrGate(nId1, nId2); + nId1 = nId; } } else { // Build AND Gate. if (nId1 == CONST0 || nId2 == CONST0) { @@ -747,10 +663,14 @@ SATMgr::buildItp(const string& proofName) const { // nId = gvNtkMgr->createNet(); // gvNtkMgr->createGVAndGate(nId, nId1, nId2); // nId1 = nId; - nId = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(nId); - nId->setIn0(nId1, false); - nId->setIn1(nId2, false); + // --- + // nId = new CirAigGate(cirMgr->getNumTots(), 0); + // cirMgr->addTotGate(nId); + // nId->setIn0(nId1, false); + // nId->setIn1(nId2, false); + // nId1 = nId; + // --- + nId = cirMgr->createAndGate(nId1, nId2); nId1 = nId; } } @@ -790,14 +710,6 @@ SatProofRes::reportCex(const CirGate* monitor, const GVNtkMgr* const ntk) const GVBitVecX dataValue; for (uint32_t i = 0; i <= _fired; ++i) { gvMsg(GV_MSG_IFO) << i << ": "; - // for (int j = ntk->getInoutSize() - 1; j >= 0; --j) { - // if (_satSolver->existVerifyData(ntk->getInout(j), i)) { - // dataValue = _satSolver->getDataValue(ntk->getInout(j), i); - // gvMsg(GV_MSG_IFO) << dataValue[0]; - // } else { - // gvMsg(GV_MSG_IFO) << 'x'; - // } - // } for (int j = cirMgr->getNumPIs() - 1; j >= 0; --j) { if (_satSolver->existVerifyData(cirMgr->getPi(j), i)) { dataValue = _satSolver->getDataValue(cirMgr->getPi(j), i); diff --git a/src/ntk/gvNtkCmd.cpp b/src/ntk/gvNtkCmd.cpp index bcdd35cf..a825a0bb 100644 --- a/src/ntk/gvNtkCmd.cpp +++ b/src/ntk/gvNtkCmd.cpp @@ -649,10 +649,6 @@ GVBlastNtkCmd ::exec(const string& option) { // construct GV network gvNtkMgr->createNetFromAbc(pFileName); - // BSETOrder - // cout << "TEST : Start to build BDD : \n"; - // gvNtkMgr->setBddOrder(true); - return GV_CMD_EXEC_DONE; } diff --git a/src/prove/proveCmd.cpp b/src/prove/proveCmd.cpp index 5db0c820..929bdc83 100644 --- a/src/prove/proveCmd.cpp +++ b/src/prove/proveCmd.cpp @@ -221,7 +221,7 @@ PCheckPropertyCmd::exec(const string& option) { assert(monitor()); // bddMgrV->runPCheckProperty(gvNtkMgr->getNetNameFromId(netId.id), monitor); string mStr = "monitor"; - bddMgrV->runPCheckProperty(mStr, monitor); + bddMgrV->runPCheckProperty(cirMgr->getPo(num)->getName(), monitor); return GV_CMD_EXEC_DONE; } From 1836b4666abe3a2a04a36ed0e1812e8b0bd4977e Mon Sep 17 00:00:00 2001 From: hchchiu Date: Sun, 26 Nov 2023 06:15:09 +0800 Subject: [PATCH 012/307] Update yosys version --- src/abc/.depend.mak | 27 --- src/abc/gvAbcCmd.cpp | 51 ++--- src/bdd/.depend.mak | 35 --- src/bdd/bddCmd.cpp | 204 ++++++++--------- src/bdd/bddMgrV.cpp | 473 ++++++++++++++++++++------------------- src/cir/.depend.mak | 97 -------- src/cir/cirAig.cpp | 25 ++- src/cir/cirCmd.cpp | 19 +- src/cmd/.depend.mak | 5 - src/cmd/gvCmdComm.cpp | 2 +- src/cmd/gvCmdMgr.h | 209 +++++++++-------- src/eng/yosyss | 1 + src/ext/sim.so | Bin 817752 -> 817840 bytes src/itp/.depend.mak | 105 +-------- src/itp/gvSatCmd.cpp | 2 +- src/main/.depend.mak | 8 - src/main/main.cpp | 38 ++-- src/mod/.depend.mak | 32 --- src/mod/gvModCmd.cpp | 2 +- src/ntk/.depend.mak | 99 -------- src/ntk/gvNtkCmd.cpp | 2 +- src/prove/.depend.mak | 67 ------ src/prove/proveCmd.cpp | 2 +- src/sim/.depend.mak | 34 --- src/sim/gvSimCmd.cpp | 2 +- src/vrf/.depend.mak | 29 --- src/vrf/gvVrfCmd.cpp | 2 +- src/yosys/.depend.mak | 12 + src/yosys/.extheader.mak | 7 + src/yosys/Makefile | 5 + src/yosys/gvYosysCmd.cpp | 59 +++++ src/yosys/gvYosysCmd.h | 8 + src/yosys/gvYosysMgr.cpp | 31 +++ src/yosys/gvYosysMgr.h | 26 +++ 34 files changed, 659 insertions(+), 1061 deletions(-) create mode 120000 src/eng/yosyss create mode 100644 src/yosys/.depend.mak create mode 100644 src/yosys/.extheader.mak create mode 100644 src/yosys/Makefile create mode 100644 src/yosys/gvYosysCmd.cpp create mode 100644 src/yosys/gvYosysCmd.h create mode 100644 src/yosys/gvYosysMgr.cpp create mode 100644 src/yosys/gvYosysMgr.h diff --git a/src/abc/.depend.mak b/src/abc/.depend.mak index 3db860d4..1e24bc4c 100644 --- a/src/abc/.depend.mak +++ b/src/abc/.depend.mak @@ -1,30 +1,3 @@ -gvAbcCmd.o: gvAbcCmd.cpp gvAbcCmd.h ../../include/gvCmdMgr.h gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - gvAbcNtk.h ../../include/gvModMgr.h ../../include/gvCmdMgr.h \ - ../../include/gvMsg.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h gvAbcMgr.o: gvAbcMgr.cpp gvAbcMgr.h ../../include/base/abc/abc.h \ ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ diff --git a/src/abc/gvAbcCmd.cpp b/src/abc/gvAbcCmd.cpp index 0ecf6174..e57ede8e 100644 --- a/src/abc/gvAbcCmd.cpp +++ b/src/abc/gvAbcCmd.cpp @@ -2,15 +2,18 @@ #define GV_ABC_CMD_C #include "gvAbcCmd.h" + +#include + +#include + #include "gvAbcMgr.h" #include "gvModMgr.h" #include "gvMsg.h" #include "util.h" -#include -#include -bool -GVinitAbcCmd() { + +bool initAbcCmd() { if (abcMgr) delete abcMgr; abcMgr = new AbcMgr; return (gvCmdMgr->regCmd("ABCRead", 4, new GVABCReadCmd), @@ -23,15 +26,17 @@ GVinitAbcCmd() { //---------------------------------------------------------------------- GVCmdExecStatus -GVABCReadCmd ::exec(const string& option) { +GVABCReadCmd::exec(const string& option) { vector options; - string fileName = ""; + string fileName = ""; GVCmdExec::lexOptions(option, options); size_t n = options.size(); for (size_t i = 0; i < n; ++i) { const string& token = options[i]; - if (fileName == "") fileName = options[i]; - else return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); + if (fileName == "") + fileName = options[i]; + else + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); } if (fileName == "") return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, @@ -40,13 +45,11 @@ GVABCReadCmd ::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -GVABCReadCmd ::usage(const bool& verbose) const { +void GVABCReadCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: ABCRead " << endl; } -void -GVABCReadCmd ::help() const { +void GVABCReadCmd::help() const { gvMsg(GV_MSG_IFO) << setw(20) << left << "ABCRead: " << "Read netlist by ABC." << endl; } @@ -56,29 +59,29 @@ GVABCReadCmd ::help() const { //---------------------------------------------------------------------- GVCmdExecStatus -GVABCPrintCmd ::exec(const string& option) { +GVABCPrintCmd::exec(const string& option) { vector options; GVCmdExec::lexOptions(option, options); - bool basic = false, verbose = false; + bool basic = false, verbose = false; size_t n = options.size(); if (options.size() > 1) return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[1]); else if (options.size()) { - if (myStrNCmp("-Verbose", options[0], 2) == 0) verbose = true; - else return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); + if (myStrNCmp("-Verbose", options[0], 2) == 0) + verbose = true; + else + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); } (abcMgr->get_abcNtkMgr())->printSummary(); return GV_CMD_EXEC_DONE; } -void -GVABCPrintCmd ::usage(const bool& verbose) const { +void GVABCPrintCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: ABCPrint " << endl; } -void -GVABCPrintCmd ::help() const { +void GVABCPrintCmd::help() const { gvMsg(GV_MSG_IFO) << setw(20) << left << "ABCPrint: " << "Print netlist information." << endl; } @@ -88,7 +91,7 @@ GVABCPrintCmd ::help() const { //---------------------------------------------------------------------- GVCmdExecStatus -GVABCOriginalCmd ::exec(const string& option) { +GVABCOriginalCmd::exec(const string& option) { vector options; GVCmdExec::lexOptions(option, options); size_t n = options.size(); @@ -107,13 +110,11 @@ GVABCOriginalCmd ::exec(const string& option) { Cmd_CommandExecute(abcMgr->get_Abc_Frame_t(), Command); } -void -GVABCOriginalCmd ::usage(const bool& verbose) const { +void GVABCOriginalCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: ABCCMD " << endl; } -void -GVABCOriginalCmd ::help() const { +void GVABCOriginalCmd::help() const { gvMsg(GV_MSG_IFO) << setw(20) << left << "ABCCMD: " << "Directly call ABC's command." << endl; } diff --git a/src/bdd/.depend.mak b/src/bdd/.depend.mak index 09ce4e74..eb07f82f 100644 --- a/src/bdd/.depend.mak +++ b/src/bdd/.depend.mak @@ -1,36 +1 @@ bddNodeV.o: bddNodeV.cpp bddNodeV.h bddMgrV.h myHash.h -bddMgrV.o: bddMgrV.cpp bddNodeV.h bddMgrV.h myHash.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -bddCmd.o: bddCmd.cpp bddCmd.h ../../include/gvCmdMgr.h bddMgrV.h myHash.h \ - bddNodeV.h ../../include/gvMsg.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/bdd/bddCmd.cpp b/src/bdd/bddCmd.cpp index 29d362d8..c62a6c5a 100644 --- a/src/bdd/bddCmd.cpp +++ b/src/bdd/bddCmd.cpp @@ -7,21 +7,23 @@ ****************************************************************************/ #include "bddCmd.h" -#include "bddMgrV.h" -#include "gvMsg.h" -#include "gvNtk.h" -#include "cirMgr.h" -#include "util.h" + #include #include #include #include #include +#include "bddMgrV.h" +#include "cirGate.h" +#include "cirMgr.h" +#include "gvMsg.h" +#include "gvNtk.h" +#include "util.h" + using namespace std; -bool -GVinitBddCmd() { +bool initBddCmd() { if (bddMgrV) delete bddMgrV; bddMgrV = new BddMgrV; return (gvCmdMgr->regCmd("BRESET", 6, new BResetCmd) && @@ -44,14 +46,13 @@ GVinitBddCmd() { return true; } -bool -isValidBddName(const string& str) { +bool isValidBddName(const string& str) { int id; return (isValidVarName(str) || (myStr2Int(str, id) && id >= 0)); } extern BddNodeV getBddNodeV(const string& bddName); -bool setBddOrder = false; +bool setBddOrder = false; //---------------------------------------------------------------------- // BRESET <(size_t nSupports)> <(size_t hashSize)> <(size_t cacheSize)> @@ -81,15 +82,13 @@ BResetCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BResetCmd::usage(const bool& verbose) const { +void BResetCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BRESET <(size_t nSupports)> <(size_t hashSize)> " << "<(size_t cacheSize)>" << endl; } -void -BResetCmd::help() const { +void BResetCmd::help() const { cout << setw(20) << left << "BRESET: " << "BDD reset" << endl; } @@ -117,19 +116,18 @@ BSetVarCmd::exec(const string& option) { !bddMgrV->addBddNodeV(options[1], n())) return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); return GV_CMD_EXEC_DONE; - } else return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); + } else + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); return GV_CMD_EXEC_DONE; } -void -BSetVarCmd::usage(const bool& verbose) const { +void BSetVarCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BSETVar <(size_t level)> <(string varName)>" << endl; } -void -BSetVarCmd::help() const { +void BSetVarCmd::help() const { cout << setw(20) << left << "BSETVar: " << "BDD set a variable name for a support" << endl; } @@ -159,14 +157,12 @@ BInvCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BInvCmd::usage(const bool& verbose) const { +void BInvCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BINV <(string varName)> <(string bddName)>" << endl; } -void -BInvCmd::help() const { +void BInvCmd::help() const { cout << setw(20) << left << "BINV: " << "BDD Inv" << endl; } @@ -200,14 +196,12 @@ BAndCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BAndCmd::usage(const bool& verbose) const { +void BAndCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BAND <(string varName)> <(string bddName)>..." << endl; } -void -BAndCmd::help() const { +void BAndCmd::help() const { cout << setw(20) << left << "BAND: " << "BDD And" << endl; } @@ -241,14 +235,12 @@ BOrCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BOrCmd::usage(const bool& verbose) const { +void BOrCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BOR <(string varName)> <(string bddName)>..." << endl; } -void -BOrCmd::help() const { +void BOrCmd::help() const { cout << setw(20) << left << "BOR: " << "BDD Or" << endl; } @@ -283,14 +275,12 @@ BNandCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BNandCmd::usage(const bool& verbose) const { +void BNandCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BNAND <(string varName)> <(string bddName)>..." << endl; } -void -BNandCmd::help() const { +void BNandCmd::help() const { cout << setw(20) << left << "BNAND: " << "BDD Nand" << endl; } @@ -325,14 +315,12 @@ BNorCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BNorCmd::usage(const bool& verbose) const { +void BNorCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BNOR <(string varName)> <(string bddName)>..." << endl; } -void -BNorCmd::help() const { +void BNorCmd::help() const { cout << setw(20) << left << "BNOR: " << "BDD Nor" << endl; } @@ -366,14 +354,12 @@ BXorCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BXorCmd::usage(const bool& verbose) const { +void BXorCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BXOR <(string varName)> <(string bddName)>..." << endl; } -void -BXorCmd::help() const { +void BXorCmd::help() const { cout << setw(20) << left << "BXOR: " << "BDD Xor" << endl; } @@ -408,14 +394,12 @@ BXnorCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BXnorCmd::usage(const bool& verbose) const { +void BXnorCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BXNOR <(string varName)> <(string bddName)>..." << endl; } -void -BXnorCmd::help() const { +void BXnorCmd::help() const { cout << setw(20) << left << "BXNOR: " << "BDD Xnor" << endl; } @@ -433,7 +417,8 @@ BCofactorCmd::exec(const string& option) { if (n > 3) return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[3]); bool posCof = false; - if (myStrNCmp("-Positive", options[0], 2) == 0) posCof = true; + if (myStrNCmp("-Positive", options[0], 2) == 0) + posCof = true; else if (myStrNCmp("-Negative", options[0], 2) != 0) return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); @@ -449,14 +434,12 @@ BCofactorCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BCofactorCmd::usage(const bool& verbose) const { +void BCofactorCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BCOFactor <-Positive | -Negative> <(string " "varName)> <(string bddName)>\n"; } -void -BCofactorCmd::help() const { +void BCofactorCmd::help() const { cout << setw(20) << left << "BCOFactor: " << "Retrieve BDD cofactor\n"; } @@ -489,14 +472,12 @@ BExistCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BExistCmd::usage(const bool& verbose) const { +void BExistCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BEXist <(size_t level)> <(string varName)> " "<(string bddName)>\n"; } -void -BExistCmd::help() const { +void BExistCmd::help() const { cout << setw(20) << left << "BEXist: " << "Perform BDD existential quantification\n"; } @@ -540,14 +521,12 @@ BCompareCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BCompareCmd::usage(const bool& verbose) const { +void BCompareCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BCOMpare <(string bddName)> <(string bddName)>" << endl; } -void -BCompareCmd::help() const { +void BCompareCmd::help() const { cout << setw(20) << left << "BCOMpare: " << "BDD comparison" << endl; } @@ -583,15 +562,13 @@ BSimulateCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BSimulateCmd::usage(const bool& verbose) const { +void BSimulateCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BSIMulate <(string bddName)> <(bit_string inputPattern)>" << endl; } -void -BSimulateCmd::help() const { +void BSimulateCmd::help() const { cout << setw(20) << left << "BSIMulate: " << "BDD simulation" << endl; } @@ -608,8 +585,8 @@ BReportCmd::exec(const string& option) { if (options.empty()) return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, ""); - bool doFile = false, doAddr = false, doRefCount = false; - string bddNodeVName, fileName; + bool doFile = false, doAddr = false, doRefCount = false; + string bddNodeVName, fileName; BddNodeV bnode; for (size_t i = 0, n = options.size(); i < n; ++i) { if (myStrNCmp("-File", options[i], 2) == 0) { @@ -619,7 +596,7 @@ BReportCmd::exec(const string& option) { return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, options[i - 1]); fileName = options[i]; - doFile = true; + doFile = true; } else if (myStrNCmp("-ADDRess", options[i], 5) == 0) { if (doAddr) return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[i]); @@ -649,24 +626,23 @@ BReportCmd::exec(const string& option) { if (!ofs) return GVCmdExec::errorOption(GV_CMD_OPT_FOPEN_FAIL, fileName); ofs << bnode << endl; - } else cout << bnode << endl; + } else + cout << bnode << endl; // always set to false afterwards - BddNodeV::_debugBddAddr = false; + BddNodeV::_debugBddAddr = false; BddNodeV::_debugRefCount = false; return GV_CMD_EXEC_DONE; } -void -BReportCmd::usage(const bool& verbose) const { +void BReportCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BREPort <(string bddName)> [-ADDRess] [-REFcount]\n " << " [-File <(string fileName)>]" << endl; } -void -BReportCmd::help() const { +void BReportCmd::help() const { cout << setw(20) << left << "BREPort: " << "BDD report node" << endl; } @@ -695,14 +671,11 @@ BDrawCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -BDrawCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BDRAW <(string bddName)> <(string fileName)>" - << endl; +void BDrawCmd::usage(const bool& verbose) const { + gvMsg(GV_MSG_IFO) << "Usage: BDRAW <(string bddName)> <(string fileName)>" << endl; } -void -BDrawCmd::help() const { +void BDrawCmd::help() const { cout << setw(20) << left << "BDRAW: " << "BDD graphic draw" << endl; } @@ -725,10 +698,13 @@ BSetOrderCmd::exec(const string& option) { return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[1]); } string token = options[0]; - bool file = false; - if (myStrNCmp("-File", token, 2) == 0) file = true; - else if (myStrNCmp("-RFile", token, 3) == 0) file = false; - else return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); + bool file = false; + if (myStrNCmp("-File", token, 2) == 0) + file = true; + else if (myStrNCmp("-RFile", token, 3) == 0) + file = false; + else + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); bddMgrV->restart(); // V3NtkHandler* const handler = v3Handler.getCurHandler(); @@ -736,15 +712,14 @@ BSetOrderCmd::exec(const string& option) { setBddOrder = cirMgr->setBddOrder(file); if (!setBddOrder) gvMsg(GV_MSG_ERR) << "Set BDD Variable Order Failed !!" << endl; - else gvMsg(GV_MSG_IFO) << "Set BDD Variable Order Succeed !!" << endl; + else + gvMsg(GV_MSG_IFO) << "Set BDD Variable Order Succeed !!" << endl; return GV_CMD_EXEC_DONE; } -void -BSetOrderCmd::usage(const bool& verbose) const { +void BSetOrderCmd::usage(const bool& verbose) const { gvMsg(GV_MSG_IFO) << "Usage: BSETOrder < -File | -RFile >" << endl; } -void -BSetOrderCmd::help() const { +void BSetOrderCmd::help() const { cout << setw(20) << left << "BSETOrder: " << "Set BDD variable Order From Circuit." << endl; } @@ -767,51 +742,54 @@ BConstructCmd::exec(const string& option) { return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[2]); } - bool isNet = false, isOutput = false; - if (myStrNCmp("-All", options[0], 2) == 0) cirMgr->buildNtkBdd(); - else if (myStrNCmp("-Netid", options[0], 2) == 0) isNet = true; - else if (myStrNCmp("-Output", options[0], 2) == 0) isOutput = true; - else return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); - if (isOutput || isNet) { + bool isGate = false, isOutput = false; + if (myStrNCmp("-All", options[0], 2) == 0) + cirMgr->buildNtkBdd(); + else if (myStrNCmp("-Gateid", options[0], 2) == 0) + isGate = true; + else if (myStrNCmp("-Output", options[0], 2) == 0) + isOutput = true; + else + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); + if (isOutput || isGate) { if (options.size() != 2) return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, options[0]); - int num = 0; + int num = 0; GVNetId netId; + CirGate* gate; if (!myStr2Int(options[1], num) || (num < 0)) return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); - if (isNet) { - if ((unsigned)num >= gvNtkMgr->getNetSize()) { - gvMsg(GV_MSG_ERR) - << "Net with Id " << num - << " does NOT Exist in Current Ntk !!" << endl; + if (isGate) { + // if ((unsigned)num >= gvNtkMgr->getNetSize()) { + if ((unsigned)num >= cirMgr->getNumTots()) { + gvMsg(GV_MSG_ERR) << "Gate with Id " << num << " does NOT Exist in Current Cir !!" << endl; return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } - netId = GVNetId::makeNetId(num, 0, gvNtkMgr->getGateType(gvNtkMgr->getGVNetId(num))); + // netId = GVNetId::makeNetId(num, 0, gvNtkMgr->getGateType(gvNtkMgr->getGVNetId(num))); + gate = cirMgr->getGate(num); } else if (isOutput) { - if ((unsigned)num >= gvNtkMgr->getOutputSize()) { - gvMsg(GV_MSG_ERR) - << "Output with Index " << num - << " does NOT Exist in Current Ntk !!" << endl; + // if ((unsigned)num >= gvNtkMgr->getOutputSize()) { + if ((unsigned)num >= cirMgr->getNumPOs()) { + gvMsg(GV_MSG_ERR) << "Output with Index " << num << " does NOT Exist in Current Cir !!" << endl; return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } - netId = gvNtkMgr->getOutput(num); + // netId = gvNtkMgr->getOutput(num); + gate = cirMgr->getPo(num); } - gvNtkMgr->buildBdd(netId); + // gvNtkMgr->buildBdd(netId); + cirMgr->buildBdd(gate); } return GV_CMD_EXEC_DONE; } -void -BConstructCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BConstruct <-Netid | -Output < " - "outputIndex > | -All > " +void BConstructCmd::usage(const bool& verbose) const { + gvMsg(GV_MSG_IFO) << "Usage: BConstruct <-Gateid | -Output | -All > " << endl; } -void -BConstructCmd::help() const { +void BConstructCmd::help() const { cout << setw(20) << left << "BConstruct: " << "Build BDD From Current Design." << endl; } diff --git a/src/bdd/bddMgrV.cpp b/src/bdd/bddMgrV.cpp index 3ff9d4ba..3428fb27 100644 --- a/src/bdd/bddMgrV.cpp +++ b/src/bdd/bddMgrV.cpp @@ -6,11 +6,13 @@ Copyright [ Copyleft(c) 2005-present LaDs(III), GIEE, NTU, Taiwan ] ****************************************************************************/ +#include "bddMgrV.h" + +#include #include #include -#include + #include "bddNodeV.h" -#include "bddMgrV.h" // #include "v3StrUtil.h" #include "util.h" @@ -19,7 +21,7 @@ using namespace std; //---------------------------------------------------------------------- // Global variables //---------------------------------------------------------------------- -BddMgrV* bddMgrV = 0; // new BddMgrV; +BddMgrV* bddMgrV = 0; // new BddMgrV; //---------------------------------------------------------------------- // External functions @@ -28,22 +30,22 @@ BddMgrV* bddMgrV = 0; // new BddMgrV; //---------------------------------------------------------------------- // static functions //---------------------------------------------------------------------- -static void swapBddNodeV(BddNodeV& f, BddNodeV& g) -{ - BddNodeV tmp = f; f = g; g = tmp; +static void swapBddNodeV(BddNodeV& f, BddNodeV& g) { + BddNodeV tmp = f; + f = g; + g = tmp; } //---------------------------------------------------------------------- // helper functions //---------------------------------------------------------------------- -BddNodeV getBddNodeV(const string& bddName) -{ - int id; - //if (v3Str2Int(bddName, id)) // bddName is an ID - if (myStr2Int(bddName, id)) // bddName is an ID - return bddMgrV->getBddNodeV(id); - else // bddNameis a name - return bddMgrV->getBddNodeV(bddName); +BddNodeV getBddNodeV(const string& bddName) { + int id; + // if (v3Str2Int(bddName, id)) // bddName is an ID + if (myStr2Int(bddName, id)) // bddName is an ID + return bddMgrV->getBddNodeV(id); + else // bddNameis a name + return bddMgrV->getBddNodeV(bddName); } //---------------------------------------------------------------------- @@ -52,160 +54,168 @@ BddNodeV getBddNodeV(const string& bddName) // _level = 0 ==> const 1 & const 0 // _level = 1 ~ nin ==> supports // -void -BddMgrV::init(size_t nin, size_t h, size_t c) -{ - reset(); - _uniqueTable.init(h); - _computedTable.init(c); - - // This must be called first - BddNodeV::setBddMgrV(this); - BddNodeVInt::_terminal = uniquify(0, 0, 0); - BddNodeV::_one = BddNodeV(BddNodeVInt::_terminal, BDD_POS_EDGEV); - BddNodeV::_zero = BddNodeV(BddNodeVInt::_terminal, BDD_NEG_EDGEV); - - _supports.reserve(nin+1); - _supports.push_back(BddNodeV::_one); - for (size_t i = 1; i <= nin; ++i) - _supports.push_back(BddNodeV(BddNodeV::_one(), BddNodeV::_zero(), i)); +void BddMgrV::init(size_t nin, size_t h, size_t c) { + reset(); + _uniqueTable.init(h); + _computedTable.init(c); + + // This must be called first + BddNodeV::setBddMgrV(this); + BddNodeVInt::_terminal = uniquify(0, 0, 0); + BddNodeV::_one = BddNodeV(BddNodeVInt::_terminal, BDD_POS_EDGEV); + BddNodeV::_zero = BddNodeV(BddNodeVInt::_terminal, BDD_NEG_EDGEV); + + _supports.reserve(nin + 1); + _supports.push_back(BddNodeV::_one); + for (size_t i = 1; i <= nin; ++i) + _supports.push_back(BddNodeV(BddNodeV::_one(), BddNodeV::_zero(), i)); } // Called by the BSETOrder command -void -BddMgrV::restart() -{ - size_t nin = _supports.size() - 1; - size_t h = _uniqueTable.numBuckets(); - size_t c = _computedTable.size(); - - init(nin, h, c); +void BddMgrV::restart() { + size_t nin = _supports.size() - 1; + size_t h = _uniqueTable.numBuckets(); + size_t c = _computedTable.size(); + + init(nin, h, c); } // This is a private function called by init() and restart() -void -BddMgrV::reset() -{ - _supports.clear(); - _bddArr.clear(); - _bddMap.clear(); - BddHash::iterator bi = _uniqueTable.begin(); - for (; bi != _uniqueTable.end(); ++bi) - delete (*bi).second; - _uniqueTable.reset(); - _computedTable.reset(); +void BddMgrV::reset() { + _supports.clear(); + _bddArr.clear(); + _bddMap.clear(); + BddHash::iterator bi = _uniqueTable.begin(); + for (; bi != _uniqueTable.end(); ++bi) + delete (*bi).second; + _uniqueTable.reset(); + _computedTable.reset(); } // [Note] Remeber to check "isNegEdge" when return BddNodeV!!!!! // BddNodeV -BddMgrV::ite(BddNodeV f, BddNodeV g, BddNodeV h) -{ - bool isNegEdge = false; // should only be flipped by "standardize()" +BddMgrV::ite(BddNodeV f, BddNodeV g, BddNodeV h) { + bool isNegEdge = false; // should only be flipped by "standardize()" #define DO_STD_ITE 1 // NOTE: make it '0' if you haven't done standardize()!! - standardize(f, g, h, isNegEdge); - - BddNodeV ret; - - // check terminal cases - if (checkIteTerminal(f, g, h, ret)) { - if (isNegEdge) ret = ~ret; - return ret; // no need to update tables - } - - // check computed table - // based on your definition of BddCacheKey, - // instantiate a BddCacheKey k (i.e. pass in proper data members) - // BddCacheKey k; // Change this line!! - BddCacheKeyV k(f(), g(), h()); - size_t ret_t; - if (_computedTable.read(k, ret_t)) { - if (isNegEdge) ret_t = ret_t ^ BDD_NEG_EDGEV; - return ret_t; - } - - // check top varaible - unsigned v = f.getLevel(); - if (g.getLevel() > v) - v = g.getLevel(); - if (h.getLevel() > v) - v = h.getLevel(); - - // recursion - BddNodeV fl = f.getLeftCofactor(v), - gl = g.getLeftCofactor(v), - hl = h.getLeftCofactor(v); - BddNodeV t = ite(fl, gl, hl); - - BddNodeV fr = f.getRightCofactor(v), - gr = g.getRightCofactor(v), - hr = h.getRightCofactor(v); - BddNodeV e = ite(fr, gr, hr); - - // get result - if (t == e) { - // update computed table - _computedTable.write(k, t()); - if (isNegEdge) t = ~t; - return t; - } - - // move bubble if necessary... ==> update isNedEdge - bool moveBubble = t.isNegEdge(); + standardize(f, g, h, isNegEdge); + + BddNodeV ret; + + // check terminal cases + if (checkIteTerminal(f, g, h, ret)) { + if (isNegEdge) ret = ~ret; + return ret; // no need to update tables + } + + // check computed table + // based on your definition of BddCacheKey, + // instantiate a BddCacheKey k (i.e. pass in proper data members) + // BddCacheKey k; // Change this line!! + BddCacheKeyV k(f(), g(), h()); + size_t ret_t; + if (_computedTable.read(k, ret_t)) { + if (isNegEdge) ret_t = ret_t ^ BDD_NEG_EDGEV; + return ret_t; + } + + // check top varaible + unsigned v = f.getLevel(); + if (g.getLevel() > v) + v = g.getLevel(); + if (h.getLevel() > v) + v = h.getLevel(); + + // recursion + BddNodeV fl = f.getLeftCofactor(v), + gl = g.getLeftCofactor(v), + hl = h.getLeftCofactor(v); + BddNodeV t = ite(fl, gl, hl); + + BddNodeV fr = f.getRightCofactor(v), + gr = g.getRightCofactor(v), + hr = h.getRightCofactor(v); + BddNodeV e = ite(fr, gr, hr); + + // get result + if (t == e) { + // update computed table + _computedTable.write(k, t()); + if (isNegEdge) t = ~t; + return t; + } + + // move bubble if necessary... ==> update isNedEdge + bool moveBubble = t.isNegEdge(); #if DO_STD_ITE - assert(!moveBubble); + assert(!moveBubble); #else - if (moveBubble) { - t = ~t; e = ~e; - } + if (moveBubble) { + t = ~t; + e = ~e; + } #endif - // check unique table - BddNodeVInt* ni = uniquify(t(), e(), v); - ret_t = size_t(ni); + // check unique table + BddNodeVInt* ni = uniquify(t(), e(), v); + ret_t = size_t(ni); #if !(DO_STD_ITE) - if (moveBubble) ret_t = ret_t ^ BDD_NEG_EDGEV; + if (moveBubble) ret_t = ret_t ^ BDD_NEG_EDGEV; #endif - // update computed table - _computedTable.write(k, ret_t); - if (isNegEdge) - ret_t = ret_t ^ BDD_NEG_EDGEV; - return ret_t; + // update computed table + _computedTable.write(k, ret_t); + if (isNegEdge) + ret_t = ret_t ^ BDD_NEG_EDGEV; + return ret_t; } -void -BddMgrV::standardize(BddNodeV &f, BddNodeV &g, BddNodeV &h, bool &isNegEdge) -{ - // (1) Identical/Complement rules - if (f == g) g = BddNodeV::_one; - else if (f == ~g) g = BddNodeV::_zero; - else if (f == h) h = BddNodeV::_zero; - else if (f == ~h) h = BddNodeV::_one; - - // (2) Symmetrical rules - if (g == BddNodeV::_one) { - if (f > h) swapBddNodeV(f, h); - } - else if (g == BddNodeV::_zero) { - if (f > h) { swapBddNodeV(f, h); f = ~f; h = ~h; } - } - else if (h == BddNodeV::_one) { - if (f > g) { swapBddNodeV(f, g); f = ~f; g = ~g; } - } - else if (h == BddNodeV::_zero) { - if (f > g) swapBddNodeV(f, g); - } - else if (g == ~h) { - if (f > g) { swapBddNodeV(f, g); h = ~g; } - } - - // (3) Complement edge rules - // ==> both f and g will be posEdge afterwards - if (f.isNegEdge()) { swapBddNodeV(g, h); f = ~f; } - if (g.isNegEdge()) { - g = ~g; h = ~h; isNegEdge = !isNegEdge; - } +void BddMgrV::standardize(BddNodeV& f, BddNodeV& g, BddNodeV& h, bool& isNegEdge) { + // (1) Identical/Complement rules + if (f == g) + g = BddNodeV::_one; + else if (f == ~g) + g = BddNodeV::_zero; + else if (f == h) + h = BddNodeV::_zero; + else if (f == ~h) + h = BddNodeV::_one; + + // (2) Symmetrical rules + if (g == BddNodeV::_one) { + if (f > h) swapBddNodeV(f, h); + } else if (g == BddNodeV::_zero) { + if (f > h) { + swapBddNodeV(f, h); + f = ~f; + h = ~h; + } + } else if (h == BddNodeV::_one) { + if (f > g) { + swapBddNodeV(f, g); + f = ~f; + g = ~g; + } + } else if (h == BddNodeV::_zero) { + if (f > g) swapBddNodeV(f, g); + } else if (g == ~h) { + if (f > g) { + swapBddNodeV(f, g); + h = ~g; + } + } + + // (3) Complement edge rules + // ==> both f and g will be posEdge afterwards + if (f.isNegEdge()) { + swapBddNodeV(g, h); + f = ~f; + } + if (g.isNegEdge()) { + g = ~g; + h = ~h; + isNegEdge = !isNegEdge; + } } // Check if triplet (l, r, i) is in _uniqueTable, @@ -213,73 +223,73 @@ BddMgrV::standardize(BddNodeV &f, BddNodeV &g, BddNodeV &h, bool &isNegEdge) // else, return the hashed one // BddNodeVInt* -BddMgrV::uniquify(size_t l, size_t r, unsigned i) -{ - BddNodeVInt* n = 0; - BddHashKeyV k(l, r, i); - if (!_uniqueTable.check(k, n)) { - n = new BddNodeVInt(l, r, i); - _uniqueTable.forceInsert(k, n); - } - return n; +BddMgrV::uniquify(size_t l, size_t r, unsigned i) { + BddNodeVInt* n = 0; + BddHashKeyV k(l, r, i); + if (!_uniqueTable.check(k, n)) { + n = new BddNodeVInt(l, r, i); + _uniqueTable.forceInsert(k, n); + } + return n; } // return false if _bddArr[id] has aleady been inserted -bool -BddMgrV::addBddNodeV(unsigned id, size_t n) -{ - if (id >= _bddArr.size()) { - unsigned origSize = _bddArr.size(); - _bddArr.resize(id+1); - for(unsigned i = origSize; i < _bddArr.size(); ++i) - _bddArr[i] = 0; - } else if (_bddArr[id] != 0) - return false; - _bddArr[id] = n; - return true; +bool BddMgrV::addBddNodeV(unsigned id, size_t n) { + if (id >= _bddArr.size()) { + unsigned origSize = _bddArr.size(); + _bddArr.resize(id + 1); + for (unsigned i = origSize; i < _bddArr.size(); ++i) + _bddArr[i] = 0; + } else if (_bddArr[id] != 0) + return false; + _bddArr[id] = n; + return true; } // return 0 if not in the map!! BddNodeV -BddMgrV::getBddNodeV(unsigned id) const -{ - if (id >= _bddArr.size()) - return size_t(0); - return _bddArr[id]; +BddMgrV::getBddNodeV(unsigned id) const { + if (id >= _bddArr.size()) + return size_t(0); + return _bddArr[id]; } // return false if str is already in the _bddMap!! -bool -BddMgrV::addBddNodeV(const string& str, size_t n) -{ - return _bddMap.insert(BddMapPair(str, n)).second; +bool BddMgrV::addBddNodeV(const string& str, size_t n) { + return _bddMap.insert(BddMapPair(str, n)).second; } -void -BddMgrV::forceAddBddNodeV(const string& str, size_t n) -{ - _bddMap[str] = n; +void BddMgrV::forceAddBddNodeV(const string& str, size_t n) { + _bddMap[str] = n; } // return 0 if not in the map!! BddNodeV -BddMgrV::getBddNodeV(const string& name) const -{ - BddMapConstIter bi = _bddMap.find(name); - if (bi == _bddMap.end()) return size_t(0); - return (*bi).second; +BddMgrV::getBddNodeV(const string& name) const { + BddMapConstIter bi = _bddMap.find(name); + if (bi == _bddMap.end()) return size_t(0); + return (*bi).second; } // return true if terminal case -bool -BddMgrV::checkIteTerminal -(const BddNodeV& f, const BddNodeV& g, const BddNodeV& h, BddNodeV& n) -{ - if (g == h) { n = g; return true; } - if (f == BddNodeV::_one) { n = g; return true; } - if (f == BddNodeV::_zero) { n = h; return true; } - if (g == BddNodeV::_one && h == BddNodeV::_zero) { n = f; return true; } - return false; +bool BddMgrV::checkIteTerminal(const BddNodeV& f, const BddNodeV& g, const BddNodeV& h, BddNodeV& n) { + if (g == h) { + n = g; + return true; + } + if (f == BddNodeV::_one) { + n = g; + return true; + } + if (f == BddNodeV::_zero) { + n = h; + return true; + } + if (g == BddNodeV::_one && h == BddNodeV::_zero) { + n = f; + return true; + } + return false; } //---------------------------------------------------------------------- @@ -289,48 +299,43 @@ BddMgrV::checkIteTerminal // // ==> return -1 if pattern is not legal // ==> return 0/1 for evaluated result -int -BddMgrV::evalCube(const BddNodeV& node, const string& pattern) const -{ - size_t v = node.getLevel(); - size_t n = pattern.size(); - if (n < v) { - cerr << "Error: " << pattern << " too short!!" << endl; - return -1; - } - - BddNodeV next = node; - for (int i = v - 1; i >= 0; --i) { - char c = pattern[i]; - if (c == '1') - next = next.getLeftCofactor(i+1); - else if (c == '0') - next = next.getRightCofactor(i+1); - else { - cerr << "Illegal pattern: " << c << "(" << i << ")" << endl; - return -1; - } - } - return (next == BddNodeV::_one)? 1 : 0; +int BddMgrV::evalCube(const BddNodeV& node, const string& pattern) const { + size_t v = node.getLevel(); + size_t n = pattern.size(); + if (n < v) { + cerr << "Error: " << pattern << " too short!!" << endl; + return -1; + } + + BddNodeV next = node; + for (int i = v - 1; i >= 0; --i) { + char c = pattern[i]; + if (c == '1') + next = next.getLeftCofactor(i + 1); + else if (c == '0') + next = next.getRightCofactor(i + 1); + else { + cerr << "Illegal pattern: " << c << "(" << i << ")" << endl; + return -1; + } + } + return (next == BddNodeV::_one) ? 1 : 0; } -bool -BddMgrV::drawBdd(const string& name, const string& fileName) const -{ - BddNodeV node = ::getBddNodeV(name); - if (node() == 0) { - cerr << "Error: \"" << name << "\" is not a legal BDD node!!" << endl; - return false; - } +bool BddMgrV::drawBdd(const string& name, const string& fileName) const { + BddNodeV node = ::getBddNodeV(name); + if (node() == 0) { + cerr << "Error: \"" << name << "\" is not a legal BDD node!!" << endl; + return false; + } - ofstream ofile(fileName.c_str()); - if (!ofile) { - cerr << "Error: cannot open file \"" << fileName << "\"!!" << endl; - return false; - } + ofstream ofile(fileName.c_str()); + if (!ofile) { + cerr << "Error: cannot open file \"" << fileName << "\"!!" << endl; + return false; + } - node.drawBdd(name, ofile); + node.drawBdd(name, ofile); - return true; + return true; } - diff --git a/src/cir/.depend.mak b/src/cir/.depend.mak index bb1fc31f..61a66e53 100644 --- a/src/cir/.depend.mak +++ b/src/cir/.depend.mak @@ -1,99 +1,2 @@ -cirAig.o: cirAig.cpp cirMgr.h cirDef.h ../../include/myHash.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirGate.h \ - ../../include/sat.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/gvModMgr.h \ - ../../include/gvCmdMgr.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/base/main/main.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/aig/ioa/ioa.h \ - ../../include/gvAbcNtk.h -cirCmd.o: cirCmd.cpp cirMgr.h cirDef.h ../../include/myHash.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirGate.h \ - ../../include/sat.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h cirCmd.h ../../include/gvCmdMgr.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h \ - ../../include/gvMsg.h cirFraig.o: cirFraig.cpp -cirGate.o: cirGate.cpp cirGate.h cirDef.h ../../include/myHash.h \ - ../../include/sat.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - cirMgr.h ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/vec/vecInt.h ../../include/misc/vec/vecFlt.h \ - ../../include/misc/vec/vecStr.h ../../include/misc/vec/vecPtr.h \ - ../../include/misc/vec/vecVec.h ../../include/misc/vec/vecAtt.h \ - ../../include/misc/vec/vecWrd.h ../../include/misc/vec/vecBit.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/vec/vecWec.h \ - ../../include/aig/hop/hop.h ../../include/aig/gia/gia.h \ - ../../include/misc/vec/vecWec.h ../../include/misc/util/utilCex.h \ - ../../include/misc/st/st.h ../../include/misc/st/stmm.h \ - ../../include/misc/nm/nm.h ../../include/misc/mem/mem.h \ - ../../include/misc/extra/extra.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -cirMgr.o: cirMgr.cpp cirMgr.h cirDef.h ../../include/myHash.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirGate.h \ - ../../include/sat.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -cirOpt.o: cirOpt.cpp cirMgr.h cirDef.h ../../include/myHash.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirGate.h \ - ../../include/sat.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h cirSim.o: cirSim.cpp diff --git a/src/cir/cirAig.cpp b/src/cir/cirAig.cpp index b0cb4f41..fafc6071 100644 --- a/src/cir/cirAig.cpp +++ b/src/cir/cirAig.cpp @@ -13,11 +13,10 @@ #include "base/abc/abc.h" #include "gvAbcMgr.h" #include "gvModMgr.h" +#include "gvYosysMgr.h" #include "kernel/yosys.h" #include "util.h" -USING_YOSYS_NAMESPACE - string gateName(const string& name, const int& bit) { return name + "[" + to_string(bit) + "]"; } @@ -66,12 +65,13 @@ void parseAigMapping(Gia_Man_t* pGia, map& id2Name) { } } -void buildNameMapping(const string& fileName, Gia_Man_t* pGia, map& id2Name) { - run_pass("read_verilog " + fileName + "; hierarchy -auto-top; flatten; proc; techmap; setundef -zero; aigmap; write_aiger -map .map.txt ._temp_.aig"); - parseAigMapping(pGia, id2Name); -} +// void buildNameMapping(const string& fileName, Gia_Man_t* pGia, map& id2Name) { +// yosysMgr->buildMapping(fileName); +// parseAigMapping(pGia, id2Name); +// } void CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { + // log_make_debug = true; CirGateV gateV; Gia_Man_t* pGia = NULL; // the gia pointer of abc Gia_Obj_t *pObj, *pObjRi, *pObjRo; // the obj element of gia @@ -84,26 +84,29 @@ void CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { char* pFileName = new char[100]; cout << "filename = " << fileName << endl; strcpy(pFileName, fileName.c_str()); - char* pTopModule = NULL; // the top module can be auto detected by yosys, no need to set + char* pTopModule = NULL; char* pDefines = NULL; - int fBlast = 1; // blast the ntk to gia (abc's aig data structure) + int fBlast = 1; int fInvert = 0; int fTechMap = 1; int fSkipStrash = 0; int fCollapse = 0; - int c, fVerbose = 0; // set verbose to 1 to see which yosys command is used + int c, fVerbose = 0; int i, *pWire; if (fileType == AIGER) pGia = Gia_AigerRead(pFileName, 0, fSkipStrash, 0); else if (fileType == VERILOG) pGia = Wln_BlastSystemVerilog(pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fVerbose); - + if (!pGia) { cerr << "Cannot open design \"" << fileName << "\"!!" << endl; return; } - if (fileType == VERILOG) buildNameMapping(fileName, pGia, id2Name); + if (fileType == VERILOG) { + yosysMgr->buildMapping(fileName); + parseAigMapping(pGia, id2Name); + } // initialize the size of the containers initCir(pGia, fileType); diff --git a/src/cir/cirCmd.cpp b/src/cir/cirCmd.cpp index 5d2bfb86..66a90f71 100644 --- a/src/cir/cirCmd.cpp +++ b/src/cir/cirCmd.cpp @@ -22,7 +22,7 @@ using namespace std; extern CirMgr* cirMgr; extern int effLimit; -bool GVinitCirCmd() { +bool initCirCmd() { return (gvCmdMgr->regCmd("CIRRead", 4, new CirReadCmd) && gvCmdMgr->regCmd("CIRPrint", 4, new CirPrintCmd) && gvCmdMgr->regCmd("CIRGate", 4, new CirGateCmd)); @@ -68,9 +68,9 @@ GVCmdExecStatus CirReadCmd::exec(const string& option) { if (myStrNCmp("-Replace", options[i], 2) == 0) { if (doReplace) return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[i]); doReplace = true; - } else if (myStrNCmp("-Verilog", options[i], 1) == 0) { + } else if (myStrNCmp("-Verilog", options[i], 2) == 0) { fileType = VERILOG; - } else if (myStrNCmp("-Aiger", options[i], 1) == 0) { + } else if (myStrNCmp("-Aiger", options[i], 2) == 0) { fileType = AIGER; } else { if (fileName.size()) @@ -102,7 +102,8 @@ void CirReadCmd::usage(const bool& verbose) const { } void CirReadCmd::help() const { - cout << setw(15) << left << "CIRRead: read in a circuit and construct the netlist" << endl; + cout << setw(20) << left << "CIRRead:" + << "Read in a circuit and construct the netlist" << endl; } //---------------------------------------------------------------------- @@ -137,11 +138,12 @@ CirPrintCmd::exec(const string& option) { } void CirPrintCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: CIRPrint [-Summary | -Netlist | -PI | -PO | -FLoating | -FECpairs]" << endl; + cout << "Usage: CIRPrint [-Summary | -Netlist | -PI | -PO | -FLoating | -FECpairs]" << endl; } void CirPrintCmd::help() const { - cout << setw(15) << left << "CIRPrint: print circuit\n "; + cout << setw(20) << left << "CIRPrint: " + << "Print circuit" << endl; } //---------------------------------------------------------------------- @@ -213,11 +215,12 @@ CirGateCmd::exec(const string& option) { } void CirGateCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: CIRGate <<(int gateId)> [<-FANIn | -FANOut><(int level)>]>" << endl; + cout << "Usage: CIRGate <<(int gateId)> [<-FANIn | -FANOut><(int level)>]>" << endl; } void CirGateCmd::help() const { - cout << setw(15) << left << "CIRGate: report a gate\n"; + cout << setw(20) << left << "CIRGate:" + << "Report a gate" << endl; } // //---------------------------------------------------------------------- diff --git a/src/cmd/.depend.mak b/src/cmd/.depend.mak index fc75d675..e69de29b 100644 --- a/src/cmd/.depend.mak +++ b/src/cmd/.depend.mak @@ -1,5 +0,0 @@ -gvCmdComm.o: gvCmdComm.cpp gvCmdComm.h gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/gvUsage.h ../../include/gvMsg.h ../../include/gvIntType.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h -gvCmdMgr.o: gvCmdMgr.cpp gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/cmd/gvCmdComm.cpp b/src/cmd/gvCmdComm.cpp index de7b781e..6590d86d 100644 --- a/src/cmd/gvCmdComm.cpp +++ b/src/cmd/gvCmdComm.cpp @@ -8,7 +8,7 @@ #include bool -GVinitCommonCmd() { +initCommonCmd() { return (gvCmdMgr->regCmd("DOfile", 2, new GVDofileCmd) && gvCmdMgr->regCmd("HELp", 3, new GVHelpCmd) && gvCmdMgr->regCmd("HIStory", 3, new GVHistoryCmd) && diff --git a/src/cmd/gvCmdMgr.h b/src/cmd/gvCmdMgr.h index 8d3c259c..16c00068 100644 --- a/src/cmd/gvCmdMgr.h +++ b/src/cmd/gvCmdMgr.h @@ -18,140 +18,135 @@ extern GVCmdMgr* gvCmdMgr; // Command Categories to String const string GVCmdTypeString[] = {"Revealed", "Common", "Verify", "Simulate", "Network", - "Abc", "Mode", "Bdd", "Prove", "Itp"}; + "Abc", "Yosys", "Mode", "Bdd", "Prove", "Itp"}; // Command Categories Enum -enum GVCmdType -{ +enum GVCmdType { // Revealed command GV_CMD_TYPE_REVEALED = 0, - GV_CMD_TYPE_COMMON = 1, - GV_CMD_TYPE_VERIFY = 2, + GV_CMD_TYPE_COMMON = 1, + GV_CMD_TYPE_VERIFY = 2, GV_CMD_TYPE_SIMULATE = 3, - GV_CMD_TYPE_NETWORK = 4, - GV_CMD_TYPE_ABC = 5, - GV_CMD_TYPE_MOD = 6, - GV_CMD_TYPE_BDD = 7, - GV_CMD_TYPE_PROVE = 8, - GV_CMD_TYPE_ITP = 9, + GV_CMD_TYPE_NETWORK = 4, + GV_CMD_TYPE_ABC = 5, + GV_CMD_TYPE_YOSYS = 6, + GV_CMD_TYPE_MOD = 7, + GV_CMD_TYPE_BDD = 8, + GV_CMD_TYPE_PROVE = 9, + GV_CMD_TYPE_ITP = 10, }; -enum GVCmdExecStatus -{ - GV_CMD_EXEC_DONE = 0, +enum GVCmdExecStatus { + GV_CMD_EXEC_DONE = 0, GV_CMD_EXEC_ERROR = 1, - GV_CMD_EXEC_QUIT = 2, - GV_CMD_EXEC_NOP = 3, + GV_CMD_EXEC_QUIT = 2, + GV_CMD_EXEC_NOP = 3, }; -enum GVCmdOptionError -{ - GV_CMD_OPT_MISSING = 0, - GV_CMD_OPT_EXTRA = 1, - GV_CMD_OPT_ILLEGAL = 2, +enum GVCmdOptionError { + GV_CMD_OPT_MISSING = 0, + GV_CMD_OPT_EXTRA = 1, + GV_CMD_OPT_ILLEGAL = 2, GV_CMD_OPT_FOPEN_FAIL = 3, }; const unordered_set _setupMode{GV_CMD_TYPE_REVEALED, GV_CMD_TYPE_COMMON, GV_CMD_TYPE_NETWORK, - GV_CMD_TYPE_ABC, GV_CMD_TYPE_MOD, GV_CMD_TYPE_BDD, GV_CMD_TYPE_PROVE}; + GV_CMD_TYPE_ABC, GV_CMD_TYPE_MOD, GV_CMD_TYPE_BDD, GV_CMD_TYPE_PROVE}; const unordered_set _vrfMode{GV_CMD_TYPE_VERIFY, GV_CMD_TYPE_SIMULATE, GV_CMD_TYPE_COMMON, - GV_CMD_TYPE_MOD, GV_CMD_TYPE_PROVE, GV_CMD_TYPE_ITP}; - -#define GV_COMMAND(cmd, type) \ - class cmd : public GVCmdExec \ - { \ - public: \ - cmd() : GVCmdExec(type) {} \ - ~cmd() {} \ - GVCmdExecStatus exec(const string&); \ - void usage(const bool& = false) const; \ - void help() const; \ + GV_CMD_TYPE_MOD, GV_CMD_TYPE_PROVE, GV_CMD_TYPE_ITP}; + +#define GV_COMMAND(cmd, type) \ + class cmd : public GVCmdExec { \ + public: \ + cmd() : GVCmdExec(type) {} \ + ~cmd() {} \ + GVCmdExecStatus exec(const string&); \ + void usage(const bool& = false) const; \ + void help() const; \ }; -class GVCmdExec -{ - public: - GVCmdExec(GVCmdType t) : _cmdType(t) {} - virtual ~GVCmdExec() {} - virtual GVCmdExecStatus exec(const string&) = 0; - virtual void usage(const bool& = false) const = 0; - virtual void help() const = 0; - - inline GVCmdType getGVCmdType() const { return _cmdType; }; - inline void setCmdLen(unsigned n) { _cmdLen = n; } - inline unsigned getCmdLen() const { return _cmdLen; } - inline void setMandCmd(const string& str) { _mandCmd.push_back(str); } - inline const string& getMandCmd(size_t idx) const { return _mandCmd[idx]; } - inline void setOptCmd(const string& str) { _optCmd.push_back(str); } - inline const string& getOptCmd(size_t idx) const { return _optCmd[idx]; } - bool checkCmd(const string&) const; - bool checkCmd(const string&, size_t) const; - bool checkMandCmd(const string&, size_t) const; - bool checkOptCmd(const string&, size_t) const; - - bool operator<(const GVCmdExec&) const; - - protected: - void lexOptions(const string&, vector&) const; - bool lexSingleOption(const string&, string&, bool optional = true) const; - GVCmdExecStatus errorOption(GVCmdOptionError err, const string& opt) const; - - private: - GVCmdType _cmdType; - unsigned _cmdLen; - vector _mandCmd; - vector _optCmd; +class GVCmdExec { +public: + GVCmdExec(GVCmdType t) : _cmdType(t) {} + virtual ~GVCmdExec() {} + virtual GVCmdExecStatus exec(const string&) = 0; + virtual void usage(const bool& = false) const = 0; + virtual void help() const = 0; + + inline GVCmdType getGVCmdType() const { return _cmdType; }; + inline void setCmdLen(unsigned n) { _cmdLen = n; } + inline unsigned getCmdLen() const { return _cmdLen; } + inline void setMandCmd(const string& str) { _mandCmd.push_back(str); } + inline const string& getMandCmd(size_t idx) const { return _mandCmd[idx]; } + inline void setOptCmd(const string& str) { _optCmd.push_back(str); } + inline const string& getOptCmd(size_t idx) const { return _optCmd[idx]; } + bool checkCmd(const string&) const; + bool checkCmd(const string&, size_t) const; + bool checkMandCmd(const string&, size_t) const; + bool checkOptCmd(const string&, size_t) const; + + bool operator<(const GVCmdExec&) const; + +protected: + void lexOptions(const string&, vector&) const; + bool lexSingleOption(const string&, string&, bool optional = true) const; + GVCmdExecStatus errorOption(GVCmdOptionError err, const string& opt) const; + +private: + GVCmdType _cmdType; + unsigned _cmdLen; + vector _mandCmd; + vector _optCmd; }; struct GVCmdCompare { - bool operator()(const GVCmdExec* a, const GVCmdExec* b) const { return (*a < *b); } + bool operator()(const GVCmdExec* a, const GVCmdExec* b) const { return (*a < *b); } }; -typedef set GVCmdExecSubSet; +typedef set GVCmdExecSubSet; typedef map GVCmdExecSet; -class GVCmdMgr -{ +class GVCmdMgr { #define READ_BUF_SIZE 65536 #define PG_OFFSET 10 - public: - GVCmdMgr(const string&); - ~GVCmdMgr(); - GVCmdExec* getCmd(const string&) const; - GVCmdExecSubSet getCmdListFromPart(const string&) const; - bool regCmd(const string&, unsigned, GVCmdExec*); - bool regCmd(const string&, unsigned, unsigned, GVCmdExec*); - - GVCmdExecStatus execOneCmd(); - - void printHelps(bool = false) const; - void printHistory(int = -1) const; - - bool openDofile(const string& dof) { - _dofile.open(dof.c_str()); - return _dofile.is_open(); - } - void closeDofile() { - _dofile.close(); - _dofile.clear(); - } - - inline const string& getPrompt() const { return _prompt; } - inline void updateModPrompt(const string newPromt) { _modPrompt = newPromt; } - inline void setPrompt() { _prompt = _modPrompt + "> "; } - - private: - // Command Helper Functions - bool addHistory(char*); - GVCmdExec* parseCmd(string&); - // Command Data members - const string _defaultPrompt; // Default Command Prompt - string _modPrompt; // Current Command Prompt - string _prompt; // Current Command Prompt - ifstream _dofile; // For Script Parsing - GVCmdExecSet _cmdLib; - vector _history; +public: + GVCmdMgr(const string&); + ~GVCmdMgr(); + GVCmdExec* getCmd(const string&) const; + GVCmdExecSubSet getCmdListFromPart(const string&) const; + bool regCmd(const string&, unsigned, GVCmdExec*); + bool regCmd(const string&, unsigned, unsigned, GVCmdExec*); + + GVCmdExecStatus execOneCmd(); + + void printHelps(bool = false) const; + void printHistory(int = -1) const; + + bool openDofile(const string& dof) { + _dofile.open(dof.c_str()); + return _dofile.is_open(); + } + void closeDofile() { + _dofile.close(); + _dofile.clear(); + } + + inline const string& getPrompt() const { return _prompt; } + inline void updateModPrompt(const string newPromt) { _modPrompt = newPromt; } + inline void setPrompt() { _prompt = _modPrompt + "> "; } + +private: + // Command Helper Functions + bool addHistory(char*); + GVCmdExec* parseCmd(string&); + // Command Data members + const string _defaultPrompt; // Default Command Prompt + string _modPrompt; // Current Command Prompt + string _prompt; // Current Command Prompt + ifstream _dofile; // For Script Parsing + GVCmdExecSet _cmdLib; + vector _history; }; #endif \ No newline at end of file diff --git a/src/eng/yosyss b/src/eng/yosyss new file mode 120000 index 00000000..5eeaead6 --- /dev/null +++ b/src/eng/yosyss @@ -0,0 +1 @@ +../../engine/yosys/gv_src \ No newline at end of file diff --git a/src/ext/sim.so b/src/ext/sim.so index 89343984f82ce8d79b3ea86ce926fd73a83119d8..25cae8a185292e488418c023ca82856003b06db7 100755 GIT binary patch delta 234353 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%0D4l2le7*b{;&zEbs#aKE0-ib5X@m(nO+lnMY0|G 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

3$CbMJ;1J=`8DzkqLOL=1^g373;e_hV0(U1Fv-k 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%0DZ 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 VqbO^dKi%3s(e_regCmd("SATVerify ITP", 4, 3, new SATVerifyItpCmd) && gvCmdMgr->regCmd("SATVerify BMC", 4, 3, new SATVerifyBmcCmd)); } diff --git a/src/main/.depend.mak b/src/main/.depend.mak index b96a8e22..e69de29b 100644 --- a/src/main/.depend.mak +++ b/src/main/.depend.mak @@ -1,8 +0,0 @@ -main.o: main.cpp ../../include/gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/gvUsage.h ../../include/gvMsg.h ../../include/gvIntType.h \ - ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ - /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ - ../../include/kernel/hashlib.h ../../include/kernel/log.h \ - ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ - ../../include/kernel/register.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/main/main.cpp b/src/main/main.cpp index d29f9577..01897493 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -16,7 +16,7 @@ #include "util.h" using namespace std; -string GVMsg::_allName = ""; +string GVMsg::_allName = ""; ofstream GVMsg::_allout; GVMsgMgr gvMsg; @@ -27,17 +27,18 @@ GVUsage gvUsage; //---------------------------------------------------------------------- GVCmdMgr* gvCmdMgr = new GVCmdMgr("gv"); -extern bool GVinitCommonCmd(); -extern bool GVinitNtkCmd(); -extern bool GVinitSimCmd(); -extern bool GVinitVrfCmd(); -extern bool GVinitAbcCmd(); -extern bool GVinitModCmd(); -extern bool GVinitBddCmd(); -extern bool GVinitProveCmd(); -extern bool GVinitProveCmd(); -extern bool GVinitItpCmd(); -extern bool GVinitCirCmd(); +extern bool initCommonCmd(); +extern bool initNtkCmd(); +extern bool initSimCmd(); +extern bool initVrfCmd(); +extern bool initAbcCmd(); +extern bool initModCmd(); +extern bool initBddCmd(); +extern bool initProveCmd(); +extern bool initProveCmd(); +extern bool initItpCmd(); +extern bool initCirCmd(); +extern bool initYosysCmd(); static void usage() { @@ -50,13 +51,12 @@ myexit() { exit(-1); } -int -main(int argc, char** argv) { +int main(int argc, char** argv) { myUsage.reset(); ifstream dof; - if (argc == 3) { // -file + if (argc == 3) { // -file if (myStrNCmp("-File", argv[1], 2) == 0) { if (!gvCmdMgr->openDofile(argv[2])) { cout << "Error: cannot open file \"" << argv[2] << "\"!!\n"; @@ -70,10 +70,10 @@ main(int argc, char** argv) { cout << "Error: illegal number of argument (" << argc << ")!!\n"; myexit(); } - Yosys::yosys_setup(); // initial yosys command - Yosys::log_streams.push_back(&std::cout); // log yosys message - if (!(GVinitCommonCmd() && GVinitNtkCmd() && GVinitSimCmd() && GVinitVrfCmd() && - GVinitAbcCmd() && GVinitModCmd() && GVinitBddCmd() && GVinitProveCmd() && GVinitItpCmd() && GVinitCirCmd())) + // Yosys::yosys_setup(); // initial yosys command + // Yosys::log_streams.push_back(&std::cout); // log yosys message + if (!(initCommonCmd() && initNtkCmd() && initSimCmd() && initVrfCmd() && initAbcCmd() && + initModCmd() && initBddCmd() && initProveCmd() && initItpCmd() && initCirCmd() && initYosysCmd())) return 1; GVCmdExecStatus status = GV_CMD_EXEC_DONE; diff --git a/src/mod/.depend.mak b/src/mod/.depend.mak index 787aa841..e69de29b 100644 --- a/src/mod/.depend.mak +++ b/src/mod/.depend.mak @@ -1,32 +0,0 @@ -gvModCmd.o: gvModCmd.cpp gvModCmd.h ../../include/gvCmdMgr.h gvModMgr.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/gvMsg.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h -gvModMgr.o: gvModMgr.cpp gvModMgr.h ../../include/gvCmdMgr.h diff --git a/src/mod/gvModCmd.cpp b/src/mod/gvModCmd.cpp index 6b2ec956..ece919e7 100644 --- a/src/mod/gvModCmd.cpp +++ b/src/mod/gvModCmd.cpp @@ -12,7 +12,7 @@ #include bool -GVinitModCmd() { +initModCmd() { if (gvModMgr) delete gvModMgr; gvModMgr = new GVModMgr; return (gvCmdMgr->regCmd("SEt SYStem", 2, 3, new GVSetSystemCmd) && diff --git a/src/ntk/.depend.mak b/src/ntk/.depend.mak index ea91cf4a..e69de29b 100644 --- a/src/ntk/.depend.mak +++ b/src/ntk/.depend.mak @@ -1,99 +0,0 @@ -gvNtkBdd.o: gvNtkBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ - ../../include/bddNodeV.h ../../include/bddNodeV.h ../../include/gvMsg.h \ - gvNtk.h ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h -gvNtkCmd.o: gvNtkCmd.cpp gvNtkCmd.h ../../include/gvCmdMgr.h \ - ../../include/gvMsg.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/gvModMgr.h ../../include/gvCmdMgr.h gvNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h -gvNtk.o: gvNtk.cpp gvNtk.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/gvMsg.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/ntk/gvNtkCmd.cpp b/src/ntk/gvNtkCmd.cpp index a825a0bb..3a27e98b 100644 --- a/src/ntk/gvNtkCmd.cpp +++ b/src/ntk/gvNtkCmd.cpp @@ -15,7 +15,7 @@ USING_YOSYS_NAMESPACE bool -GVinitNtkCmd() { +initNtkCmd() { if (gvNtkMgr) delete gvNtkMgr; gvNtkMgr = new GVNtkMgr; return (gvCmdMgr->regCmd("SEt Engine", 2, 1, new GVSetEngineCmd) && diff --git a/src/prove/.depend.mak b/src/prove/.depend.mak index 4cd432ae..e69de29b 100644 --- a/src/prove/.depend.mak +++ b/src/prove/.depend.mak @@ -1,67 +0,0 @@ -proveBdd.o: proveBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ - ../../include/bddNodeV.h ../../include/gvMsg.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h -proveCmd.o: proveCmd.cpp proveCmd.h ../../include/gvCmdMgr.h \ - ../../include/bddMgrV.h ../../include/myHash.h ../../include/bddNodeV.h \ - ../../include/gvMsg.h ../../include/gvNtk.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/prove/proveCmd.cpp b/src/prove/proveCmd.cpp index 929bdc83..6c23e9ad 100644 --- a/src/prove/proveCmd.cpp +++ b/src/prove/proveCmd.cpp @@ -19,7 +19,7 @@ using namespace std; bool -GVinitProveCmd() { +initProveCmd() { return (gvCmdMgr->regCmd("PINITialstate", 5, new PInitialStateCmd) && gvCmdMgr->regCmd("PTRansrelation", 3, new PTransRelationCmd) && gvCmdMgr->regCmd("PIMAGe", 5, new PImageCmd) && diff --git a/src/sim/.depend.mak b/src/sim/.depend.mak index 4299e5d4..e69de29b 100644 --- a/src/sim/.depend.mak +++ b/src/sim/.depend.mak @@ -1,34 +0,0 @@ -gvSimCmd.o: gvSimCmd.cpp gvSimCmd.h ../../include/gvCmdMgr.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/gvModMgr.h ../../include/gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h \ - ../../include/gvNtk.h ../../include/gvAbcMgr.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h diff --git a/src/sim/gvSimCmd.cpp b/src/sim/gvSimCmd.cpp index d2bf0cda..c2aff854 100644 --- a/src/sim/gvSimCmd.cpp +++ b/src/sim/gvSimCmd.cpp @@ -11,7 +11,7 @@ #include "gvNtk.h" bool -GVinitSimCmd() { +initSimCmd() { return (gvCmdMgr->regCmd("RAndom Sim", 2, 1, new GVRandomSimCmd) && gvCmdMgr->regCmd("SEt SAfe", 2, 2, new GVRandomSetSafe) && gvCmdMgr->regCmd("SHow", 2, new GVShowCmd)); diff --git a/src/vrf/.depend.mak b/src/vrf/.depend.mak index ed12a040..e69de29b 100644 --- a/src/vrf/.depend.mak +++ b/src/vrf/.depend.mak @@ -1,29 +0,0 @@ -gvVrfCmd.o: gvVrfCmd.cpp gvVrfCmd.h ../../include/gvCmdMgr.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/gvMsg.h ../../include/gvUsage.h ../../include/gvMsg.h \ - ../../include/gvIntType.h ../../include/gvModMgr.h \ - ../../include/gvCmdMgr.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h diff --git a/src/vrf/gvVrfCmd.cpp b/src/vrf/gvVrfCmd.cpp index 8215fe34..c1175461 100644 --- a/src/vrf/gvVrfCmd.cpp +++ b/src/vrf/gvVrfCmd.cpp @@ -15,7 +15,7 @@ using namespace std; bool -GVinitVrfCmd() { +initVrfCmd() { return (gvCmdMgr->regCmd("Formal Verify", 1, 1, new GVFormalVerifyCmd)); } diff --git a/src/yosys/.depend.mak b/src/yosys/.depend.mak new file mode 100644 index 00000000..b203a328 --- /dev/null +++ b/src/yosys/.depend.mak @@ -0,0 +1,12 @@ +gvYosysCmd.o: gvYosysCmd.cpp gvYosysCmd.h ../../include/gvCmdMgr.h \ + ../../include/gvMsg.h gvYosysMgr.h ../../include/kernel/yosys.h \ + /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ + /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ + ../../include/kernel/log.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h \ + ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h +gvYosysMgr.o: gvYosysMgr.cpp gvYosysMgr.h ../../include/kernel/yosys.h \ + /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ + /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ + ../../include/kernel/log.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h diff --git a/src/yosys/.extheader.mak b/src/yosys/.extheader.mak new file mode 100644 index 00000000..6582fa0b --- /dev/null +++ b/src/yosys/.extheader.mak @@ -0,0 +1,7 @@ +yosys.d: ../../include/gvYosysCmd.h ../../include/gvYosysMgr.h +../../include/gvYosysCmd.h: gvYosysCmd.h + @rm -f ../../include/gvYosysCmd.h + @ln -fs ../src/yosys/gvYosysCmd.h ../../include/gvYosysCmd.h +../../include/gvYosysMgr.h: gvYosysMgr.h + @rm -f ../../include/gvYosysMgr.h + @ln -fs ../src/yosys/gvYosysMgr.h ../../include/gvYosysMgr.h diff --git a/src/yosys/Makefile b/src/yosys/Makefile new file mode 100644 index 00000000..fe2e6499 --- /dev/null +++ b/src/yosys/Makefile @@ -0,0 +1,5 @@ +PKGFLAG = $(DEBUG_FLAG) +EXTHDRS = gvYosysCmd.h gvYosysMgr.h + +include ../Makefile.in +include ../Makefile.lib \ No newline at end of file diff --git a/src/yosys/gvYosysCmd.cpp b/src/yosys/gvYosysCmd.cpp new file mode 100644 index 00000000..ff4ea6ee --- /dev/null +++ b/src/yosys/gvYosysCmd.cpp @@ -0,0 +1,59 @@ +#ifndef GV_ABC_CMD_C +#define GV_ABC_CMD_C + +#include "gvYosysCmd.h" + +#include +#include + +#include "gvCmdMgr.h" +#include "gvMsg.h" +#include "gvYosysMgr.h" +#include "util.h" + +bool initYosysCmd() { + if (yosysMgr) delete yosysMgr; + yosysMgr = new YosysMgr; yosysMgr->init(); + return (gvCmdMgr->regCmd("YSYSet", 4, new YosysSetCmd)); +} + +//---------------------------------------------------------------------- +// YSYSet <-log (int enable)> +//---------------------------------------------------------------------- +GVCmdExecStatus YosysSetCmd::exec(const string& option) { + vector options; + GVCmdExec::lexOptions(option, options); + if (options.empty()) + return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, ""); + else if (options.size() > 2) + return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[2]); + + bool doLog = false, isValid = false; + int enable = 0; + size_t n = options.size(); + if (myStrNCmp("-LOG", options[0], 4) == 0) + doLog = true; + else + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); + + if (doLog) { + if (myStr2Int(options[1], enable)) + isValid = true; + else + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); + } + if (isValid) yosysMgr->setLogging(enable); + + return GV_CMD_EXEC_DONE; +} + +void YosysSetCmd::usage(const bool& verbose) const { + gvMsg(GV_MSG_IFO) << "Usage: YSYSet <-log (int enable)>" << endl; +} + +void YosysSetCmd::help() const { + gvMsg(GV_MSG_IFO) << setw(20) << left << "YSYSet: " + << "Set the option of Yosys." << endl; +} + +#endif \ No newline at end of file diff --git a/src/yosys/gvYosysCmd.h b/src/yosys/gvYosysCmd.h new file mode 100644 index 00000000..acc7074e --- /dev/null +++ b/src/yosys/gvYosysCmd.h @@ -0,0 +1,8 @@ +#ifndef GV_YOSYS_CMD_H +#define GV_YOSYS_CMD_H + +#include "gvCmdMgr.h" + +GV_COMMAND(YosysSetCmd, GV_CMD_TYPE_YOSYS); + +#endif \ No newline at end of file diff --git a/src/yosys/gvYosysMgr.cpp b/src/yosys/gvYosysMgr.cpp new file mode 100644 index 00000000..1d425ddc --- /dev/null +++ b/src/yosys/gvYosysMgr.cpp @@ -0,0 +1,31 @@ +#include "gvYosysMgr.h" + +#include + +YosysMgr* yosysMgr; + +void YosysMgr::init() { + Yosys::yosys_setup(); +} + +void YosysMgr::reset() { + delete Yosys::yosys_design; + Yosys::yosys_design = new RTLIL::Design; +} + +void YosysMgr::setLogging(const bool& enable) { + if (enable && log_streams.empty()) + log_streams.push_back(&std::cout); + else if (!enable && !log_streams.empty()) + log_streams.pop_back(); +} + +void YosysMgr::buildMapping(const string& fileName) { + string yosys = "yosys -qp "; + string readVerilog = "read_verilog " + fileName + "; "; + string topModule = "hierarchy -auto-top; "; + string preProcess = "flatten; proc; techmap; setundef -zero; aigmap; "; + string writeAigMapping = "write_aiger -map .map.txt ._temp_.aig"; + string command = yosys + "\"" + readVerilog + topModule + preProcess + writeAigMapping + "\""; + system(command.c_str()); +} diff --git a/src/yosys/gvYosysMgr.h b/src/yosys/gvYosysMgr.h new file mode 100644 index 00000000..26dd332a --- /dev/null +++ b/src/yosys/gvYosysMgr.h @@ -0,0 +1,26 @@ +#ifndef GV_YOSYS_MGR +#define GV_YOSYS_MGR + +#include "kernel/yosys.h" + +using namespace std; +USING_YOSYS_NAMESPACE + +class YosysMgr; +extern YosysMgr* yosysMgr; + +class YosysMgr { +public: + YosysMgr() { init(); } + ~YosysMgr() {} + + void init(); + void reset(); + + void setLogging(const bool& = false); + void buildMapping(const string& fileName); + +private: +}; + +#endif From c0e9d3960447e66afe58c62dbe4dd2b841b777fd Mon Sep 17 00:00:00 2001 From: hchchiu Date: Sun, 26 Nov 2023 06:24:02 +0800 Subject: [PATCH 013/307] Update Makefile --- Makefile | 6 +++--- engine/yosys.script | 13 ++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index e3d0cb59..071faa74 100755 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -SRCPKGS = util cmd mod abc bdd itp ntk cir sim vrf ext prove -LIBPKGS = util cmd mod abc bdd itp ntk cir sim vrf prove +SRCPKGS = util cmd mod abc yosys bdd itp ntk cir sim vrf ext prove +LIBPKGS = util cmd mod abc yosys bdd itp ntk cir sim vrf prove MAIN = main @@ -13,7 +13,7 @@ ENGPKGS += lgl ENGPKGS += btor2parser #ENGPKGS += minisat ENGPKGS += abcc -ENGPKGS += yosys +ENGPKGS += yosyss ENGSSRC = eng diff --git a/engine/yosys.script b/engine/yosys.script index 93d18af9..aa041166 100755 --- a/engine/yosys.script +++ b/engine/yosys.script @@ -4,8 +4,8 @@ git clone https://github.com/YosysHQ/yosys.git # go to yosys/ cd yosys/; -# switch to version 0.23 of yosys -git checkout yosys-0.23 +# switch to version 0.35 of yosys +git checkout yosys-0.35 # enable the libyosys.so flag sed -i -e "s/ENABLE_LIBYOSYS := 0/ENABLE_LIBYOSYS := 1/g" Makefile; @@ -19,8 +19,11 @@ make config-gcc; make -j12; make libyosys.so; make install; # create gv_src/ directory mkdir gv_src; +# rename yosys shared library +mv libyosys.so libyosyss.so + # copy "yosys" shared library to gv_src/ directory -mv libyosys.so gv_src/; +mv libyosyss.so gv_src/; # copy "yosys" header files to gv_src/ directory cp -rf share/include/kernel gv_src/; @@ -33,5 +36,5 @@ ln -fs engine/yosys/yosys-config ./yosys-config ln -fs engine/yosys/yosys-abc ./yosys-abc # go to src/eng and create symbol link -echo "Creating softlink from engine/yosys/gv_src to src/eng/yosys ..."; -cd ./src/eng/; ln -fs ../../engine/yosys/gv_src ./yosys +echo "Creating softlink from engine/yosys/gv_src to src/eng/yosyss ..."; +cd ./src/eng/; ln -fs ../../engine/yosys/gv_src ./yosyss From 28e2a9079f1262403f2f3d87d9d41765834106d5 Mon Sep 17 00:00:00 2001 From: hchchiu Date: Wed, 29 Nov 2023 05:06:03 +0800 Subject: [PATCH 014/307] Organize the code --- src/abc/.depend.mak | 27 + src/bdd/.depend.mak | 42 + src/cir/.depend.mak | 230 +++++ src/cir/cirAig.cpp | 61 +- src/cir/cirBdd.cpp | 15 +- src/cir/cirCmd.cpp | 6 +- src/cir/cirGate.h | 2 +- src/cir/cirMgr.h | 3 +- src/cmd/.depend.mak | 5 + src/cmd/gvCmdMgr.cpp | 183 ++-- src/cmd/gvCmdMgr.h | 4 +- src/ext/sim.so | Bin 817840 -> 817840 bytes src/gvsat/.depend.mak | 40 + src/gvsat/.extheader.mak | 4 + src/{itp => gvsat}/FileV.cpp | 0 src/{itp => gvsat}/FileV.h | 0 src/{itp => gvsat}/GlobalV.h | 0 src/{itp => gvsat}/HeapV.h | 0 src/gvsat/Makefile | 5 + src/{itp => gvsat}/ProofV.cpp | 0 src/{itp => gvsat}/ProofV.h | 0 src/{itp => gvsat}/SolverTypesV.h | 0 src/{itp => gvsat}/SolverV.cpp | 0 src/{itp => gvsat}/SolverV.h | 0 src/{itp => gvsat}/SortV.h | 0 src/{itp => gvsat}/VarOrderV.h | 0 src/{itp => gvsat}/gvBitVec.cpp | 0 src/{itp => gvsat}/gvBitVec.h | 0 src/{itp => gvsat}/gvSat.cpp | 132 ++- src/gvsat/gvSat.h | 80 ++ src/{itp => gvsat}/reader.cpp | 0 src/{itp => gvsat}/reader.h | 0 src/itp/.depend.mak | 84 +- src/itp/.extheader.mak | 8 +- src/itp/Makefile | 2 +- src/itp/gvSat.h | 79 -- src/itp/gvSatCmd.cpp | 97 +- src/itp/gvSatMgr.cpp | 335 +++---- src/itp/gvSatMgr.h | 160 ++- src/main/.depend.mak | 8 + src/main/main.cpp | 6 +- src/mod/.depend.mak | 32 + src/mod/gvModMgr.cpp | 77 +- src/ntk/.depend.mak | 105 ++ src/prove/.depend.mak | 79 ++ src/sat/File.cpp | 157 --- src/sat/File.h | 142 --- src/sat/Global.h | 278 ------ src/sat/Heap.h | 100 -- src/sat/NO_USE/sat.h | 92 -- src/sat/NO_USE/satMiniSat.cpp | 45 - src/sat/Proof.cpp | 251 ----- src/sat/Proof.h | 74 -- src/sat/README | 76 -- src/sat/Solver.cpp | 854 ---------------- src/sat/Solver.h | 219 ----- src/sat/SolverTypes.h | 141 --- src/sat/Sort.h | 131 --- src/sat/VarOrder.h | 97 -- src/sat/make.sat | 7 - src/sat/minisat/LICENSE | 21 - src/sat/minisat/README | 24 - src/sat/minisat/core/Dimacs.h | 89 -- src/sat/minisat/core/Main.cc | 192 ---- src/sat/minisat/core/Main.or | Bin 98728 -> 0 bytes src/sat/minisat/core/Makefile | 4 - src/sat/minisat/core/Solver.cc | 923 ------------------ src/sat/minisat/core/Solver.h | 373 ------- src/sat/minisat/core/Solver.or | Bin 501400 -> 0 bytes src/sat/minisat/core/SolverTypes.h | 407 -------- src/sat/minisat/core/depend.mk | 37 - src/sat/minisat/doc/ReleaseNotes-2.2.0.txt | 79 -- src/sat/minisat/mtl/Alg.h | 84 -- src/sat/minisat/mtl/Alloc.h | 131 --- src/sat/minisat/mtl/Heap.h | 148 --- src/sat/minisat/mtl/IntTypes.h | 42 - src/sat/minisat/mtl/Map.h | 193 ---- src/sat/minisat/mtl/Queue.h | 69 -- src/sat/minisat/mtl/Sort.h | 98 -- src/sat/minisat/mtl/Vec.h | 130 --- src/sat/minisat/mtl/XAlloc.h | 45 - src/sat/minisat/mtl/config.mk | 6 - src/sat/minisat/mtl/template.mk | 107 -- src/sat/minisat/simp/Main.cc | 211 ---- src/sat/minisat/simp/Makefile | 4 - src/sat/minisat/simp/SimpSolver.cc | 717 -------------- src/sat/minisat/simp/SimpSolver.h | 197 ---- src/sat/minisat/utils/Makefile | 4 - src/sat/minisat/utils/Options.cc | 91 -- src/sat/minisat/utils/Options.h | 386 -------- src/sat/minisat/utils/Options.or | Bin 45312 -> 0 bytes src/sat/minisat/utils/ParseUtils.h | 122 --- src/sat/minisat/utils/System.cc | 95 -- src/sat/minisat/utils/System.h | 60 -- src/sat/minisat/utils/System.or | Bin 10488 -> 0 bytes src/sat/ref | 121 --- src/sat/reff | 121 --- src/sat/sat.h | 122 --- src/sat/test/File.cpp | 157 --- src/sat/test/File.h | 142 --- src/sat/test/Global.h | 278 ------ src/sat/test/Heap.h | 100 -- src/sat/test/Makefile | 17 - src/sat/test/Makefile2 | 17 - src/sat/test/Makefile3 | 17 - src/sat/test/NO_USE/itp.h | 228 ----- src/sat/test/NO_USE/mitp.h | 13 - src/sat/test/Proof.cpp | 251 ----- src/sat/test/Proof.h | 74 -- src/sat/test/Solver.cpp | 854 ---------------- src/sat/test/Solver.h | 219 ----- src/sat/test/SolverTypes.h | 141 --- src/sat/test/Sort.h | 131 --- src/sat/test/VarOrder.h | 97 -- src/sat/test/andTest | Bin 193160 -> 0 bytes src/sat/test/andTest.cpp | 90 -- src/sat/test/andTest.dSYM/Contents/Info.plist | 20 - .../Contents/Resources/DWARF/andTest | Bin 203461 -> 0 bytes src/sat/test/sat.h | 110 --- src/sat/test/satTest | Bin 242861 -> 0 bytes src/sat/test/satTest.cpp | 108 -- src/sat/test/satTest2 | Bin 194256 -> 0 bytes src/sat/test/satTest2.cpp | 108 -- src/sat/test/satTest3 | Bin 194248 -> 0 bytes src/sat/test/tags | 467 --------- src/sim/.depend.mak | 34 + src/vrf/.depend.mak | 29 + 127 files changed, 1287 insertions(+), 12443 deletions(-) create mode 100644 src/gvsat/.depend.mak create mode 100644 src/gvsat/.extheader.mak rename src/{itp => gvsat}/FileV.cpp (100%) rename src/{itp => gvsat}/FileV.h (100%) rename src/{itp => gvsat}/GlobalV.h (100%) rename src/{itp => gvsat}/HeapV.h (100%) create mode 100644 src/gvsat/Makefile rename src/{itp => gvsat}/ProofV.cpp (100%) rename src/{itp => gvsat}/ProofV.h (100%) rename src/{itp => gvsat}/SolverTypesV.h (100%) rename src/{itp => gvsat}/SolverV.cpp (100%) rename src/{itp => gvsat}/SolverV.h (100%) rename src/{itp => gvsat}/SortV.h (100%) rename src/{itp => gvsat}/VarOrderV.h (100%) rename src/{itp => gvsat}/gvBitVec.cpp (100%) rename src/{itp => gvsat}/gvBitVec.h (100%) rename src/{itp => gvsat}/gvSat.cpp (59%) create mode 100644 src/gvsat/gvSat.h rename src/{itp => gvsat}/reader.cpp (100%) rename src/{itp => gvsat}/reader.h (100%) delete mode 100644 src/itp/gvSat.h delete mode 100644 src/sat/File.cpp delete mode 100644 src/sat/File.h delete mode 100644 src/sat/Global.h delete mode 100644 src/sat/Heap.h delete mode 100644 src/sat/NO_USE/sat.h delete mode 100644 src/sat/NO_USE/satMiniSat.cpp delete mode 100644 src/sat/Proof.cpp delete mode 100644 src/sat/Proof.h delete mode 100644 src/sat/README delete mode 100644 src/sat/Solver.cpp delete mode 100644 src/sat/Solver.h delete mode 100644 src/sat/SolverTypes.h delete mode 100644 src/sat/Sort.h delete mode 100644 src/sat/VarOrder.h delete mode 100644 src/sat/make.sat delete mode 100644 src/sat/minisat/LICENSE delete mode 100644 src/sat/minisat/README delete mode 100644 src/sat/minisat/core/Dimacs.h delete mode 100644 src/sat/minisat/core/Main.cc delete mode 100644 src/sat/minisat/core/Main.or delete mode 100644 src/sat/minisat/core/Makefile delete mode 100644 src/sat/minisat/core/Solver.cc delete mode 100644 src/sat/minisat/core/Solver.h delete mode 100644 src/sat/minisat/core/Solver.or delete mode 100644 src/sat/minisat/core/SolverTypes.h delete mode 100644 src/sat/minisat/core/depend.mk delete mode 100644 src/sat/minisat/doc/ReleaseNotes-2.2.0.txt delete mode 100644 src/sat/minisat/mtl/Alg.h delete mode 100644 src/sat/minisat/mtl/Alloc.h delete mode 100644 src/sat/minisat/mtl/Heap.h delete mode 100644 src/sat/minisat/mtl/IntTypes.h delete mode 100644 src/sat/minisat/mtl/Map.h delete mode 100644 src/sat/minisat/mtl/Queue.h delete mode 100644 src/sat/minisat/mtl/Sort.h delete mode 100644 src/sat/minisat/mtl/Vec.h delete mode 100644 src/sat/minisat/mtl/XAlloc.h delete mode 100644 src/sat/minisat/mtl/config.mk delete mode 100644 src/sat/minisat/mtl/template.mk delete mode 100644 src/sat/minisat/simp/Main.cc delete mode 100644 src/sat/minisat/simp/Makefile delete mode 100644 src/sat/minisat/simp/SimpSolver.cc delete mode 100644 src/sat/minisat/simp/SimpSolver.h delete mode 100644 src/sat/minisat/utils/Makefile delete mode 100644 src/sat/minisat/utils/Options.cc delete mode 100644 src/sat/minisat/utils/Options.h delete mode 100644 src/sat/minisat/utils/Options.or delete mode 100644 src/sat/minisat/utils/ParseUtils.h delete mode 100644 src/sat/minisat/utils/System.cc delete mode 100644 src/sat/minisat/utils/System.h delete mode 100644 src/sat/minisat/utils/System.or delete mode 100644 src/sat/ref delete mode 100644 src/sat/reff delete mode 100644 src/sat/sat.h delete mode 100644 src/sat/test/File.cpp delete mode 100644 src/sat/test/File.h delete mode 100644 src/sat/test/Global.h delete mode 100644 src/sat/test/Heap.h delete mode 100644 src/sat/test/Makefile delete mode 100644 src/sat/test/Makefile2 delete mode 100644 src/sat/test/Makefile3 delete mode 100644 src/sat/test/NO_USE/itp.h delete mode 100644 src/sat/test/NO_USE/mitp.h delete mode 100644 src/sat/test/Proof.cpp delete mode 100644 src/sat/test/Proof.h delete mode 100644 src/sat/test/Solver.cpp delete mode 100644 src/sat/test/Solver.h delete mode 100644 src/sat/test/SolverTypes.h delete mode 100644 src/sat/test/Sort.h delete mode 100644 src/sat/test/VarOrder.h delete mode 100644 src/sat/test/andTest delete mode 100644 src/sat/test/andTest.cpp delete mode 100644 src/sat/test/andTest.dSYM/Contents/Info.plist delete mode 100644 src/sat/test/andTest.dSYM/Contents/Resources/DWARF/andTest delete mode 100644 src/sat/test/sat.h delete mode 100644 src/sat/test/satTest delete mode 100644 src/sat/test/satTest.cpp delete mode 100644 src/sat/test/satTest2 delete mode 100644 src/sat/test/satTest2.cpp delete mode 100644 src/sat/test/satTest3 delete mode 100644 src/sat/test/tags diff --git a/src/abc/.depend.mak b/src/abc/.depend.mak index 1e24bc4c..3db860d4 100644 --- a/src/abc/.depend.mak +++ b/src/abc/.depend.mak @@ -1,3 +1,30 @@ +gvAbcCmd.o: gvAbcCmd.cpp gvAbcCmd.h ../../include/gvCmdMgr.h gvAbcMgr.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/base/main/main.h ../../include/base/main/abcapis.h \ + ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ + ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ + ../../include/base/main/main.h ../../include/misc/tim/tim.h \ + ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ + ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ + ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ + ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ + ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ + ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ + gvAbcNtk.h ../../include/gvModMgr.h ../../include/gvCmdMgr.h \ + ../../include/gvMsg.h ../../include/util.h ../../include/rnGen.h \ + ../../include/myUsage.h gvAbcMgr.o: gvAbcMgr.cpp gvAbcMgr.h ../../include/base/abc/abc.h \ ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ diff --git a/src/bdd/.depend.mak b/src/bdd/.depend.mak index eb07f82f..f1435642 100644 --- a/src/bdd/.depend.mak +++ b/src/bdd/.depend.mak @@ -1 +1,43 @@ +bddCmd.o: bddCmd.cpp bddCmd.h ../../include/gvCmdMgr.h bddMgrV.h myHash.h \ + bddNodeV.h ../../include/cirGate.h ../../include/cirDef.h myHash.h \ + ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirMgr.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/gvBitVec.h ../../include/gvIntType.h ../../include/gvNtk.h \ + ../../include/gvAbcMgr.h ../../include/base/main/main.h \ + ../../include/base/abc/abc.h ../../include/base/main/abcapis.h \ + ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ + ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ + ../../include/base/main/main.h ../../include/misc/tim/tim.h \ + ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ + ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ + ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ + ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ + ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ + ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ + ../../include/gvAbcNtk.h ../../include/kernel/sigtools.h \ + ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ + /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ + ../../include/kernel/hashlib.h ../../include/kernel/log.h \ + ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ + ../../include/kernel/register.h ../../include/kernel/utils.h \ + ../../include/kernel/yosys.h ../../include/cirMgr.h \ + ../../include/gvMsg.h ../../include/gvNtk.h ../../include/util.h \ + ../../include/rnGen.h ../../include/myUsage.h +bddMgrV.o: bddMgrV.cpp bddMgrV.h myHash.h bddNodeV.h ../../include/util.h \ + ../../include/rnGen.h ../../include/myUsage.h bddNodeV.o: bddNodeV.cpp bddNodeV.h bddMgrV.h myHash.h diff --git a/src/cir/.depend.mak b/src/cir/.depend.mak index 61a66e53..afa47b1c 100644 --- a/src/cir/.depend.mak +++ b/src/cir/.depend.mak @@ -1,2 +1,232 @@ +cirAig.o: cirAig.cpp cirGate.h cirDef.h ../../include/myHash.h \ + ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirMgr.h ../../include/cirDef.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/gvBitVec.h ../../include/gvIntType.h ../../include/gvNtk.h \ + ../../include/gvAbcMgr.h ../../include/base/main/main.h \ + ../../include/base/abc/abc.h ../../include/base/main/abcapis.h \ + ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ + ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ + ../../include/base/main/main.h ../../include/misc/tim/tim.h \ + ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ + ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ + ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ + ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ + ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ + ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ + ../../include/gvAbcNtk.h ../../include/kernel/sigtools.h \ + ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ + /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ + ../../include/kernel/hashlib.h ../../include/kernel/log.h \ + ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ + ../../include/kernel/register.h ../../include/kernel/utils.h \ + ../../include/kernel/yosys.h cirMgr.h ../../include/gvAbcMgr.h \ + ../../include/gvModMgr.h ../../include/gvCmdMgr.h \ + ../../include/gvYosysMgr.h ../../include/util.h ../../include/rnGen.h \ + ../../include/myUsage.h +cirBdd.o: cirBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ + ../../include/bddNodeV.h ../../include/bddNodeV.h cirGate.h cirDef.h \ + ../../include/myHash.h ../../include/gvSat.h ../../include/SolverV.h \ + ../../include/ProofV.h ../../include/SolverTypesV.h \ + ../../include/GlobalV.h ../../include/FileV.h ../../include/VarOrderV.h \ + ../../include/HeapV.h ../../include/cirGate.h ../../include/cirMgr.h \ + ../../include/cirDef.h ../../include/base/abc/abc.h \ + ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/gvBitVec.h ../../include/gvIntType.h ../../include/gvNtk.h \ + ../../include/gvAbcMgr.h ../../include/base/main/main.h \ + ../../include/base/abc/abc.h ../../include/base/main/abcapis.h \ + ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ + ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ + ../../include/base/main/main.h ../../include/misc/tim/tim.h \ + ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ + ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ + ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ + ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ + ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ + ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ + ../../include/gvAbcNtk.h ../../include/kernel/sigtools.h \ + ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ + /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ + ../../include/kernel/hashlib.h ../../include/kernel/log.h \ + ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ + ../../include/kernel/register.h ../../include/kernel/utils.h \ + ../../include/kernel/yosys.h cirMgr.h ../../include/gvMsg.h \ + ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h +cirCmd.o: cirCmd.cpp cirCmd.h ../../include/gvCmdMgr.h cirGate.h cirDef.h \ + ../../include/myHash.h ../../include/gvSat.h ../../include/SolverV.h \ + ../../include/ProofV.h ../../include/SolverTypesV.h \ + ../../include/GlobalV.h ../../include/FileV.h ../../include/VarOrderV.h \ + ../../include/HeapV.h ../../include/cirGate.h ../../include/cirMgr.h \ + ../../include/cirDef.h ../../include/base/abc/abc.h \ + ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/gvBitVec.h ../../include/gvIntType.h ../../include/gvNtk.h \ + ../../include/gvAbcMgr.h ../../include/base/main/main.h \ + ../../include/base/abc/abc.h ../../include/base/main/abcapis.h \ + ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ + ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ + ../../include/base/main/main.h ../../include/misc/tim/tim.h \ + ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ + ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ + ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ + ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ + ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ + ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ + ../../include/gvAbcNtk.h ../../include/kernel/sigtools.h \ + ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ + /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ + ../../include/kernel/hashlib.h ../../include/kernel/log.h \ + ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ + ../../include/kernel/register.h ../../include/kernel/utils.h \ + ../../include/kernel/yosys.h cirMgr.h ../../include/gvModMgr.h \ + ../../include/gvCmdMgr.h ../../include/gvMsg.h ../../include/util.h \ + ../../include/rnGen.h ../../include/myUsage.h cirFraig.o: cirFraig.cpp +cirGate.o: cirGate.cpp cirGate.h cirDef.h ../../include/myHash.h \ + ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirMgr.h ../../include/cirDef.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/gvBitVec.h ../../include/gvIntType.h ../../include/gvNtk.h \ + ../../include/gvAbcMgr.h ../../include/base/main/main.h \ + ../../include/base/abc/abc.h ../../include/base/main/abcapis.h \ + ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ + ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ + ../../include/base/main/main.h ../../include/misc/tim/tim.h \ + ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ + ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ + ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ + ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ + ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ + ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ + ../../include/gvAbcNtk.h ../../include/kernel/sigtools.h \ + ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ + /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ + ../../include/kernel/hashlib.h ../../include/kernel/log.h \ + ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ + ../../include/kernel/register.h ../../include/kernel/utils.h \ + ../../include/kernel/yosys.h cirMgr.h ../../include/util.h \ + ../../include/rnGen.h ../../include/myUsage.h +cirMgr.o: cirMgr.cpp cirMgr.h cirDef.h ../../include/myHash.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirGate.h \ + ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirMgr.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h ../../include/gvNtk.h ../../include/gvAbcMgr.h \ + ../../include/base/abc/abc.h ../../include/base/main/main.h \ + ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ + ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ + ../../include/base/main/mainInt.h ../../include/base/main/main.h \ + ../../include/misc/tim/tim.h ../../include/map/if/if.h \ + ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ + ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ + ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ + ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ + ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ + ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ + ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ + ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ + /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ + /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ + ../../include/kernel/log.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h \ + ../../include/kernel/utils.h ../../include/kernel/yosys.h \ + ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h +cirOpt.o: cirOpt.cpp cirMgr.h cirDef.h ../../include/myHash.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirGate.h \ + ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirMgr.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h ../../include/gvNtk.h ../../include/gvAbcMgr.h \ + ../../include/base/abc/abc.h ../../include/base/main/main.h \ + ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ + ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ + ../../include/base/main/mainInt.h ../../include/base/main/main.h \ + ../../include/misc/tim/tim.h ../../include/map/if/if.h \ + ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ + ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ + ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ + ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ + ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ + ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ + ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ + ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ + /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ + /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ + ../../include/kernel/log.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h \ + ../../include/kernel/utils.h ../../include/kernel/yosys.h \ + ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h cirSim.o: cirSim.cpp diff --git a/src/cir/cirAig.cpp b/src/cir/cirAig.cpp index fafc6071..a9660114 100644 --- a/src/cir/cirAig.cpp +++ b/src/cir/cirAig.cpp @@ -1,9 +1,9 @@ /**************************************************************************** FileName [ cirAig.cpp ] PackageName [ cir ] - Synopsis [ Define basic cir package commands ] - Author [ Chung-Yang (Ric) Huang ] - Copyright [ ] + Synopsis [ Define GV cir/aig functions ] + Author [ Design Verification Lab ] + Copyright [ Copyright(c) 2023-present DVLab, GIEE, NTU, Taiwan ] ****************************************************************************/ #include #include @@ -65,12 +65,8 @@ void parseAigMapping(Gia_Man_t* pGia, map& id2Name) { } } -// void buildNameMapping(const string& fileName, Gia_Man_t* pGia, map& id2Name) { -// yosysMgr->buildMapping(fileName); -// parseAigMapping(pGia, id2Name); -// } -void CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { +const bool CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { // log_make_debug = true; CirGateV gateV; Gia_Man_t* pGia = NULL; // the gia pointer of abc @@ -82,16 +78,16 @@ void CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { // abc function parameters char* pFileName = new char[100]; - cout << "filename = " << fileName << endl; + // cout << "filename = " << fileName << endl; strcpy(pFileName, fileName.c_str()); - char* pTopModule = NULL; + char* pTopModule = NULL; char* pDefines = NULL; - int fBlast = 1; + int fBlast = 1; int fInvert = 0; int fTechMap = 1; int fSkipStrash = 0; int fCollapse = 0; - int c, fVerbose = 0; + int c, fVerbose = 0; int i, *pWire; if (fileType == AIGER) @@ -101,7 +97,7 @@ void CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { if (!pGia) { cerr << "Cannot open design \"" << fileName << "\"!!" << endl; - return; + return false; } if (fileType == VERILOG) { yosysMgr->buildMapping(fileName); @@ -190,10 +186,6 @@ void CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { CirGate* riGate = getGate(riGid); CirRoGate* roGate = static_cast(getGate(roGid)); roGate->setIn0(riGate, false); - - // cout << Gia_ObjId(pGia, pObjRi) << endl; - // cout << Gia_ObjId(pGia, pObjRo) << endl;//<< " <---> "<< PPI2RO[Gia_ObjId(pGia,pObjRo)]<< endl; - // cout << " --- \n"; } // CONST1 Gate _const1 = new CirAigGate(getNumTots(), 0); @@ -202,19 +194,12 @@ void CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { _const1->setIn1(_const0, true); genDfsList(); - - // DEBUG - // for (int i = 0; i < _totGateList.size(); ++i) { - // CirGate* g = _totGateList[i]; - // // if (g->getType() == RI_GATE || g->getType() == PO_GATE) isPrint = true; - // if (g) g->printGate(); - // } - // _poList[0]->printGate(); + return true; } void CirMgr::initCir(Gia_Man_t* pGia, const CirFileType& fileType) { // Create lists - cout << "initializing ..." << endl; + // cout << "initializing ..." << endl; int piNum = 0, regNum = 0, poNum = 0, totNum = 0; if (fileType == VERILOG) { piNum = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; @@ -250,36 +235,36 @@ void CirMgr::initCir(Gia_Man_t* pGia, const CirFileType& fileType) { // } CirGate* CirMgr::createNotGate(CirGate* in0) { - CirGate* notGate = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(notGate); + CirGate* notGate = new CirAigGate(getNumTots(), 0); + addTotGate(notGate); notGate->setIn0(in0, true); notGate->setIn1(_const1, false); return notGate; } CirGate* CirMgr::createAndGate(CirGate* in0, CirGate* in1) { - CirGate* andGate = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(andGate); + CirGate* andGate = new CirAigGate(getNumTots(), 0); + addTotGate(andGate); andGate->setIn0(in0, false); andGate->setIn1(in1, false); return andGate; } CirGate* CirMgr::createOrGate(CirGate* in0, CirGate* in1) { - CirGate* tmpGate = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(tmpGate); + CirGate* tmpGate = new CirAigGate(getNumTots(), 0); + addTotGate(tmpGate); tmpGate->setIn0(in0, true); tmpGate->setIn1(in1, true); return createNotGate(tmpGate); } CirGate* CirMgr::createXorGate(CirGate* in0, CirGate* in1) { - CirGate* tmpGate0 = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(tmpGate0); - CirGate* tmpGate1 = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(tmpGate1); - CirGate* tmpGate2 = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(tmpGate2); + CirGate* tmpGate0 = new CirAigGate(getNumTots(), 0); + addTotGate(tmpGate0); + CirGate* tmpGate1 = new CirAigGate(getNumTots(), 0); + addTotGate(tmpGate1); + CirGate* tmpGate2 = new CirAigGate(getNumTots(), 0); + addTotGate(tmpGate2); tmpGate0->setIn0(in0, true); tmpGate0->setIn1(in1, false); tmpGate1->setIn0(in0, false); diff --git a/src/cir/cirBdd.cpp b/src/cir/cirBdd.cpp index 804f3af5..55fc357c 100644 --- a/src/cir/cirBdd.cpp +++ b/src/cir/cirBdd.cpp @@ -1,20 +1,16 @@ /**************************************************************************** - FileName [ v3NtkBdd.cpp ] - PackageName [ v3/src/ntk ] - Synopsis [ V3 Network to BDDs. ] - Author [ Cheng-Yin Wu ] - Copyright [ Copyright(c) 2012-present LaDs(III), GIEE, NTU, Taiwan ] + FileName [ cirBdd.cpp ] + PackageName [ cir ] + Synopsis [ Define BDD manager functions ] + Author [ Design Verification Lab ] + Copyright [ Copyright(c) 2023-present DVLab, GIEE, NTU, Taiwan ] ****************************************************************************/ -#ifndef V3_NTK_C -#define V3_NTK_C - #include "bddMgrV.h" // MODIFICATION FOR SoCV BDD #include "bddNodeV.h" // MODIFICATION FOR SoCV BDD #include "cirGate.h" #include "cirMgr.h" #include "gvMsg.h" -#include "stack" #include "util.h" extern BddMgrV* bddMgrV; // MODIFICATION FOR SoCV BDD @@ -106,4 +102,3 @@ void CirMgr::buildBdd(CirGate* gate) { } } -#endif diff --git a/src/cir/cirCmd.cpp b/src/cir/cirCmd.cpp index 66a90f71..6bab72d4 100644 --- a/src/cir/cirCmd.cpp +++ b/src/cir/cirCmd.cpp @@ -14,6 +14,8 @@ #include "cirGate.h" #include "cirMgr.h" +#include "gvCmdMgr.h" +#include "gvModMgr.h" #include "gvMsg.h" #include "util.h" @@ -91,8 +93,8 @@ GVCmdExecStatus CirReadCmd::exec(const string& option) { } } cirMgr = new CirMgr; - cirMgr->readCirFromAbc(fileName, fileType); - // curCmd = CIRREAD; + if (cirMgr->readCirFromAbc(fileName, fileType)) + gvModMgr->setInputFileExist(true); return GV_CMD_EXEC_DONE; } diff --git a/src/cir/cirGate.h b/src/cir/cirGate.h index a5f0f59e..40a0147f 100644 --- a/src/cir/cirGate.h +++ b/src/cir/cirGate.h @@ -15,7 +15,7 @@ #include #include #include "cirDef.h" -#include "sat.h" +#include "gvSat.h" using namespace std; diff --git a/src/cir/cirMgr.h b/src/cir/cirMgr.h index 29a7e3b9..0aa4e37a 100644 --- a/src/cir/cirMgr.h +++ b/src/cir/cirMgr.h @@ -114,9 +114,8 @@ class CirMgr void initCir(Gia_Man_t* pGia, const CirFileType& type); void buildBdd(CirGate* gate); void buildNtkBdd(); - void readCirFromAbc(string fileName, CirFileType fileType); void addTotGate(CirGate* gate){_totGateList.push_back(gate);}; - // void parseAigMapping(Gia_Man_t* pGia, map& id2Name); + const bool readCirFromAbc(string fileName, CirFileType fileType); const bool setBddOrder(const bool& file); // CirGate* createGate(const GateType& type); CirGate* createNotGate(CirGate* in0); diff --git a/src/cmd/.depend.mak b/src/cmd/.depend.mak index e69de29b..fc75d675 100644 --- a/src/cmd/.depend.mak +++ b/src/cmd/.depend.mak @@ -0,0 +1,5 @@ +gvCmdComm.o: gvCmdComm.cpp gvCmdComm.h gvCmdMgr.h ../../include/gvMsg.h \ + ../../include/gvUsage.h ../../include/gvMsg.h ../../include/gvIntType.h \ + ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h +gvCmdMgr.o: gvCmdMgr.cpp gvCmdMgr.h ../../include/gvMsg.h \ + ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/cmd/gvCmdMgr.cpp b/src/cmd/gvCmdMgr.cpp index 7c426676..ed5a3a93 100644 --- a/src/cmd/gvCmdMgr.cpp +++ b/src/cmd/gvCmdMgr.cpp @@ -1,17 +1,18 @@ #ifndef GV_CMD_MGR_C #define GV_CMD_MGR_C +#include "gvCmdMgr.h" + #include #include #include #include -#include "gvCmdMgr.h" #include "gvMsg.h" #include "util.h" -extern "C" -{ + +extern "C" { #include #include } @@ -20,8 +21,7 @@ extern "C" * Class GVCmdMgr Implementations \* -------------------------------------------------- */ -bool -GVCmdExec::operator<(const GVCmdExec& rhs) const { +bool GVCmdExec::operator<(const GVCmdExec& rhs) const { string lstr, rstr; for (size_t idx = 0; idx < _cmdLen; ++idx) { if (idx != 0) lstr.append(" "); @@ -36,8 +36,7 @@ GVCmdExec::operator<(const GVCmdExec& rhs) const { return (lstr < rstr); } -void -GVCmdExec::lexOptions(const string& option, vector& tokens) const { +void GVCmdExec::lexOptions(const string& option, vector& tokens) const { string token; size_t n = myStrGetTok(option, token); while (token.size()) { @@ -46,57 +45,53 @@ GVCmdExec::lexOptions(const string& option, vector& tokens) const { } } -bool -GVCmdExec::lexSingleOption -(const string& option, string& token, bool optional) const -{ - size_t n = myStrGetTok(option, token); - if (!optional) { - if (token.size() == 0) { - errorOption(GV_CMD_OPT_MISSING, ""); - return false; - } - } - if (n != string::npos) { - errorOption(GV_CMD_OPT_EXTRA, option.substr(n)); - return false; - } - return true; +bool GVCmdExec::lexSingleOption(const string& option, string& token, bool optional) const { + size_t n = myStrGetTok(option, token); + if (!optional) { + if (token.size() == 0) { + errorOption(GV_CMD_OPT_MISSING, ""); + return false; + } + } + if (n != string::npos) { + errorOption(GV_CMD_OPT_EXTRA, option.substr(n)); + return false; + } + return true; } GVCmdExecStatus GVCmdExec::errorOption(GVCmdOptionError err, const string& opt) const { switch (err) { - case GV_CMD_OPT_MISSING: - if (opt.size()) - gvMsg(GV_MSG_ERR) << "Missing option \"" << opt << "\" !!" << endl; - else - gvMsg(GV_MSG_ERR) << "Missing option" - << "!!" << endl; - break; - case GV_CMD_OPT_EXTRA: - gvMsg(GV_MSG_ERR) << "Extra option \"" << opt << "\" !!" << endl; - break; - case GV_CMD_OPT_ILLEGAL: - gvMsg(GV_MSG_ERR) << "Illegal option \"" << opt << "\" !!" << endl; - break; - case GV_CMD_OPT_FOPEN_FAIL: - gvMsg(GV_MSG_ERR) << "Error: cannot open file \"" << opt << "\" !!" - << endl; - break; - default: - gvMsg(GV_MSG_ERR) << "Unknown option error type \"" << err << "\" !!" - << endl; - break; + case GV_CMD_OPT_MISSING: + if (opt.size()) + gvMsg(GV_MSG_ERR) << "Missing option \"" << opt << "\" !!" << endl; + else + gvMsg(GV_MSG_ERR) << "Missing option" + << "!!" << endl; + break; + case GV_CMD_OPT_EXTRA: + gvMsg(GV_MSG_ERR) << "Extra option \"" << opt << "\" !!" << endl; + break; + case GV_CMD_OPT_ILLEGAL: + gvMsg(GV_MSG_ERR) << "Illegal option \"" << opt << "\" !!" << endl; + break; + case GV_CMD_OPT_FOPEN_FAIL: + gvMsg(GV_MSG_ERR) << "Error: cannot open file \"" << opt << "\" !!" + << endl; + break; + default: + gvMsg(GV_MSG_ERR) << "Unknown option error type \"" << err << "\" !!" + << endl; + break; } return GV_CMD_EXEC_ERROR; } -bool -GVCmdExec::checkCmd(const string& check) const { - unsigned len = this->getCmdLen(); - bool result = false; - size_t space = 0, nxt_space; +bool GVCmdExec::checkCmd(const string& check) const { + unsigned len = this->getCmdLen(); + bool result = false; + size_t space = 0, nxt_space; for (unsigned word = 1; word <= len; ++word) { nxt_space = check.find(' ', space + 1); @@ -104,7 +99,7 @@ GVCmdExec::checkCmd(const string& check) const { for (unsigned i = space + 1; i <= nxt_space; ++i) { string checkMand = check.substr(space, i - space); - string checkOpt = check.substr(i, nxt_space - space - i); + string checkOpt = check.substr(i, nxt_space - space - i); if (checkMandCmd(checkMand, word) && (checkOpt.empty() || checkOptCmd(checkOpt, word))) { @@ -115,21 +110,20 @@ GVCmdExec::checkCmd(const string& check) const { if (result == false) return false; result = false; - space = nxt_space + 1; + space = nxt_space + 1; } return true; } -bool -GVCmdExec::checkCmd(const string& check, size_t idx) const { +bool GVCmdExec::checkCmd(const string& check, size_t idx) const { if (idx >= this->getCmdLen()) return false; bool result = false; for (unsigned i = 1, n = check.size(); i <= n; ++i) { string checkMand = check.substr(0, i); - string checkOpt = check.substr(i, n + 1 - i); + string checkOpt = check.substr(i, n + 1 - i); if (checkMandCmd(checkMand, idx) && (checkOpt.empty() || checkOptCmd(checkOpt, idx))) { @@ -140,8 +134,7 @@ GVCmdExec::checkCmd(const string& check, size_t idx) const { return result; } -bool -GVCmdExec::checkMandCmd(const string& check, size_t idx) const { +bool GVCmdExec::checkMandCmd(const string& check, size_t idx) const { if (check.size() != _mandCmd[idx - 1].size()) return false; for (unsigned i = 0, n = _mandCmd[idx - 1].size(); i < n; ++i) { if (!check[i]) return true; @@ -152,8 +145,7 @@ GVCmdExec::checkMandCmd(const string& check, size_t idx) const { return true; } -bool -GVCmdExec::checkOptCmd(const string& check, size_t idx) const { +bool GVCmdExec::checkOptCmd(const string& check, size_t idx) const { if (check.size() > _optCmd[idx - 1].size()) return false; for (unsigned i = 0, n = _optCmd[idx - 1].size(); i < n; ++i) { if (!check[i]) return true; @@ -177,8 +169,7 @@ GVCmdMgr::~GVCmdMgr() { if (_dofile.is_open()) _dofile.close(); } -bool -GVCmdMgr::regCmd(const string& cmd, unsigned nCmp, GVCmdExec* e) { +bool GVCmdMgr::regCmd(const string& cmd, unsigned nCmp, GVCmdExec* e) { assert(e); assert(cmd.size()); assert(nCmp); @@ -195,20 +186,20 @@ GVCmdMgr::regCmd(const string& cmd, unsigned nCmp, GVCmdExec* e) { e->setMandCmd(str.substr(0, nCmp)); e->setOptCmd(str.substr(nCmp)); - GVCmdExecSet::iterator it = _cmdLib.find(e->getGVCmdType()); - GVCmdExecSubSet* cmdSet = 0; + GVCmdExecSet::iterator it = _cmdLib.find(e->getGVCmdType()); + GVCmdExecSubSet* cmdSet = 0; if (it == _cmdLib.end()) { cmdSet = new GVCmdExecSubSet(); _cmdLib.insert(make_pair(e->getGVCmdType(), cmdSet)); - } else cmdSet = it->second; + } else + cmdSet = it->second; cmdSet->insert(e); return true; } -bool -GVCmdMgr::regCmd(const string& cmd, unsigned nCmp1, unsigned nCmp2, - GVCmdExec* e) { +bool GVCmdMgr::regCmd(const string& cmd, unsigned nCmp1, unsigned nCmp2, + GVCmdExec* e) { assert(e); assert(cmd.size()); assert(nCmp1); @@ -236,12 +227,13 @@ GVCmdMgr::regCmd(const string& cmd, unsigned nCmp1, unsigned nCmp2, e->setMandCmd(str2.substr(0, nCmp2)); e->setOptCmd(str2.substr(nCmp2)); - GVCmdExecSet::iterator it = _cmdLib.find(e->getGVCmdType()); - GVCmdExecSubSet* cmdSet = 0; + GVCmdExecSet::iterator it = _cmdLib.find(e->getGVCmdType()); + GVCmdExecSubSet* cmdSet = 0; if (it == _cmdLib.end()) { cmdSet = new GVCmdExecSubSet(); _cmdLib.insert(make_pair(e->getGVCmdType(), cmdSet)); - } else cmdSet = it->second; + } else + cmdSet = it->second; cmdSet->insert(e); return true; } @@ -249,34 +241,35 @@ GVCmdMgr::regCmd(const string& cmd, unsigned nCmp1, unsigned nCmp2, GVCmdExecStatus GVCmdMgr::execOneCmd() { // Read User Command Input - string str = ""; - char* execCmd = new char[1024]; + string str = ""; + char* execCmd = new char[1024]; if (_dofile.is_open()) { getline(_dofile, str); strcpy(execCmd, str.c_str()); cout << getPrompt() << execCmd << endl; if (_dofile.eof()) closeDofile(); - } else execCmd = readline(getPrompt().c_str()); + } else + execCmd = readline(getPrompt().c_str()); assert(execCmd); if (addHistory(execCmd)) { add_history(_history.back().c_str()); - string option = ""; - GVCmdExec* e = parseCmd(option); + string option = ""; + GVCmdExec* e = parseCmd(option); // Check command types if (e) { GVCmdType cmdType = e->getGVCmdType(); - // if (getPrompt().find("vrf") != string::npos) { - // if (_vrfMode.find(cmdType) == _vrfMode.end()) { - // cout << "Please switch to \"SETUP MODE\" !!" << endl; - // return GV_CMD_EXEC_NOP; - // } - // } else { - // if (_setupMode.find(cmdType) == _setupMode.end()) { - // cout << "Please switch to \"VRF MODE\" !!" << endl; - // return GV_CMD_EXEC_NOP; - // } - // } + if (getPrompt().find("vrf") != string::npos) { + if (_vrfMode.find(cmdType) == _vrfMode.end()) { + cout << "Please switch to \"SETUP MODE\" !!" << endl; + return GV_CMD_EXEC_NOP; + } + } else { + if (_setupMode.find(cmdType) == _setupMode.end()) { + cout << "Please switch to \"VRF MODE\" !!" << endl; + return GV_CMD_EXEC_NOP; + } + } } if (e) return e->exec(option); @@ -292,7 +285,7 @@ GVCmdMgr::parseCmd(string& option) { assert(str[0] != 0 && str[0] != ' '); GVCmdExec* e = 0; - string cmd; + string cmd; // normalize: keep only one space between two words unsigned delCount = 0; @@ -335,7 +328,8 @@ GVCmdMgr::parseCmd(string& option) { if ((_cmd == "ls") || (_cmd == "vi") || (_cmd == "vim") || (_cmd == "echo") || (_cmd == "cat") || (_cmd == "clear")) system(str.c_str()); - else gvMsg(GV_MSG_ERR) << "Illegal command!! (" << str << ")" << endl; + else + gvMsg(GV_MSG_ERR) << "Illegal command!! (" << str << ")" << endl; } else if (idx != string::npos) { size_t opt = str.find_first_not_of(' ', idx); if (opt != string::npos) option = str.substr(opt); @@ -354,7 +348,7 @@ GVCmdMgr::getCmd(const string& cmd) const { if (cmd[i] == ' ') ++spCount; GVCmdExecSet::const_iterator it; - GVCmdExecSubSet::iterator is; + GVCmdExecSubSet::iterator is; for (it = _cmdLib.begin(); it != _cmdLib.end(); ++it) { for (is = it->second->begin(); is != it->second->end(); ++is) { if (((*is)->getCmdLen() == spCount + 1) && (*is)->checkCmd(cmd)) { @@ -377,7 +371,7 @@ GVCmdMgr::getCmdListFromPart(const string& cmd) const { if (cmd[i] == ' ') ++spCount; GVCmdExecSet::const_iterator it; - GVCmdExecSubSet::iterator is; + GVCmdExecSubSet::iterator is; for (it = _cmdLib.begin(); it != _cmdLib.end(); ++it) { if (it->first != GV_CMD_TYPE_REVEALED) { for (is = it->second->begin(); is != it->second->end(); ++is) { @@ -397,10 +391,9 @@ GVCmdMgr::getCmdListFromPart(const string& cmd) const { return result; } -void -GVCmdMgr::printHelps(bool revealed) const { +void GVCmdMgr::printHelps(bool revealed) const { GVCmdExecSet::const_iterator it; - GVCmdExecSubSet::iterator is; + GVCmdExecSubSet::iterator is; gvMsg(GV_MSG_IFO) << endl; for (it = _cmdLib.begin(); it != _cmdLib.end(); ++it) { if ((revealed) ^ (it->first != GV_CMD_TYPE_REVEALED)) { @@ -413,8 +406,7 @@ GVCmdMgr::printHelps(bool revealed) const { } } -void -GVCmdMgr::printHistory(int nPrint) const { +void GVCmdMgr::printHistory(int nPrint) const { int historySize = _history.size(); if (historySize == 0) { gvMsg(GV_MSG_IFO) << "Empty command history!!" << endl; @@ -426,8 +418,7 @@ GVCmdMgr::printHistory(int nPrint) const { gvMsg(GV_MSG_IFO) << " " << i << ": " << _history[i] << endl; } -bool -GVCmdMgr::addHistory(char* cmd) { +bool GVCmdMgr::addHistory(char* cmd) { // remove ' ' at the end char* tmp = &(cmd[strlen(cmd) - 1]); while ((tmp >= cmd) && (*tmp == ' ')) *(tmp--) = 0; diff --git a/src/cmd/gvCmdMgr.h b/src/cmd/gvCmdMgr.h index 16c00068..2a45b6c6 100644 --- a/src/cmd/gvCmdMgr.h +++ b/src/cmd/gvCmdMgr.h @@ -51,7 +51,7 @@ enum GVCmdOptionError { }; const unordered_set _setupMode{GV_CMD_TYPE_REVEALED, GV_CMD_TYPE_COMMON, GV_CMD_TYPE_NETWORK, - GV_CMD_TYPE_ABC, GV_CMD_TYPE_MOD, GV_CMD_TYPE_BDD, GV_CMD_TYPE_PROVE}; + GV_CMD_TYPE_ABC, GV_CMD_TYPE_MOD, GV_CMD_TYPE_BDD}; const unordered_set _vrfMode{GV_CMD_TYPE_VERIFY, GV_CMD_TYPE_SIMULATE, GV_CMD_TYPE_COMMON, GV_CMD_TYPE_MOD, GV_CMD_TYPE_PROVE, GV_CMD_TYPE_ITP}; @@ -78,8 +78,8 @@ class GVCmdExec { inline void setCmdLen(unsigned n) { _cmdLen = n; } inline unsigned getCmdLen() const { return _cmdLen; } inline void setMandCmd(const string& str) { _mandCmd.push_back(str); } - inline const string& getMandCmd(size_t idx) const { return _mandCmd[idx]; } inline void setOptCmd(const string& str) { _optCmd.push_back(str); } + inline const string& getMandCmd(size_t idx) const { return _mandCmd[idx]; } inline const string& getOptCmd(size_t idx) const { return _optCmd[idx]; } bool checkCmd(const string&) const; bool checkCmd(const string&, size_t) const; diff --git a/src/ext/sim.so b/src/ext/sim.so index 25cae8a185292e488418c023ca82856003b06db7..a2a96a590d22e10fde82c63e2a571eeb07b78eaf 100755 GIT binary patch delta 780 zcmXZZT}V@50LJm1bKbL$b52OvZY1!g@M5?XWFJP@)!L1b)J+!|IL4^dK33)mnPg-} zH+r*()(2DuL5w7KVb=amt)06EJMYf5HFO;BY5F?#%WgmEhV(>65{1!3!BT9+sU-?#sHGIqRjZO#x|K`H zb>)S!ptx2jlvH*pw$*GmoYLX{r(0)M9~T#C<8Vtj=WVqITugKJ2I@?(z6ocU_SY(@ zI=t-((+JJNO>njiGSDN!$7pBavM|?ZH)xOG3G*5470g2&7KHVkwnB3q5r-C0GOg0I zvD47SJVf*PN{)GgIV9YxFu}YDlQ0dl!n}s}%tcs+Kj0c&tPxfdBw#1(E#Uz;0!3kl zY2(6f*H5r-t3@7)(3FVIz;k#9A7Bn<^f$-8sChq_X-#jHX=shyZh%c9nuHy0C?E3n zsd|T@SGX5oOvJ#O5YYafV!75%d@-ZM+^le3jkzhV?u2`dpL zs>Bqp=2!fI{&3-FUox955BouUZGY}uejt?}*qkby&ZcsMXUcnmAYPmGgU^}Tor6Jj Yqh*)7iotekq&!v(I;>CSx5Z%TAGqLtQvd(} delta 788 zcmW;JOGs2<00rRxb@jd=q!tx~i;U1K-9po9(`JemMHoR)2Gva*wMpyRH2Gcd*Zbw&J5sU@HGwk*4U zWoCWD;CyoEYq566^Ig$sMQ!S{>I8ny2XQWlC87{r3Sx75b(S{)l0e##LF6j(5}8J{ z6rvH?h$vaB79Cr7u?5<3CVO~smTj2a1bRTB-QmR;&)$$SCy`%(uCV=+cz-SVv<*xR zSplqio;8!LAFqhe`u{|I~&Zlgz$RsI~X&}F|&9P|>7L!#VYXWGRxD#Y2 z=N>kP{}OSgI8OmUPvCwIvhc>&C8@_}=fRLEbV4K6$&my&wYO15Na8`)1z0&|9K z7^n^S2&#ZqeGiDoz#b>h$XoJ}yeH$95YA^b_a|op)BVG#*lKvYoU86bLJcQ#k0AbS1^c$R3X)f zjW~!~@(N!1XhWFnO?8CH2)|t?!o%q!2M>k)slKo?y*7-GM`6c6zlgh1Yoe(1$n$@1 eE8W`dKdF-<- #include -GVSatSolver::GVSatSolver(GVNtkMgr* ntk) : _ntk(NULL) { - _solver = new SolverV(); +#include "cirGate.h" +#include "cirMgr.h" + +GVSatSolver::GVSatSolver(CirMgr* cirMgr) : _cirMgr(cirMgr) { + _solver = new SolverV(); _solver->proof = new Proof(); _assump.clear(); _curVar = 0; _solver->newVar(); ++_curVar; - // _ntkData = new vector[ntk->getNetSize()]; - // for (uint32_t i = 0; i < ntk->getNetSize(); ++i) _ntkData[i].clear(); - _ntkData = new vector[cirMgr->getNumTots()]; - for (uint32_t i = 0; i < cirMgr->getNumTots(); ++i) _ntkData[i].clear(); + _ntkData = new vector[_cirMgr->getNumTots()]; + for (uint32_t i = 0; i < _cirMgr->getNumTots(); ++i) _ntkData[i].clear(); } GVSatSolver::~GVSatSolver() { delete _solver; assumeRelease(); - for (uint32_t i = 0; i < _ntk->getNetSize(); ++i) _ntkData[i].clear(); + for (uint32_t i = 0; i < _cirMgr->getNumTots(); ++i) _ntkData[i].clear(); delete[] _ntkData; } -void -GVSatSolver::reset() { +void GVSatSolver::reset() { delete _solver; - _solver = new SolverV(); + _solver = new SolverV(); _solver->proof = new Proof(); _assump.clear(); _curVar = 0; _solver->newVar(); ++_curVar; - _ntkData = new vector[_ntk->getNetSize()]; - for (uint32_t i = 0; i < _ntk->getNetSize(); ++i) _ntkData[i].clear(); + _ntkData = new vector[_cirMgr->getNumTots()]; + for (uint32_t i = 0; i < _cirMgr->getNumTots(); ++i) _ntkData[i].clear(); } -void -GVSatSolver::assumeRelease() { +void GVSatSolver::assumeRelease() { _assump.clear(); } -void -GVSatSolver::assumeProperty(const size_t& var, const bool& invert) { +void GVSatSolver::assumeProperty(const size_t& var, const bool& invert) { _assump.push(mkLit(getOriVar(var), invert ^ isNegFormula(var))); } -void -GVSatSolver::assertProperty(const size_t& var, const bool& invert) { +void GVSatSolver::assertProperty(const size_t& var, const bool& invert) { _solver->addUnit(mkLit(getOriVar(var), invert ^ isNegFormula(var))); } -void -GVSatSolver::assumeProperty(const CirGate* gate, const bool& invert, const uint32_t& depth) { +void GVSatSolver::assumeProperty(const CirGate* gate, const bool& invert, const uint32_t& depth) { const Var var = getVerifyData(gate, depth); - // _assump.push(mkLit(var, invert ^ id.cp)); _assump.push(mkLit(var, invert)); } -void -GVSatSolver::assertProperty(const CirGate* gate, const bool& invert, const uint32_t& depth) { +void GVSatSolver::assertProperty(const CirGate* gate, const bool& invert, const uint32_t& depth) { const Var var = getVerifyData(gate, depth); - // _solver->addUnit(mkLit(var, invert ^ id.cp)); _solver->addUnit(mkLit(var, invert)); } @@ -96,18 +88,22 @@ GVSatSolver::assump_solve() { const GVBitVecX GVSatSolver::getDataValue(const CirGate* gate, const uint32_t& depth) const { - Var var = getVerifyData(gate, depth); - uint32_t i, width = 1; + Var var = getVerifyData(gate, depth); + uint32_t i, width = 1; GVBitVecX value(width); // Modification for cir structure if (false) { for (i = 0; i < width; ++i) - if (gv_l_True == _solver->model[var + i]) value.set0(i); - else value.set1(i); + if (gv_l_True == _solver->model[var + i]) + value.set0(i); + else + value.set1(i); } else { for (i = 0; i < width; ++i) - if (gv_l_True == _solver->model[var + i]) value.set1(i); - else value.set0(i); + if (gv_l_True == _solver->model[var + i]) + value.set1(i); + else + value.set0(i); } return value; } @@ -123,11 +119,9 @@ GVSatSolver::getFormula(const GVNetId& id, const uint32_t& depth) { // return (id.fanin0Cp ? getNegVar(var) : getPosVar(var)); } -void -GVSatSolver::resizeNtkData(const uint32_t& num) { - // vector* tmp = new vector[_ntk->getNetSize()]; - vector* tmp = new vector[cirMgr->getNumTots()]; - for (uint32_t i = 0, j = cirMgr->getNumTots() - num; i < j; ++i) tmp[i] = _ntkData[i]; +void GVSatSolver::resizeNtkData(const uint32_t& num) { + vector* tmp = new vector[_cirMgr->getNumTots()]; + for (uint32_t i = 0, j = _cirMgr->getNumTots() - num; i < j; ++i) tmp[i] = _ntkData[i]; delete[] _ntkData; _ntkData = tmp; } @@ -142,42 +136,35 @@ GVSatSolver::newVar() { const Var GVSatSolver::getVerifyData(const CirGate* gate, const uint32_t& depth) const { - if (depth >= _ntkData[gate->getGid()].size()) return 0; - else return _ntkData[gate->getGid()][depth]; + if (depth >= _ntkData[gate->getGid()].size()) + return 0; + else + return _ntkData[gate->getGid()][depth]; } -void -GVSatSolver::add_FALSE_Formula(const CirGate* gate, const uint32_t& depth) { - // const uint32_t index = getGVNetIndex(out); +void GVSatSolver::add_FALSE_Formula(const CirGate* gate, const uint32_t& depth) { const uint32_t index = gate->getGid(); _ntkData[index].push_back(newVar()); _solver->addUnit(mkLit(_ntkData[index].back(), true)); } -void -GVSatSolver::add_PI_Formula(const CirGate* gate, const uint32_t& depth) { - // const uint32_t index = getGVNetIndex(out); +void GVSatSolver::add_PI_Formula(const CirGate* gate, const uint32_t& depth) { const uint32_t index = gate->getGid(); _ntkData[index].push_back(newVar()); } -void -GVSatSolver::add_FF_Formula(const CirGate* gate, const uint32_t& depth) { - // const uint32_t index = getGVNetIndex(out); +void GVSatSolver::add_FF_Formula(const CirGate* gate, const uint32_t& depth) { const uint32_t index = gate->getGid(); - // assert(depth == _ntkData[index].size()); - if (depth) { // Build FF I/O Relation - // const GVNetId in1 = _ntk->getInputNetId(out, 0); - CirGateV in0 = gate->getIn0(); - const Var var1 = getVerifyData(in0.gate(), depth - 1); + CirGateV in0 = gate->getIn0(); + const Var var1 = getVerifyData(in0.gate(), depth - 1); if (in0.isInv()) { // a <-> b _ntkData[index].push_back(newVar()); - Lit a = mkLit(_ntkData[index].back()); - Lit b = mkLit(var1, true); + Lit a = mkLit(_ntkData[index].back()); + Lit b = mkLit(var1, true); vec lits; lits.clear(); lits.push(~a); @@ -188,26 +175,24 @@ GVSatSolver::add_FF_Formula(const CirGate* gate, const uint32_t& depth) { lits.push(~b); _solver->addClause(lits); lits.clear(); - } else _ntkData[index].push_back(var1); - } else { // Timeframe 0 + } else + _ntkData[index].push_back(var1); + } else { // Timeframe 0 _ntkData[index].push_back(newVar()); } } -void -GVSatSolver::add_AND_Formula(const CirGate* gate, const uint32_t& depth) { +void GVSatSolver::add_AND_Formula(const CirGate* gate, const uint32_t& depth) { // const uint32_t index = getGVNetIndex(out); const uint32_t index = gate->getGid(); _ntkData[index].push_back(newVar()); - const Var& var = _ntkData[index].back(); + const Var& var = _ntkData[index].back(); // Build AND I/O Relation - // const GVNetId in1 = _ntk->getInputNetId(out, 0); - // const GVNetId in2 = _ntk->getInputNetId(out, 1); - const CirGateV in0 = gate->getIn0(); - const CirGateV in1 = gate->getIn1(); - const Var var0 = getVerifyData(in0.gate(), depth); - const Var var1 = getVerifyData(in1.gate(), depth); + const CirGateV in0 = gate->getIn0(); + const CirGateV in1 = gate->getIn1(); + const Var var0 = getVerifyData(in0.gate(), depth); + const Var var1 = getVerifyData(in1.gate(), depth); Lit y = mkLit(var); Lit a = mkLit(var0, in0.isInv()); @@ -230,17 +215,16 @@ GVSatSolver::add_AND_Formula(const CirGate* gate, const uint32_t& depth) { lits.clear(); } -void -GVSatSolver::addBoundedVerifyData(const CirGate* gate, const uint32_t& depth) { +void GVSatSolver::addBoundedVerifyData(const CirGate* gate, const uint32_t& depth) { if (existVerifyData(gate, depth)) return; addBoundedVerifyDataRecursively(gate, depth); } -void -GVSatSolver::addBoundedVerifyDataRecursively(const CirGate* gate, const uint32_t& depth) { +void GVSatSolver::addBoundedVerifyDataRecursively(const CirGate* gate, const uint32_t& depth) { GateType type = gate->getType(); if (existVerifyData(gate, depth)) return; - if (type == PI_GATE) add_PI_Formula(gate, depth); + if (type == PI_GATE) + add_PI_Formula(gate, depth); else if (RO_GATE == type || RI_GATE == type) { uint32_t newDepth = depth; if (depth) { @@ -248,8 +232,7 @@ GVSatSolver::addBoundedVerifyDataRecursively(const CirGate* gate, const uint32_t addBoundedVerifyDataRecursively(gate->getIn0Gate(), newDepth); } add_FF_Formula(gate, depth); - } - else{ + } else { if (type == PO_GATE) { addBoundedVerifyDataRecursively(gate->getIn0Gate(), depth); add_FF_Formula(gate, depth); @@ -262,9 +245,6 @@ GVSatSolver::addBoundedVerifyDataRecursively(const CirGate* gate, const uint32_t add_FALSE_Formula(gate, depth); } } - // } else { - // // assert(0); - // } } const bool diff --git a/src/gvsat/gvSat.h b/src/gvsat/gvSat.h new file mode 100644 index 00000000..74e0c99e --- /dev/null +++ b/src/gvsat/gvSat.h @@ -0,0 +1,80 @@ +/**************************************************************************** + FileName [ sat.h ] + PackageName [ sat ] + Synopsis [ Define miniSat solver interface functions ] + Author [ Chung-Yang (Ric) Huang, Cheng-Yin Wu ] + Copyright [ Copyleft(c) 2010-2014 LaDs(III), GIEE, NTU, Taiwan ] +****************************************************************************/ + +#ifndef GV_SAT_H +#define GV_SAT_H + +#include +#include +#include + +#include "SolverV.h" +#include "cirGate.h" +#include "cirMgr.h" +#include "gvBitVec.h" +#include "gvNtk.h" +using namespace std; + +class SATMgr; + +/********** MiniSAT_Solver **********/ +class GVSatSolver { + friend class SATMgr; + +public: + GVSatSolver(CirMgr*); + ~GVSatSolver(); + + void reset(); + void assumeRelease(); + void assumeProperty(const size_t&, const bool&); + void assertProperty(const size_t&, const bool&); + void assumeProperty(const CirGate* gate, const bool& invert, const uint32_t& depth); + void assertProperty(const CirGate* gate, const bool& invert, const uint32_t& depth); + const bool simplify(); + const bool solve(); + const bool assump_solve(); + int getNumClauses() const { return _solver->nRootCla(); } + + // Network to Solver Functions + const size_t getFormula(const GVNetId&, const uint32_t&); + const GVBitVecX getDataValue(const CirGate*, const uint32_t&) const; + const bool getDataValue(const size_t&) const; + // Variable Interface Functions + inline const size_t reserveFormula() { return getPosVar(newVar()); } + inline const bool isNegFormula(const size_t& v) const { return (v & 1ul); } + inline const size_t getNegFormula(const size_t& v) const { return (v ^ 1ul); } + + // Gate Formula to Solver Functions + void add_FALSE_Formula(const CirGate*, const uint32_t&); + void add_PI_Formula(const CirGate*, const uint32_t&); + void add_FF_Formula(const CirGate*, const uint32_t&); + void add_AND_Formula(const CirGate*, const uint32_t&); + + void addBoundedVerifyData(const CirGate*, const uint32_t&); + const bool existVerifyData(const CirGate*, const uint32_t&); + void resizeNtkData(const uint32_t& num); + +private: + const Var newVar(); + const Var getVerifyData(const CirGate*, const uint32_t&) const; + void addBoundedVerifyDataRecursively(const CirGate*, const uint32_t&); + + inline const Var getOriVar(const size_t& v) const { return (Var)(v >> 1ul); } + inline const size_t getPosVar(const Var& v) const { return (((size_t)v) << 1ul); } + inline const size_t getNegVar(const Var& v) const { return ((getPosVar(v)) | 1ul); } + + SolverV* _solver; // Pointer to a Minisat solver + Var _curVar; // Variable currently + vec _assump; // Assumption List for assumption solve + const CirMgr* _cirMgr; // Network Under Verification + vector* _ntkData; // Mapping between GVNetId and Solver Data + // GVNtkMgr* _ntk; // Network Under Verification +}; + +#endif // SAT_H diff --git a/src/itp/reader.cpp b/src/gvsat/reader.cpp similarity index 100% rename from src/itp/reader.cpp rename to src/gvsat/reader.cpp diff --git a/src/itp/reader.h b/src/gvsat/reader.h similarity index 100% rename from src/itp/reader.h rename to src/gvsat/reader.h diff --git a/src/itp/.depend.mak b/src/itp/.depend.mak index 5ddf7caa..cb19a6ff 100644 --- a/src/itp/.depend.mak +++ b/src/itp/.depend.mak @@ -1,5 +1,79 @@ -FileV.o: FileV.cpp FileV.h GlobalV.h -ProofV.o: ProofV.cpp ProofV.h SolverTypesV.h GlobalV.h FileV.h SortV.h -reader.o: reader.cpp reader.h -SolverV.o: SolverV.cpp SolverV.h ProofV.h SolverTypesV.h GlobalV.h \ - FileV.h VarOrderV.h HeapV.h SortV.h +gvSatCmd.o: gvSatCmd.cpp gvSatCmd.h ../../include/gvCmdMgr.h \ + ../../include/cirGate.h ../../include/cirDef.h ../../include/myHash.h \ + ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirMgr.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/gvBitVec.h ../../include/gvIntType.h ../../include/gvNtk.h \ + ../../include/gvAbcMgr.h ../../include/base/main/main.h \ + ../../include/base/abc/abc.h ../../include/base/main/abcapis.h \ + ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ + ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ + ../../include/base/main/main.h ../../include/misc/tim/tim.h \ + ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ + ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ + ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ + ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ + ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ + ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ + ../../include/gvAbcNtk.h ../../include/kernel/sigtools.h \ + ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ + /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ + ../../include/kernel/hashlib.h ../../include/kernel/log.h \ + ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ + ../../include/kernel/register.h ../../include/kernel/utils.h \ + ../../include/kernel/yosys.h ../../include/cirMgr.h \ + ../../include/gvMsg.h gvSatMgr.h ../../include/gvNtk.h \ + ../../include/gvSat.h ../../include/reader.h ../../include/util.h \ + ../../include/rnGen.h ../../include/myUsage.h +gvSatMgr.o: gvSatMgr.cpp gvSatMgr.h ../../include/gvNtk.h \ + ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ + ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/base/main/main.h ../../include/base/abc/abc.h \ + ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ + ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ + ../../include/base/main/mainInt.h ../../include/base/main/main.h \ + ../../include/misc/tim/tim.h ../../include/map/if/if.h \ + ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ + ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ + ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ + ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ + ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ + ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ + ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ + ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ + /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ + /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ + ../../include/kernel/log.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h \ + ../../include/kernel/utils.h ../../include/kernel/yosys.h \ + ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirDef.h ../../include/myHash.h \ + ../../include/gvSat.h ../../include/cirMgr.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h ../../include/gvNtk.h ../../include/cirGate.h \ + ../../include/cirMgr.h ../../include/reader.h ../../include/gvMsg.h diff --git a/src/itp/.extheader.mak b/src/itp/.extheader.mak index 45cf6833..29b95764 100644 --- a/src/itp/.extheader.mak +++ b/src/itp/.extheader.mak @@ -1,13 +1,7 @@ -itp.d: ../../include/gvSat.h ../../include/gvSatMgr.h ../../include/gvSatCmd.h ../../include/VarOrderV.h -../../include/gvSat.h: gvSat.h - @rm -f ../../include/gvSat.h - @ln -fs ../src/itp/gvSat.h ../../include/gvSat.h +itp.d: ../../include/gvSatMgr.h ../../include/gvSatCmd.h ../../include/gvSatMgr.h: gvSatMgr.h @rm -f ../../include/gvSatMgr.h @ln -fs ../src/itp/gvSatMgr.h ../../include/gvSatMgr.h ../../include/gvSatCmd.h: gvSatCmd.h @rm -f ../../include/gvSatCmd.h @ln -fs ../src/itp/gvSatCmd.h ../../include/gvSatCmd.h -../../include/VarOrderV.h: VarOrderV.h - @rm -f ../../include/VarOrderV.h - @ln -fs ../src/itp/VarOrderV.h ../../include/VarOrderV.h diff --git a/src/itp/Makefile b/src/itp/Makefile index 5c4d3b69..225e32e9 100644 --- a/src/itp/Makefile +++ b/src/itp/Makefile @@ -1,5 +1,5 @@ PKGFLAG = -EXTHDRS = gvSat.h gvSatMgr.h gvSatCmd.h VarOrderV.h +EXTHDRS = gvSatMgr.h gvSatCmd.h include ../Makefile.in include ../Makefile.lib diff --git a/src/itp/gvSat.h b/src/itp/gvSat.h deleted file mode 100644 index c0c1f004..00000000 --- a/src/itp/gvSat.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** - FileName [ sat.h ] - PackageName [ sat ] - Synopsis [ Define miniSat solver interface functions ] - Author [ Chung-Yang (Ric) Huang, Cheng-Yin Wu ] - Copyright [ Copyleft(c) 2010-2014 LaDs(III), GIEE, NTU, Taiwan ] -****************************************************************************/ - -#ifndef GV_SAT_H -#define GV_SAT_H - -#include "SolverV.h" -#include "gvBitVec.h" -#include "gvNtk.h" -#include "cirGate.h" -#include "cirMgr.h" -#include -#include -#include -using namespace std; - -class SATMgr; - -/********** MiniSAT_Solver **********/ -class GVSatSolver -{ - friend class SATMgr; - - public: - GVSatSolver(GVNtkMgr*); - ~GVSatSolver(); - - void reset(); - void assumeRelease(); - void assumeProperty(const size_t&, const bool&); - void assertProperty(const size_t&, const bool&); - void assumeProperty(const CirGate* gate, const bool& invert, const uint32_t& depth); - void assertProperty(const CirGate* gate, const bool& invert, const uint32_t& depth); - const bool simplify(); - const bool solve(); - const bool assump_solve(); - int getNumClauses() const { return _solver->nRootCla(); } - - // Network to Solver Functions - const size_t getFormula(const GVNetId&, const uint32_t&); - const GVBitVecX getDataValue(const CirGate*, const uint32_t&) const; - const bool getDataValue(const size_t&) const; - // Variable Interface Functions - inline const size_t reserveFormula() { return getPosVar(newVar()); } - inline const bool isNegFormula(const size_t& v) const { return (v & 1ul); } - inline const size_t getNegFormula(const size_t& v) const { return (v ^ 1ul); } - - // Gate Formula to Solver Functions - void add_FALSE_Formula(const CirGate*, const uint32_t&); - void add_PI_Formula(const CirGate*, const uint32_t&); - void add_FF_Formula(const CirGate*, const uint32_t&); - void add_AND_Formula(const CirGate*, const uint32_t&); - - void addBoundedVerifyData(const CirGate*, const uint32_t&); - const bool existVerifyData(const CirGate*, const uint32_t&); - void resizeNtkData(const uint32_t& num); - - private: - const Var newVar(); - const Var getVerifyData(const CirGate*, const uint32_t&) const; - void addBoundedVerifyDataRecursively(const CirGate*, const uint32_t&); - - inline const Var getOriVar(const size_t& v) const { return (Var)(v >> 1ul); } - inline const size_t getPosVar(const Var& v) const { return (((size_t)v) << 1ul); } - inline const size_t getNegVar(const Var& v) const { return ((getPosVar(v)) | 1ul); } - - SolverV* _solver; // Pointer to a Minisat solver - Var _curVar; // Variable currently - vec _assump; // Assumption List for assumption solve - GVNtkMgr* _ntk; // Network Under Verification - vector* _ntkData; // Mapping between GVNetId and Solver Data -}; - -#endif // SAT_H diff --git a/src/itp/gvSatCmd.cpp b/src/itp/gvSatCmd.cpp index e0cb8a44..cd16edf1 100644 --- a/src/itp/gvSatCmd.cpp +++ b/src/itp/gvSatCmd.cpp @@ -7,25 +7,26 @@ ****************************************************************************/ #include "gvSatCmd.h" + +#include +#include + +#include "cirGate.h" +#include "cirMgr.h" #include "gvMsg.h" #include "gvSatMgr.h" -#include "cirMgr.h" -#include "cirGate.h" #include "util.h" -#include -#include using namespace std; static SATMgr* satMgr = new SATMgr(); -bool -initItpCmd() { +bool initItpCmd() { return (gvCmdMgr->regCmd("SATVerify ITP", 4, 3, new SATVerifyItpCmd) && gvCmdMgr->regCmd("SATVerify BMC", 4, 3, new SATVerifyBmcCmd)); } //---------------------------------------------------------------------- -// SATVerify ITP < -Netid | -Output > > +// SATVerify ITP < -GateId | -Output > > //---------------------------------------------------------------------- GVCmdExecStatus SATVerifyItpCmd::exec(const string& option) { @@ -37,58 +38,52 @@ SATVerifyItpCmd::exec(const string& option) { bool isNet = false; - if (myStrNCmp("-Netid", options[0], 2) == 0) isNet = true; - else if (myStrNCmp("-Output", options[0], 2) == 0) isNet = false; - else return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); + if (myStrNCmp("-GateId", options[0], 2) == 0) + isNet = true; + else if (myStrNCmp("-Output", options[0], 2) == 0) + isNet = false; + else + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); - int num = 0; - GVNetId netId; + int num = 0; CirGate* gate; + string monitorName = ""; if (!myStr2Int(options[1], num) || (num < 0)) return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); if (isNet) { - if ((unsigned)num >= gvNtkMgr->getNetSize()) { + if ((unsigned)num >= cirMgr->getNumTots()) { gvMsg(GV_MSG_ERR) << "Net with Id " << num << " does NOT Exist in Current Ntk !!" << endl; return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } - netId = GVNetId::makeNetId(num); + gate = cirMgr->getGate(num); } else { if ((unsigned)num >= cirMgr->getNumPOs()) { gvMsg(GV_MSG_ERR) << "Output with Index " << num << " does NOT Exist in Current Ntk !!" << endl; return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } - // netId = gvNtkMgr->getOutput(num); gate = cirMgr->getPo(num); + monitorName = gate->getName(); } // get PO's input, since the PO is actually a redundant node and should be removed - // GVNetId redundantNode = gvNtkMgr->getGVNetId(netId.id); - // GVNetId monitor = gvNtkMgr->getInputNetId(redundantNode, 0); - // satMgr->verifyPropertyItp(gvNtkMgr->getNetNameFromId(redundantNode.id), monitor); - - CirGate* monitor = new CirAigGate(cirMgr->getNumTots(), 0); cirMgr->addTotGate(monitor); + CirGate* monitor = new CirAigGate(cirMgr->getNumTots(), 0); + cirMgr->addTotGate(monitor); monitor->setIn0(gate->getIn0Gate(), gate->getIn0().isInv()); - // monitor->setIn1(cirMgr->_const0, true); monitor->setIn1(cirMgr->_const1, false); - satMgr->verifyPropertyItp(gate->getName(), monitor); - - // Ref - // satMgr->verifyPropertyItp("monitor", gate->getIn0Gate()); + satMgr->verifyPropertyItp(monitorName, monitor); return GV_CMD_EXEC_DONE; } -void -SATVerifyItpCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: SATVerify ITP < -Netid | -Output >" << endl; +void SATVerifyItpCmd::usage(const bool& verbose) const { + gvMsg(GV_MSG_IFO) << "Usage: SATVerify ITP < -GateId | -Output >" << endl; } -void -SATVerifyItpCmd::help() const { +void SATVerifyItpCmd::help() const { cout << setw(20) << left << "SATVerify ITP:" << "check the monitor by interpolation-based technique" << endl; } // //---------------------------------------------------------------------- -// // SATVerify BMC < -Netid | -Output > > +// // SATVerify BMC < -GateId | -Output > > // //---------------------------------------------------------------------- GVCmdExecStatus SATVerifyBmcCmd::exec(const string& option) { @@ -100,44 +95,42 @@ SATVerifyBmcCmd::exec(const string& option) { bool isNet = false; - if (myStrNCmp("-Netid", options[0], 2) == 0) isNet = true; - else if (myStrNCmp("-Output", options[0], 2) == 0) isNet = false; - else return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); + if (myStrNCmp("-GateId", options[0], 2) == 0) + isNet = true; + else if (myStrNCmp("-Output", options[0], 2) == 0) + isNet = false; + else + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); - int num = 0; - GVNetId netId; + int num = 0; CirGate* gate; + string monitorName = ""; if (!myStr2Int(options[1], num) || (num < 0)) return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); if (isNet) { - if ((unsigned)num >= gvNtkMgr->getNetSize()) { - gvMsg(GV_MSG_ERR) << "Net with Id " << num << " does NOT Exist in Current Ntk !!" << endl; + if ((unsigned)num >= cirMgr->getNumTots()) { + gvMsg(GV_MSG_ERR) << "Gate with Id " << num << " does NOT Exist in Current Cir !!" << endl; return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } - netId = GVNetId::makeNetId(num); + gate = cirMgr->getGate(num); } else { - if ((unsigned)num >= gvNtkMgr->getOutputSize()) { - gvMsg(GV_MSG_ERR) << "Output with Index " << num << " does NOT Exist in Current Ntk !!" << endl; + if ((unsigned)num >= cirMgr->getNumPOs()) { + gvMsg(GV_MSG_ERR) << "Output with Index " << num << " does NOT Exist in Current Cir !!" << endl; return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } - netId = gvNtkMgr->getOutput(num); - gate = cirMgr->getPo(num); + monitorName = cirMgr->getPo(num)->getName(); + gate = cirMgr->getPo(num)->getIn0Gate(); } // get PO's input, since the PO is actually a redundant node and should be removed - GVNetId redundantNode = gvNtkMgr->getGVNetId(netId.id); - GVNetId monitor = gvNtkMgr->getInputNetId(redundantNode, 0); - // satMgr->verifyPropertyBmc(gvNtkMgr->getNetNameFromId(redundantNode.id), monitor); - satMgr->verifyPropertyBmc("monitor", gate->getIn0Gate()); + satMgr->verifyPropertyBmc(monitorName, gate); return GV_CMD_EXEC_DONE; } -void -SATVerifyBmcCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: SATVerify BMC < -Netid | -Output < outputIndex >> " << endl; +void SATVerifyBmcCmd::usage(const bool& verbose) const { + gvMsg(GV_MSG_IFO) << "Usage: SATVerify BMC < -GateId | -Output < outputIndex >> " << endl; } -void -SATVerifyBmcCmd::help() const { +void SATVerifyBmcCmd::help() const { cout << setw(20) << left << "SATVerify BMC:" << "check the monitor by bounded model checking" << endl; } diff --git a/src/itp/gvSatMgr.cpp b/src/itp/gvSatMgr.cpp index 1122608b..7644f6cf 100644 --- a/src/itp/gvSatMgr.cpp +++ b/src/itp/gvSatMgr.cpp @@ -7,25 +7,28 @@ ****************************************************************************/ #include "gvSatMgr.h" -#include "gvMsg.h" -#include "reader.h" -#include "cirMgr.h" -#include "cirGate.h" + #include #include #include #include +#include "cirGate.h" +#include "cirMgr.h" +#include "gvMsg.h" +#include "reader.h" + using namespace std; -void -SATMgr::verifyPropertyItp(const string& name, const CirGate* monitor) { +void SATMgr::verifyPropertyItp(const string &name, const CirGate *monitor) { // Initialize // duplicate the network, so you can modified // the ntk for the proving property without // destroying the original network - SatProofRes pRes; - GVSatSolver* gvSatSolver = new GVSatSolver(gvNtkMgr); + _cirMgr = new CirMgr(); + *_cirMgr = *cirMgr; + SatProofRes pRes; + GVSatSolver *gvSatSolver = new GVSatSolver(_cirMgr); // Prove the monitor here!! pRes.setMaxDepth(1000); @@ -33,21 +36,22 @@ SATMgr::verifyPropertyItp(const string& name, const CirGate* monitor) { itpUbmc(monitor, pRes); pRes.reportResult(name); - if (pRes.isFired()) pRes.reportCex(monitor, gvNtkMgr); + if (pRes.isFired()) pRes.reportCex(monitor, _cirMgr); - // delete gvSatSolver; - // delete _ntk; + delete gvSatSolver; + delete _cirMgr; reset(); } -void -SATMgr::verifyPropertyBmc(const string& name, const CirGate* monitor) { +void SATMgr::verifyPropertyBmc(const string &name, const CirGate *monitor) { // Initialize // duplicate the network, so you can modified // the ntk for the proving property without // destroying the original network - SatProofRes pRes; - GVSatSolver* gvSatSolver = new GVSatSolver(gvNtkMgr); + _cirMgr = new CirMgr(); + *_cirMgr = *cirMgr; + SatProofRes pRes; + GVSatSolver *gvSatSolver = new GVSatSolver(_cirMgr); // Prove the monitor here!! pRes.setMaxDepth(1000); @@ -55,21 +59,20 @@ SATMgr::verifyPropertyBmc(const string& name, const CirGate* monitor) { indBmc(monitor, pRes); pRes.reportResult(name); - if (pRes.isFired()) pRes.reportCex(monitor, gvNtkMgr); + if (pRes.isFired()) pRes.reportCex(monitor, _cirMgr); - // delete gvSatSolver; - // delete _ntk; + delete gvSatSolver; + delete _cirMgr; reset(); } -void -SATMgr::indBmc(const CirGate* monitor, SatProofRes& pRes) { - GVSatSolver* gvSatSolver = pRes.getSatSolver(); +void SATMgr::indBmc(const CirGate *monitor, SatProofRes &pRes) { + GVSatSolver *gvSatSolver = pRes.getSatSolver(); bind(gvSatSolver); uint32_t i = 0; // GVNetId I = buildInitState(); - CirGate* I = buildInitState(); + CirGate *I = buildInitState(); gvSatSolver->addBoundedVerifyData(I, i); gvSatSolver->assertProperty(I, false, i); @@ -89,31 +92,29 @@ SATMgr::indBmc(const CirGate* monitor, SatProofRes& pRes) { } } -void -SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { - - GVSatSolver* gvSatSolver = pRes.getSatSolver(); +void SATMgr::itpUbmc(const CirGate *monitor, SatProofRes &pRes) { + GVSatSolver *gvSatSolver = pRes.getSatSolver(); bind(gvSatSolver); size_t num_clauses = getNumClauses(); - bool proved = false; + bool proved = false; gvSatSolver->assumeRelease(); // GVNetId S, R, R_prime, tmp1, tmp2, tmp3, tmp4; - CirGate* S; - CirGate* R; - CirGate* R_prime; - CirGate* tmp1; - CirGate* tmp2; - CirGate* tmp3; - CirGate* tmp4; - CirGate* tmp5; + CirGate *S; + CirGate *R; + CirGate *R_prime; + CirGate *tmp1; + CirGate *tmp2; + CirGate *tmp3; + CirGate *tmp4; + CirGate *tmp5; // TODO : finish your own Interpolation-based property checking // PART I: // Build Initial State // GVNetId I = buildInitState(); - CirGate* I = buildInitState(); + CirGate *I = buildInitState(); // PART II: // Take care the first timeframe (i.e. Timeframe 0 ) // Check if monitor is violated at timeframe 0 @@ -135,15 +136,15 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { num_clauses = getNumClauses(); gvSatSolver->assertProperty(monitor, true, i); - for (size_t j = 0; j < cirMgr->getNumLATCHs(); ++j) { - gvSatSolver->addBoundedVerifyData(cirMgr->getRo(j), i); - mapVar2Net(gvSatSolver->getVerifyData(cirMgr->getRo(j), i), cirMgr->getRo(j)); + for (size_t j = 0; j < _cirMgr->getNumLATCHs(); ++j) { + gvSatSolver->addBoundedVerifyData(_cirMgr->getRo(j), i); + mapVar2Net(gvSatSolver->getVerifyData(_cirMgr->getRo(j), i), _cirMgr->getRo(j)); } - i++; // i = 2 + i++; // i = 2 // map gvSatSolver vars to latch nets - for (size_t j = 0; j < cirMgr->getNumLATCHs(); ++j) { - gvSatSolver->addBoundedVerifyData(cirMgr->getRo(j), i); - mapVar2Net(gvSatSolver->getVerifyData(cirMgr->getRo(j), i), cirMgr->getRo(j)); + for (size_t j = 0; j < _cirMgr->getNumLATCHs(); ++j) { + gvSatSolver->addBoundedVerifyData(_cirMgr->getRo(j), i); + mapVar2Net(gvSatSolver->getVerifyData(_cirMgr->getRo(j), i), _cirMgr->getRo(j)); } num_clauses = getNumClauses(); @@ -153,9 +154,9 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { } num_clauses = getNumClauses(); - for (size_t j = 0; j < cirMgr->getNumLATCHs(); ++j) { - gvSatSolver->addBoundedVerifyData(cirMgr->getRo(j), i); - mapVar2Net(gvSatSolver->getVerifyData(cirMgr->getRo(j), i), cirMgr->getRo(j)); + for (size_t j = 0; j < _cirMgr->getNumLATCHs(); ++j) { + gvSatSolver->addBoundedVerifyData(_cirMgr->getRo(j), i); + mapVar2Net(gvSatSolver->getVerifyData(_cirMgr->getRo(j), i), _cirMgr->getRo(j)); } num_clauses = getNumClauses(); @@ -186,13 +187,12 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { markOffsetClause(j); } num_clauses = getNumClauses(); - + k = 0; R = I; S = getItp(); for (; k < pRes.getMaxDepth(); ++k) { - - // DEBUG + // DEBUG // cout << "[LOG] "<< "i = " << i << " k = " << k << endl; gvSatSolver->assumeRelease(); @@ -208,27 +208,28 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { // Assumption Solver: If SAT, disproved! if (gvSatSolver->assump_solve()) { - gvSatSolver->assertProperty(monitor, true, i); for (size_t j = num_clauses; j < getNumClauses(); ++j) { markOffsetClause(j); } num_clauses = getNumClauses(); break; - } else num_clauses = getNumClauses(); + } else + num_clauses = getNumClauses(); S = getItp(); // see if Si or Ri-1 equals to Ri - unsigned gateSize = cirMgr->getNumTots(); - R_prime = cirMgr->createOrGate(R,S); - tmp5 = cirMgr->createXorGate(R,R_prime); - gvSatSolver->resizeNtkData(cirMgr->getNumTots() - gateSize); + unsigned gateSize = _cirMgr->getNumTots(); + R_prime = _cirMgr->createOrGate(R, S); + tmp5 = _cirMgr->createXorGate(R, R_prime); + gvSatSolver->resizeNtkData(_cirMgr->getNumTots() - gateSize); gvSatSolver->addBoundedVerifyData(tmp5, 0); gvSatSolver->assumeRelease(); - gvSatSolver->assumeProperty(tmp5, false, 0); // assume R xor R_prime is true + gvSatSolver->assumeProperty(tmp5, false, + 0); // assume R xor R_prime is true gvSatSolver->simplify(); - if (!gvSatSolver->assump_solve()) // USAT + if (!gvSatSolver->assump_solve()) // USAT { pRes.setProved(k); proved = true; @@ -238,7 +239,7 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { markOnsetClause(j); } num_clauses = getNumClauses(); - R = R_prime; + R = R_prime; } } if (proved) break; @@ -246,17 +247,17 @@ SATMgr::itpUbmc(const CirGate* monitor, SatProofRes& pRes) { return; } -void -SATMgr::bind(GVSatSolver* ptrMinisat) { +void SATMgr::bind(GVSatSolver *ptrMinisat) { _ptrMinisat = ptrMinisat; if (_ptrMinisat->_solver->proof == NULL) { - gvMsg(GV_MSG_ERR) << "The Solver has no Proof!! Try Declaring the Solver with proofLog be set!!" << endl; + gvMsg(GV_MSG_ERR) << "The Solver has no Proof!! Try Declaring the Solver " + "with proofLog be set!!" + << endl; exit(0); } } -void -SATMgr::reset() { +void SATMgr::reset() { _ptrMinisat = NULL; _varGroup.clear(); _var2Net.clear(); @@ -264,8 +265,7 @@ SATMgr::reset() { _isClaOnDup.clear(); } -void -SATMgr::markOnsetClause(const ClauseId& cid) { +void SATMgr::markOnsetClause(const ClauseId &cid) { unsigned cSize = getNumClauses(); assert(cid < (int)cSize); if (_isClauseOn.size() < cSize) { @@ -274,8 +274,7 @@ SATMgr::markOnsetClause(const ClauseId& cid) { _isClauseOn[cid] = true; } -void -SATMgr::markOffsetClause(const ClauseId& cid) { +void SATMgr::markOffsetClause(const ClauseId &cid) { unsigned cSize = getNumClauses(); assert(cid < (int)cSize); if (_isClauseOn.size() < cSize) { @@ -284,17 +283,13 @@ SATMgr::markOffsetClause(const ClauseId& cid) { _isClauseOn[cid] = false; } -void -SATMgr::mapVar2Net(const Var& var, CirGate* net) { - _var2Net[var] = net; -} +void SATMgr::mapVar2Net(const Var &var, CirGate *net) { _var2Net[var] = net; } -CirGate* -SATMgr::getItp() const { +CirGate *SATMgr::getItp() const { assert(_ptrMinisat); assert(_ptrMinisat->_solver->proof); - string proofName = "socv_proof.itp"; + string proofName = "socv_proof.itp"; // remove proof log if exist ifstream logFile(proofName.c_str()); if (logFile.good()) { @@ -307,16 +302,15 @@ SATMgr::getItp() const { // bulding ITP // GVNetId netId = buildItp(proofName); - CirGate* netId = buildItp(proofName); + CirGate *gateId = buildItp(proofName); // delete proof log unlink(proofName.c_str()); - return netId; + return gateId; } -vector -SATMgr::getUNSATCore() const { +vector SATMgr::getUNSATCore() const { assert(_ptrMinisat); assert(_ptrMinisat->_solver->proof); @@ -338,8 +332,7 @@ SATMgr::getUNSATCore() const { return unsatCore; } -void -SATMgr::retrieveProof(Reader& rdr, vector& unsatCore) const { +void SATMgr::retrieveProof(Reader &rdr, vector &unsatCore) const { unsigned int tmp, cid, idx, tmp_cid; // Clear all @@ -353,25 +346,25 @@ SATMgr::retrieveProof(Reader& rdr, vector& unsatCore) const { for (unsigned int pos = 0; (tmp = rdr.get64()) != RDR_EOF; pos = rdr.Current_Pos()) { cid = clausePos.size(); clausePos.push_back(pos); - if ((tmp & 1) == 0) { // root clause + if ((tmp & 1) == 0) { // root clause while ((tmp = rdr.get64()) != 0) { } - } else { // learnt clause + } else { // learnt clause idx = 0; while ((tmp = rdr.get64()) != 0) { idx = 1; } - if (idx == 0) clausePos.pop_back(); // Clause Deleted + if (idx == 0) clausePos.pop_back(); // Clause Deleted } } // Generate unsatCore priority_queue clause_queue; - vector in_queue; + vector in_queue; in_queue.resize(clausePos.size()); for (unsigned int i = 0; i < in_queue.size(); ++i) in_queue[i] = false; in_queue[in_queue.size() - 1] = true; - clause_queue.push(clausePos.size() - 1); // Push leaf (empty) clause + clause_queue.push(clausePos.size() - 1); // Push leaf (empty) clause while (clause_queue.size() != 0) { cid = clause_queue.top(); clause_queue.pop(); @@ -411,8 +404,7 @@ SATMgr::retrieveProof(Reader& rdr, vector& unsatCore) const { } } -void -SATMgr::retrieveProof(Reader& rdr, vector& clausePos, vector& usedClause) const { +void SATMgr::retrieveProof(Reader &rdr, vector &clausePos, vector &usedClause) const { unsigned int tmp, cid, idx, tmp_cid, root_cid; // Clear all @@ -435,22 +427,30 @@ SATMgr::retrieveProof(Reader& rdr, vector& clausePos, vector> 1; if (_isClauseOn[root_cid]) { - if (_varGroup[idx >> 1] == NONE) _varGroup[idx >> 1] = LOCAL_ON; - else if (_varGroup[idx >> 1] == LOCAL_OFF) _varGroup[idx >> 1] = COMMON; + if (_varGroup[idx >> 1] == NONE) + _varGroup[idx >> 1] = LOCAL_ON; + else if (_varGroup[idx >> 1] == LOCAL_OFF) + _varGroup[idx >> 1] = COMMON; } else { - if (_varGroup[idx >> 1] == NONE) _varGroup[idx >> 1] = LOCAL_OFF; - else if (_varGroup[idx >> 1] == LOCAL_ON) _varGroup[idx >> 1] = COMMON; + if (_varGroup[idx >> 1] == NONE) + _varGroup[idx >> 1] = LOCAL_OFF; + else if (_varGroup[idx >> 1] == LOCAL_ON) + _varGroup[idx >> 1] = COMMON; } while (1) { tmp = rdr.get64(); if (tmp == 0) break; idx += tmp; if (_isClauseOn[root_cid]) { - if (_varGroup[idx >> 1] == NONE) _varGroup[idx >> 1] = LOCAL_ON; - else if (_varGroup[idx >> 1] == LOCAL_OFF) _varGroup[idx >> 1] = COMMON; + if (_varGroup[idx >> 1] == NONE) + _varGroup[idx >> 1] = LOCAL_ON; + else if (_varGroup[idx >> 1] == LOCAL_OFF) + _varGroup[idx >> 1] = COMMON; } else { - if (_varGroup[idx >> 1] == NONE) _varGroup[idx >> 1] = LOCAL_OFF; - else if (_varGroup[idx >> 1] == LOCAL_ON) _varGroup[idx >> 1] = COMMON; + if (_varGroup[idx >> 1] == NONE) + _varGroup[idx >> 1] = LOCAL_OFF; + else if (_varGroup[idx >> 1] == LOCAL_ON) + _varGroup[idx >> 1] = COMMON; } } ++root_cid; @@ -464,19 +464,19 @@ SATMgr::retrieveProof(Reader& rdr, vector& clausePos, vector clause_queue; - vector in_queue; + vector in_queue; in_queue.resize(clausePos.size()); for (unsigned int i = 0; i < in_queue.size(); ++i) in_queue[i] = false; in_queue[in_queue.size() - 1] = true; - clause_queue.push(clausePos.size() - 1); // Push root empty clause + clause_queue.push(clausePos.size() - 1); // Push root empty clause while (clause_queue.size() != 0) { cid = clause_queue.top(); clause_queue.pop(); @@ -484,7 +484,7 @@ SATMgr::retrieveProof(Reader& rdr, vector& clausePos, vector> 1); @@ -509,53 +509,45 @@ SATMgr::retrieveProof(Reader& rdr, vector& clausePos, vectorgetNumTots(), 0); cirMgr->addTotGate(I); - in2 = new CirConstGate(cirMgr->_const0->getGid()); I->setIn0(cirMgr->_const1, false); // I->setIn0(cirMgr->_const0, true); - // iteratively and adn all the PI's negation with otthers - for (size_t i = 0; i < cirMgr->getNumLATCHs(); ++i) { - I->setIn1(cirMgr->getRo(i), true); - if(i + 1 != cirMgr->getNumLATCHs()){ - in1 = new CirAigGate(cirMgr->getNumTots(), 0); - cirMgr->addTotGate(in1); + I = new CirAigGate(_cirMgr->getNumTots(), 0); + _cirMgr->addTotGate(I); + I->setIn0(_cirMgr->_const1, false); + // iteratively and and all the PI's negation with others + for (size_t i = 0; i < _cirMgr->getNumLATCHs(); ++i) { + I->setIn1(_cirMgr->getRo(i), true); + if (i + 1 != _cirMgr->getNumLATCHs()) { + in1 = new CirAigGate(_cirMgr->getNumTots(), 0); + _cirMgr->addTotGate(in1); in1->setIn0(I, false); I = in1; } } - // resize solver data to ntk size - // _ptrMinisat->resizeNtkData(gvNtkMgr->getFFSize()); - _ptrMinisat->resizeNtkData(cirMgr->getNumLATCHs()); - // GateList orderedGates; - // CirGate::setGlobalRef(); - // I->genDfsList(orderedGates); + _ptrMinisat->resizeNtkData(_cirMgr->getNumLATCHs()); return I; } // build the McMillan Interpolant -CirGate* -SATMgr::buildItp(const string& proofName) const { - Reader rdr; +CirGate *SATMgr::buildItp(const string &proofName) const { + Reader rdr; // records - map claItpLookup; - vector clausePos; - vector usedClause; + map claItpLookup; + vector clausePos; + vector usedClause; // ntk - uint32_t netSize = cirMgr->getNumTots(); + uint32_t netSize = _cirMgr->getNumTots(); // temperate variables - CirGate* nId; - CirGate* nId1; - CirGate* nId2; - int i, cid, tmp, idx, tmp_cid; + CirGate *nId; + CirGate *nId1; + CirGate *nId2; + int i, cid, tmp, idx, tmp_cid; // const 1 & const 0 - CirGate* CONST0 = cirMgr->_const0; - CirGate* CONST1 = cirMgr->_const1; + CirGate *CONST0 = _cirMgr->_const0; + CirGate *CONST1 = _cirMgr->_const1; rdr.open(proofName.c_str()); retrieveProof(rdr, clausePos, usedClause); @@ -575,10 +567,10 @@ SATMgr::buildItp(const string& proofName) const { } if (_varGroup[idx >> 1] == COMMON) { assert(_var2Net.find(idx >> 1) != _var2Net.end()); - nId = (_var2Net.find(idx >> 1))->second; + nId = (_var2Net.find(idx >> 1))->second; nId1 = (_var2Net.find(idx >> 1))->second; - if ((idx & 1) == 1) nId1 = cirMgr->createNotGate(nId1); - if ((idx & 1) == 1) nId = cirMgr->createNotGate(nId); + if ((idx & 1) == 1) nId1 = _cirMgr->createNotGate(nId1); + if ((idx & 1) == 1) nId = _cirMgr->createNotGate(nId); while (1) { tmp = rdr.get64(); if (tmp == 0) break; @@ -586,13 +578,8 @@ SATMgr::buildItp(const string& proofName) const { if (_varGroup[idx >> 1] == COMMON) { assert(_var2Net.find(idx >> 1) != _var2Net.end()); nId2 = (_var2Net.find(idx >> 1))->second; - if ((idx & 1) == 1) nId2 = cirMgr->createNotGate(nId2); - // or - // nId = ~gvNtkMgr->createNet(); - // gvNtkMgr->createGVAndGate(nId, ~nId1, ~nId2); - // nId1 = nId; - // --- - nId = cirMgr->createOrGate(nId1, nId2); + if ((idx & 1) == 1) nId2 = _cirMgr->createNotGate(nId2); + nId = _cirMgr->createOrGate(nId1, nId2); nId1 = nId; } } @@ -607,7 +594,7 @@ SATMgr::buildItp(const string& proofName) const { // Derived Clause tmp_cid = cid - (tmp >> 1); assert(claItpLookup.find(tmp_cid) != claItpLookup.end()); - nId = (claItpLookup.find(tmp_cid))->second; + nId = (claItpLookup.find(tmp_cid))->second; nId1 = (claItpLookup.find(tmp_cid))->second; while (1) { idx = rdr.get64(); @@ -618,59 +605,34 @@ SATMgr::buildItp(const string& proofName) const { assert(claItpLookup.find(tmp_cid) != claItpLookup.end()); nId2 = (claItpLookup.find(tmp_cid))->second; if (nId1 != nId2) { - if (_varGroup[idx] == LOCAL_ON) { // Local to A. Build OR Gate. + if (_varGroup[idx] == LOCAL_ON) { // Local to A. Build OR Gate. if (nId1 == CONST1 || nId2 == CONST1) { - nId = CONST1; + nId = CONST1; nId1 = nId; } else if (nId1 == CONST0) { - nId = nId2; + nId = nId2; nId1 = nId; } else if (nId2 == CONST0) { - nId = nId1; + nId = nId1; nId1 = nId; } else { // or - // nId = ~gvNtkMgr->createNet(); - // gvNtkMgr->createGVAndGate(nId, ~nId1, ~nId2); - // nId1 = nId; - // --- - // CirGate* tmpId = new CirAigGate(cirMgr->getNumTots(), 0); - // cirMgr->addTotGate(tmpId); - // tmpId->setIn0(nId1,true); - // tmpId->setIn1(nId2, true); - // nId = new CirAigGate(cirMgr->getNumTots(), 0); - // cirMgr->addTotGate(nId); - // nId->setIn0(tmpId,true); - // // nId->setIn1(cirMgr->_const0, true); - // nId->setIn1(CONST1, false); - // nId1 = nId; - // --- - nId = cirMgr->createOrGate(nId1, nId2); + nId = _cirMgr->createOrGate(nId1, nId2); nId1 = nId; } - } else { // Build AND Gate. + } else { // Build AND Gate. if (nId1 == CONST0 || nId2 == CONST0) { - nId = CONST0; + nId = CONST0; nId1 = nId; } else if (nId1 == CONST1) { - nId = nId2; + nId = nId2; nId1 = nId; } else if (nId2 == CONST1) { - nId = nId1; + nId = nId1; nId1 = nId; } else { // and - // nId = gvNtkMgr->createNet(); - // gvNtkMgr->createGVAndGate(nId, nId1, nId2); - // nId1 = nId; - // --- - // nId = new CirAigGate(cirMgr->getNumTots(), 0); - // cirMgr->addTotGate(nId); - // nId->setIn0(nId1, false); - // nId->setIn1(nId2, false); - // nId1 = nId; - // --- - nId = cirMgr->createAndGate(nId1, nId2); + nId = _cirMgr->createAndGate(nId1, nId2); nId1 = nId; } } @@ -683,14 +645,12 @@ SATMgr::buildItp(const string& proofName) const { cid = usedClause[usedClause.size() - 1]; nId = claItpLookup[cid]; - // _ptrMinisat->resizeNtkData(gvNtkMgr->getNetSize() - netSize); // resize Solver data to ntk size - _ptrMinisat->resizeNtkData(cirMgr->getNumTots() - netSize); // resize Solver data to ntk size + _ptrMinisat->resizeNtkData(_cirMgr->getNumTots() - netSize); // resize Solver data to ntk size return nId; } -void -SatProofRes::reportResult(const string& name) const { +void SatProofRes::reportResult(const string &name) const { // Report Verification Result gvMsg(GV_MSG_IFO) << endl; if (isProved()) { @@ -702,17 +662,16 @@ SatProofRes::reportResult(const string& name) const { } } -void -SatProofRes::reportCex(const CirGate* monitor, const GVNtkMgr* const ntk) const { +void SatProofRes::reportCex(const CirGate *monitor, const CirMgr *const _cirMgr) const { assert(_satSolver != 0); // Output Pattern Value (PI + PIO) GVBitVecX dataValue; for (uint32_t i = 0; i <= _fired; ++i) { gvMsg(GV_MSG_IFO) << i << ": "; - for (int j = cirMgr->getNumPIs() - 1; j >= 0; --j) { - if (_satSolver->existVerifyData(cirMgr->getPi(j), i)) { - dataValue = _satSolver->getDataValue(cirMgr->getPi(j), i); + for (int j = _cirMgr->getNumPIs() - 1; j >= 0; --j) { + if (_satSolver->existVerifyData(_cirMgr->getPi(j), i)) { + dataValue = _satSolver->getDataValue(_cirMgr->getPi(j), i); gvMsg(GV_MSG_IFO) << dataValue[0]; } else { gvMsg(GV_MSG_IFO) << 'x'; diff --git a/src/itp/gvSatMgr.h b/src/itp/gvSatMgr.h index 882f162e..6231c7b3 100644 --- a/src/itp/gvSatMgr.h +++ b/src/itp/gvSatMgr.h @@ -9,110 +9,108 @@ #ifndef SAT_MGR_H_ #define SAT_MGR_H_ -#include "gvNtk.h" -#include "gvSat.h" +#include + #include #include -#include #include + +#include "gvNtk.h" +#include "gvSat.h" // #include "SolverTypesV.h" -#include "reader.h" -#include "cirMgr.h" #include "cirGate.h" +#include "cirMgr.h" +#include "reader.h" class GVNetId; typedef int ClauseId; -enum VAR_GROUP -{ +enum VAR_GROUP { LOCAL_ON, LOCAL_OFF, COMMON, NONE }; -class SatProofRes -{ - public: - SatProofRes(GVSatSolver* s = 0) : _proved(GVNtkUD), _fired(GVNtkUD), _maxDepth(GVNtkUD), _satSolver(s) {} +class SatProofRes { +public: + SatProofRes(GVSatSolver* s = 0) : _proved(GVNtkUD), _fired(GVNtkUD), _maxDepth(GVNtkUD), _satSolver(s) {} - void setProved(uint32_t i) { _proved = i; } - void setFired(uint32_t i) { _fired = i; } + void setProved(uint32_t i) { _proved = i; } + void setFired(uint32_t i) { _fired = i; } - bool isProved() const { return (_proved != GVNtkUD); } - bool isFired() const { return (_fired != GVNtkUD); } + bool isProved() const { return (_proved != GVNtkUD); } + bool isFired() const { return (_fired != GVNtkUD); } - void setMaxDepth(uint32_t d) { _maxDepth = d; } - uint32_t getMaxDepth() const { return _maxDepth; } + void setMaxDepth(uint32_t d) { _maxDepth = d; } + uint32_t getMaxDepth() const { return _maxDepth; } - void setSatSolver(GVSatSolver* s) { _satSolver = s; } - GVSatSolver* getSatSolver() const { return _satSolver; } + void setSatSolver(GVSatSolver* s) { _satSolver = s; } + GVSatSolver* getSatSolver() const { return _satSolver; } - void reportResult(const string&) const; - void reportCex(const CirGate*, const GVNtkMgr* const) const; + void reportResult(const string&) const; + void reportCex(const CirGate*, const CirMgr* const) const; - private: - uint32_t _proved; - uint32_t _fired; - uint32_t _maxDepth; // maximum proof depth - GVSatSolver* _satSolver; +private: + uint32_t _proved; + uint32_t _fired; + uint32_t _maxDepth; // maximum proof depth + GVSatSolver* _satSolver; }; -class SATMgr -{ - public: - SATMgr() : _ptrMinisat(NULL), _ntk(NULL) { reset(); } - ~SATMgr() { reset(); } - - // entry point for SoCV SAT property checking - void verifyPropertyItp(const string& name, const CirGate* monitor); - void verifyPropertyBmc(const string& name, const CirGate* monitor); - // Various proof engines - void indBmc(const CirGate*, SatProofRes&); - void itpUbmc(const CirGate*, SatProofRes&); - - // bind with a solver to get proof info. - void bind(GVSatSolver* ptrMinisat); - // clear data members - void reset(); - // mark onset/offset clause - void markOnsetClause(const ClauseId& cid); - void markOffsetClause(const ClauseId& cid); - // map var to V3Net (PPI) - void mapVar2Net(const Var& var, CirGate* net); - // please be sure that you call these function right after a UNSAT solving - // GVNetId getItp() const; - CirGate* getItp() const; - vector getUNSATCore() const; - // get number of clauses (the latest clause id + 1) - int getNumClauses() const { return _ptrMinisat->getNumClauses(); } - - // self define helper function - void markSet(bool onORoff, ClauseId& currClause); - bool startSatSolver(GVSatSolver* GVSatSolver); - void buildMiter(GVSatSolver* GVSatSolver, GVNetId& R_, GVNetId& R, int& orgNtkSize); - - private: - // helper functions to get proof info. - // GVNetId buildInitState() const; - CirGate* buildInitState() const; - // GVNetId buildItp(const string& proofName) const; - CirGate* buildItp(const string& proofName) const; - void retrieveProof(Reader& rdr, vector& clausePos, vector& usedClause) const; - void retrieveProof(Reader& rdr, vector& unsatCore) const; - - // V3 minisat interface for model checking - GVSatSolver* _ptrMinisat; - // The duplicated V3Ntk - GVNtkMgr* _ntk; - CirMgr* _cirNtk; - - // to handle interpolation - map _var2Net; // mapping common variables to net - vector _isClauseOn; // record onset clauses - // will be determined in retrieveProof, you don't need to take care about this! - mutable vector _isClaOnDup; // duplication & extension of _isClauseOn - mutable vector _varGroup; // mapping var to different groups +class SATMgr { +public: + SATMgr() : _ptrMinisat(NULL), _cirMgr(NULL) { reset(); } + ~SATMgr() { reset(); } + + // entry point for SoCV SAT property checking + void verifyPropertyItp(const string& name, const CirGate* monitor); + void verifyPropertyBmc(const string& name, const CirGate* monitor); + // Various proof engines + void indBmc(const CirGate*, SatProofRes&); + void itpUbmc(const CirGate*, SatProofRes&); + + // bind with a solver to get proof info. + void bind(GVSatSolver* ptrMinisat); + // clear data members + void reset(); + // mark onset/offset clause + void markOnsetClause(const ClauseId& cid); + void markOffsetClause(const ClauseId& cid); + // map var to V3Net (PPI) + void mapVar2Net(const Var& var, CirGate* net); + // please be sure that you call these function right after a UNSAT solving + // GVNetId getItp() const; + CirGate* getItp() const; + vector getUNSATCore() const; + // get number of clauses (the latest clause id + 1) + int getNumClauses() const { return _ptrMinisat->getNumClauses(); } + + // self define helper function + void markSet(bool onORoff, ClauseId& currClause); + bool startSatSolver(GVSatSolver* GVSatSolver); + void buildMiter(GVSatSolver* GVSatSolver, GVNetId& R_, GVNetId& R, int& orgNtkSize); + +private: + // helper functions to get proof info. + // GVNetId buildInitState() const; + CirGate* buildInitState() const; + // GVNetId buildItp(const string& proofName) const; + CirGate* buildItp(const string& proofName) const; + void retrieveProof(Reader& rdr, vector& clausePos, vector& usedClause) const; + void retrieveProof(Reader& rdr, vector& unsatCore) const; + + // GV minisat interface for model checking + GVSatSolver* _ptrMinisat; + // The duplicated Cir + CirMgr* _cirMgr; + + // to handle interpolation + map _var2Net; // mapping common variables to net + vector _isClauseOn; // record onset clauses + // will be determined in retrieveProof, you don't need to take care about this! + mutable vector _isClaOnDup; // duplication & extension of _isClauseOn + mutable vector _varGroup; // mapping var to different groups }; #endif /* SAT_MGR_H_ */ diff --git a/src/main/.depend.mak b/src/main/.depend.mak index e69de29b..b96a8e22 100644 --- a/src/main/.depend.mak +++ b/src/main/.depend.mak @@ -0,0 +1,8 @@ +main.o: main.cpp ../../include/gvCmdMgr.h ../../include/gvMsg.h \ + ../../include/gvUsage.h ../../include/gvMsg.h ../../include/gvIntType.h \ + ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ + /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ + ../../include/kernel/hashlib.h ../../include/kernel/log.h \ + ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ + ../../include/kernel/register.h ../../include/util.h \ + ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/main/main.cpp b/src/main/main.cpp index 01897493..27f18b36 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -42,7 +42,7 @@ extern bool initYosysCmd(); static void usage() { - cout << "Usage: cirTest [ -File < doFile > ]" << endl; + cout << "Usage: ./gv [ -File < doFile > ]" << endl; } static void @@ -70,8 +70,8 @@ int main(int argc, char** argv) { cout << "Error: illegal number of argument (" << argc << ")!!\n"; myexit(); } - // Yosys::yosys_setup(); // initial yosys command - // Yosys::log_streams.push_back(&std::cout); // log yosys message + + cout << "GV v0.3.0 - Copyright © 2022-2023, DVLab NTUEE.\n"; if (!(initCommonCmd() && initNtkCmd() && initSimCmd() && initVrfCmd() && initAbcCmd() && initModCmd() && initBddCmd() && initProveCmd() && initItpCmd() && initCirCmd() && initYosysCmd())) return 1; diff --git a/src/mod/.depend.mak b/src/mod/.depend.mak index e69de29b..787aa841 100644 --- a/src/mod/.depend.mak +++ b/src/mod/.depend.mak @@ -0,0 +1,32 @@ +gvModCmd.o: gvModCmd.cpp gvModCmd.h ../../include/gvCmdMgr.h gvModMgr.h \ + ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ + ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/base/main/main.h ../../include/base/abc/abc.h \ + ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ + ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ + ../../include/base/main/mainInt.h ../../include/base/main/main.h \ + ../../include/misc/tim/tim.h ../../include/map/if/if.h \ + ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ + ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ + ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ + ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ + ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ + ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ + ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ + ../../include/gvMsg.h ../../include/kernel/yosys.h \ + /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ + /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ + ../../include/kernel/log.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h \ + ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h +gvModMgr.o: gvModMgr.cpp gvModMgr.h ../../include/gvCmdMgr.h diff --git a/src/mod/gvModMgr.cpp b/src/mod/gvModMgr.cpp index 582d8b3e..13b954cd 100644 --- a/src/mod/gvModMgr.cpp +++ b/src/mod/gvModMgr.cpp @@ -1,23 +1,25 @@ #include "gvModMgr.h" -#include "gvCmdMgr.h" + #include #include #include #include +#include "gvCmdMgr.h" + GVModMgr* gvModMgr; /* -------------------------------------------------- *\ * Class GVModMgr Implementations \* -------------------------------------------------- */ GVModMgr::GVModMgr() { + _property = -1; + _propertySet = false; _inputFileExist = false; - _property = -1; - _propertySet = false; - _inputFileName = ""; - _aig_name = ""; - _gvMode = GVModType::GV_MOD_TYPE_SETUP; // default mode : Setup - _gvEng = GVModEngine::GV_MOD_ENGINE_YOSYS; // default engine : yosys + _inputFileName = ""; + _aig_name = ""; + _gvMode = GVModType::GV_MOD_TYPE_SETUP; // default mode : Setup + _gvEng = GVModEngine::GV_MOD_ENGINE_YOSYS; // default engine : yosys setModPromt(); } @@ -26,8 +28,7 @@ GVModMgr::~GVModMgr() {} /* ------------------------- *\ * GET functions \* ------------------------- */ -bool -GVModMgr::getInputFileExist() { +bool GVModMgr::getInputFileExist() { return _inputFileExist; } @@ -58,17 +59,15 @@ GVModMgr::getGVEngine() { string GVModMgr::getModPrompt() { - setModPromt(); // update mode prompt + setModPromt(); // update mode prompt return _modPrompt; } -int -GVModMgr::getSafe() { +int GVModMgr::getSafe() { return _property; } -void -GVModMgr::printWizardPrompt(int promptStart, int promptLength) { +void GVModMgr::printWizardPrompt(int promptStart, int promptLength) { if (promptStart < 0) { if (promptStart == -1) { cout << "[CORRECT COMMAND] !! "; @@ -85,11 +84,10 @@ GVModMgr::printWizardPrompt(int promptStart, int promptLength) { while (idx++ < promptLength) cout << _wizardContent[promptStart++] << "\n"; } -void -GVModMgr::printWizardProgress(int pos, int promptNum) { +void GVModMgr::printWizardProgress(int pos, int promptNum) { float float_percent = (static_cast(pos) / (promptNum - 1)) * 100; - int int_percent = float_percent; - int idx = 0; + int int_percent = float_percent; + int idx = 0; cout << "progress : ["; while (idx++ < pos) cout << "="; cout << ">"; @@ -103,63 +101,54 @@ GVModMgr::printWizardProgress(int pos, int promptNum) { /* ------------------------- *\ * SET functions \* ------------------------- */ -void -GVModMgr::setInputFileExist(bool exist) { +void GVModMgr::setInputFileExist(bool exist) { _inputFileExist = exist; } -void -GVModMgr::setInputFileName(string& filename) { +void GVModMgr::setInputFileName(string& filename) { _inputFileName = filename; } -void -GVModMgr::setAigFileName(string aigFileName) { +void GVModMgr::setAigFileName(string aigFileName) { _aig_name = aigFileName; } -void -GVModMgr::setTopModuleName(string topModuleName) { +void GVModMgr::setTopModuleName(string topModuleName) { _top_module_name = topModuleName; } -void -GVModMgr::setGVMode(GVModType mode) { +void GVModMgr::setGVMode(GVModType mode) { _gvMode = mode; setModPromt(); } -void -GVModMgr::setGVEngine(GVModEngine engine) { +void GVModMgr::setGVEngine(GVModEngine engine) { _gvEng = engine; setModPromt(); } -void -GVModMgr::setModPromt() { +void GVModMgr::setModPromt() { if (_gvMode == GVModType::GV_MOD_TYPE_SETUP) _modPrompt = GVEngineString[_gvEng] + GVModTypeString[_gvMode]; - else _modPrompt = GVModTypeString[_gvMode]; + else + _modPrompt = GVModTypeString[_gvMode]; gvCmdMgr->updateModPrompt(_modPrompt); } -void -GVModMgr::setSafe(int p) { - _property = p; +void GVModMgr::setSafe(int p) { + _property = p; _propertySet = true; } -void -GVModMgr::setWizardContent(string prompt) { +void GVModMgr::setWizardContent(string prompt) { _wizardContent.push_back(prompt); } /* ------------------------- *\ * RESET functions \* ------------------------- */ -void -GVModMgr::reset() { +void GVModMgr::reset() { _inputFileExist = false; - _property = -1; - _propertySet = false; - _inputFileName = ""; - _aig_name = ""; + _property = -1; + _propertySet = false; + _inputFileName = ""; + _aig_name = ""; setModPromt(); } diff --git a/src/ntk/.depend.mak b/src/ntk/.depend.mak index e69de29b..71777112 100644 --- a/src/ntk/.depend.mak +++ b/src/ntk/.depend.mak @@ -0,0 +1,105 @@ +gvNtkBdd.o: gvNtkBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ + ../../include/bddNodeV.h ../../include/bddNodeV.h ../../include/gvMsg.h \ + gvNtk.h ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ + ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/base/main/main.h ../../include/base/abc/abc.h \ + ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ + ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ + ../../include/base/main/mainInt.h ../../include/base/main/main.h \ + ../../include/misc/tim/tim.h ../../include/map/if/if.h \ + ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ + ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ + ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ + ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ + ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ + ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ + ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ + ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ + /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ + /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ + ../../include/kernel/log.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h \ + ../../include/kernel/utils.h ../../include/util.h ../../include/rnGen.h \ + ../../include/myUsage.h +gvNtkCmd.o: gvNtkCmd.cpp gvNtkCmd.h ../../include/gvCmdMgr.h \ + ../../include/gvMsg.h ../../include/util.h ../../include/rnGen.h \ + ../../include/myUsage.h ../../include/gvAbcMgr.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/base/main/main.h ../../include/base/abc/abc.h \ + ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ + ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ + ../../include/base/main/mainInt.h ../../include/base/main/main.h \ + ../../include/misc/tim/tim.h ../../include/map/if/if.h \ + ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ + ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ + ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ + ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ + ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ + ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ + ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ + ../../include/gvModMgr.h ../../include/gvCmdMgr.h gvNtk.h \ + ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ + /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ + /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ + ../../include/kernel/log.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h \ + ../../include/kernel/utils.h +gvNtk.o: gvNtk.cpp gvNtk.h ../../include/gvAbcMgr.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/base/main/main.h ../../include/base/abc/abc.h \ + ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ + ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ + ../../include/base/main/mainInt.h ../../include/base/main/main.h \ + ../../include/misc/tim/tim.h ../../include/map/if/if.h \ + ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ + ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ + ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ + ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ + ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ + ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ + ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ + ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ + /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ + /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ + ../../include/kernel/log.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h \ + ../../include/kernel/utils.h ../../include/cirMgr.h \ + ../../include/cirDef.h ../../include/myHash.h ../../include/cirGate.h \ + ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirMgr.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h gvNtk.h ../../include/gvMsg.h \ + ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/prove/.depend.mak b/src/prove/.depend.mak index e69de29b..d0c660b0 100644 --- a/src/prove/.depend.mak +++ b/src/prove/.depend.mak @@ -0,0 +1,79 @@ +proveBdd.o: proveBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ + ../../include/bddNodeV.h ../../include/gvMsg.h ../../include/gvNtk.h \ + ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ + ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/base/main/main.h ../../include/base/abc/abc.h \ + ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ + ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ + ../../include/base/main/mainInt.h ../../include/base/main/main.h \ + ../../include/misc/tim/tim.h ../../include/map/if/if.h \ + ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ + ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ + ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ + ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ + ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ + ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ + ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ + ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ + /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ + /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ + ../../include/kernel/log.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h \ + ../../include/kernel/utils.h ../../include/kernel/yosys.h \ + ../../include/cirMgr.h ../../include/cirDef.h ../../include/cirGate.h \ + ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirMgr.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h ../../include/gvNtk.h ../../include/util.h \ + ../../include/rnGen.h ../../include/myUsage.h +proveCmd.o: proveCmd.cpp proveCmd.h ../../include/gvCmdMgr.h \ + ../../include/bddMgrV.h ../../include/myHash.h ../../include/bddNodeV.h \ + ../../include/gvMsg.h ../../include/gvNtk.h ../../include/gvAbcMgr.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/base/main/main.h ../../include/base/abc/abc.h \ + ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ + ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ + ../../include/base/main/mainInt.h ../../include/base/main/main.h \ + ../../include/misc/tim/tim.h ../../include/map/if/if.h \ + ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ + ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ + ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ + ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ + ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ + ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ + ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ + ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ + /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ + /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ + ../../include/kernel/log.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h \ + ../../include/kernel/utils.h ../../include/kernel/yosys.h \ + ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h \ + ../../include/cirMgr.h ../../include/cirDef.h ../../include/cirGate.h \ + ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirMgr.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h ../../include/gvNtk.h diff --git a/src/sat/File.cpp b/src/sat/File.cpp deleted file mode 100644 index eb113245..00000000 --- a/src/sat/File.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include "File.h" - -void File::open(int file_descr, FileMode m, bool own) -{ - if (fd != -1) ::close(fd); - fd = file_descr; - mode = m; - own_fd = own; - pos = 0; - buf = xmalloc(File_BufSize); - if (mode == READ) size = read(fd, buf, File_BufSize); - else size = -1; -} - -void File::open(cchar* name, cchar* mode_) -{ - if (fd != -1) ::close(fd); - bool has_r = strchr(mode_, 'r') != NULL; - bool has_w = strchr(mode_, 'w') != NULL; - bool has_a = strchr(mode_, 'a') != NULL; - bool has_p = strchr(mode_, '+') != NULL; - bool has_x = strchr(mode_, 'x') != NULL; - assert(!(has_r && has_w)); - assert(has_r || has_w || has_a); - - int mask = 0; - if (has_p) mask |= O_RDWR; - else if (has_r) mask |= O_RDONLY; - else mask |= O_WRONLY; - - if (!has_r) mask |= O_CREAT; - if (has_w) mask |= O_TRUNC; - if (has_x) mask |= O_EXCL; - - fd = open64(name, mask, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); - - if (fd != -1){ - mode = has_r ? READ : WRITE; - own_fd = true; - pos = 0; - if (has_a) lseek64(fd, 0, SEEK_END); - buf = xmalloc(File_BufSize); - if (mode == READ) size = read(fd, buf, File_BufSize); - else size = -1; - } -} - - -void File::close(void) -{ - if (fd == -1) return; - if (mode == WRITE) - flush(); - xfree(buf); buf = NULL; - if (own_fd) - ::close(fd); - fd = -1; -} - -void File::seek(int64 file_pos, int whence) -{ - if (mode == WRITE){ - flush(); - pos = 0; - lseek64(fd, file_pos, whence); - }else{ - if (whence == SEEK_CUR) lseek64(fd, file_pos - (size - pos), SEEK_CUR); - else lseek64(fd, file_pos, whence); - size = read(fd, buf, File_BufSize); - pos = 0; - } -} - -int64 File::tell(void) -{ - if (mode == WRITE) - return lseek64(fd, 0, SEEK_CUR); - else - return lseek64(fd, 0, SEEK_CUR) - (size - pos); -} - - -//================================================================================================= -// Marshaling: - - -void putUInt(File& out, uint64 val) -{ - if (val < 0x20000000){ - uint v = (uint)val; - if (v < 0x80) - out.putChar(v); - else{ - if (v < 0x2000) - out.putChar(0x80 | (v >> 8)), - out.putChar((uchar)v); - else if (v < 0x200000) - out.putChar(0xA0 | (v >> 16)), - out.putChar((uchar)(v >> 8)), - out.putChar((uchar)v); - else - out.putChar((v >> 24) | 0xC0), - out.putChar((uchar)(v >> 16)), - out.putChar((uchar)(v >> 8)), - out.putChar((uchar)v); - } - }else - out.putChar(0xE0), - out.putChar((uchar)(val >> 56)), - out.putChar((uchar)(val >> 48)), - out.putChar((uchar)(val >> 40)), - out.putChar((uchar)(val >> 32)), - out.putChar((uchar)(val >> 24)), - out.putChar((uchar)(val >> 16)), - out.putChar((uchar)(val >> 8)), - out.putChar((uchar)val); -} - - -uint64 getUInt(File& in) -// throw(Exception_EOF) -//warning: dynamic exception specifications are deprecated in C++11 [-Wdeprecated] -{ - uint byte0, byte1, byte2, byte3, byte4, byte5, byte6, byte7; - byte0 = in.getChar(); - if (byte0 == (uint)EOF) - throw Exception_EOF(); - if (!(byte0 & 0x80)) - return byte0; - else{ - switch ((byte0 & 0x60) >> 5){ - case 0: - byte1 = in.getChar(); - return ((byte0 & 0x1F) << 8) | byte1; - case 1: - byte1 = in.getChar(); - byte2 = in.getChar(); - return ((byte0 & 0x1F) << 16) | (byte1 << 8) | byte2; - case 2: - byte1 = in.getChar(); - byte2 = in.getChar(); - byte3 = in.getChar(); - return ((byte0 & 0x1F) << 24) | (byte1 << 16) | (byte2 << 8) | byte3; - default: - byte0 = in.getChar(); - byte1 = in.getChar(); - byte2 = in.getChar(); - byte3 = in.getChar(); - byte4 = in.getChar(); - byte5 = in.getChar(); - byte6 = in.getChar(); - byte7 = in.getChar(); - return ((uint64)((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3) << 32) - | (uint64)((byte4 << 24) | (byte5 << 16) | (byte6 << 8) | byte7); - } - } -} diff --git a/src/sat/File.h b/src/sat/File.h deleted file mode 100644 index 931a9542..00000000 --- a/src/sat/File.h +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef File_h -#define File_h - -#ifndef Global_h -#include "Global.h" -#endif - -#include -#include -#include - -#ifndef _LARGEFILE64_SOURCE -#define lseek64 ::lseek -#define open64 ::open -#endif - - -//================================================================================================= -// A buffered file abstraction with only 'putChar()' and 'getChar()'. - - -#define File_BufSize 1024 // A small buffer seem to work just as fine as a big one (at least under Linux) - -enum FileMode { READ, WRITE }; - -class Exception_EOF {}; - - -// WARNING! This code is not thoroughly tested. May contain bugs! - -class File { - int fd; // Underlying file descriptor. - FileMode mode; // Reading or writing. - uchar* buf; // Read or write buffer. - int size; // Size of buffer (at end of file, less than 'File_BufSize'). - int pos; // Current position in buffer - bool own_fd; // Do we own the file descriptor? If so, will close file in destructor. - -public: - #define DEFAULTS fd(-1), mode(READ), buf(NULL), size(-1), pos(0), own_fd(true) - File(void) : DEFAULTS {} - - File(int fd, FileMode mode, bool own_fd = true) : DEFAULTS { - open(fd, mode, own_fd); } - - File(cchar* name, cchar* mode) : DEFAULTS { - open(name, mode); } - #undef DEFAULTS - - ~File(void) { - close(); } - - void open(int fd, FileMode mode, bool own_fd = true); // Low-level open. If 'own_fd' is FALSE, descriptor will not be closed by destructor. - void open(cchar* name, cchar* mode); // FILE* compatible interface. - void close(void); - - bool null(void) { // TRUE if no file is opened. - return fd == -1; } - - int releaseDescriptor(void) { // Don't run UNIX function 'close()' on descriptor in 'File's 'close()'. - if (mode == READ) - lseek64(fd, pos - size, SEEK_CUR); - own_fd = false; - return fd; } - - FileMode getMode(void) { - return mode; } - - void setMode(FileMode m) { - if (m == mode) return; - if (m == READ){ - flush(); - size = read(fd, buf, File_BufSize); - }else{ - lseek64(fd, pos - size, SEEK_CUR); - size = -1; } - mode = m; - pos = 0; } - - int getCharQ(void) { // Quick version with minimal overhead -- don't call this in the wrong mode! - #ifdef PARANOID - assert(mode == READ); - #endif - if (pos < size) return (uchar)buf[pos++]; - if (size < File_BufSize) return EOF; - size = read(fd, buf, File_BufSize); - pos = 0; - if (size == 0) return EOF; - return (uchar)buf[pos++]; } - - int putCharQ(int chr) { // Quick version with minimal overhead -- don't call this in the wrong mode! - #ifdef PARANOID - assert(mode == WRITE); - #endif - if (pos == File_BufSize) - write(fd, buf, File_BufSize), - pos = 0; - return buf[pos++] = (uchar)chr; } - - int getChar(void) { - if (mode == WRITE) setMode(READ); - return getCharQ(); } - - int putChar(int chr) { - if (mode == READ) setMode(WRITE); - return putCharQ(chr); } - - bool eof(void) { - assert(mode == READ); - if (pos < size) return false; - if (size < File_BufSize) return true; - size = read(fd, buf, File_BufSize); - pos = 0; - if (size == 0) return true; - return false; } - - void flush(void) { - assert(mode == WRITE); - write(fd, buf, pos); - pos = 0; } - - void seek(int64 pos, int whence = SEEK_SET); - int64 tell(void); -}; - - -//================================================================================================= -// Some nice helper functions: - - -void putUInt (File& out, uint64 val); -//uint64 getUInt (File& in) throw(Exception_EOF); -//warning: dynamic exception specifications are deprecated in C++11 [-Wdeprecated] -uint64 getUInt (File& in); -static inline uint64 encode64(int64 val) { return (val >= 0) ? (uint64)val << 1 : (((uint64)(~val) << 1) | 1); } -static inline int64 decode64(uint64 val) { return ((val & 1) == 0) ? (int64)(val >> 1) : ~(int64)(val >> 1); } -static inline void putInt (File& out, int64 val) { putUInt(out, encode64(val)); } -static inline uint64 getInt (File& in) { return decode64(getUInt(in)); } - - -//================================================================================================= -#endif diff --git a/src/sat/Global.h b/src/sat/Global.h deleted file mode 100644 index 14dbfe85..00000000 --- a/src/sat/Global.h +++ /dev/null @@ -1,278 +0,0 @@ -/****************************************************************************************[Global.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Global_h -#define Global_h - -#include -#include -#include -#include -#include -#include -#include - - -//================================================================================================= -// Basic Types & Minor Things: - - -#ifdef _MSC_VER -typedef INT64 int64; -typedef UINT64 uint64; -typedef INT_PTR intp; -typedef UINT_PTR uintp; -#define I64_fmt "I64d" -#else -typedef long long int64; -typedef unsigned long long uint64; -typedef __PTRDIFF_TYPE__ intp; -typedef unsigned __PTRDIFF_TYPE__ uintp; -#define I64_fmt "lld" -#endif -typedef unsigned char uchar; -typedef const char cchar; - -// FIXED BY RIC -#ifndef uint -typedef unsigned int uint; -#endif - -template static inline T min(T x, T y) { return (x < y) ? x : y; } -template static inline T max(T x, T y) { return (x > y) ? x : y; } - -template struct STATIC_ASSERTION_FAILURE {}; -//template <> struct STATIC_ASSERTION_FAILURE{}; -#define TEMPLATE_FAIL STATIC_ASSERTION_FAILURE() - - -//================================================================================================= -// 'malloc()'-style memory allocation -- never returns NULL; aborts instead: - - -template static inline T* xmalloc(size_t size) { - T* tmp = (T*)malloc(size * sizeof(T)); - assert(size == 0 || tmp != NULL); - return tmp; } - -template static inline T* xrealloc(T* ptr, size_t size) { - T* tmp = (T*)realloc((void*)ptr, size * sizeof(T)); - assert(size == 0 || tmp != NULL); - return tmp; } - -template static inline void xfree(T *ptr) { - if (ptr != NULL) free((void*)ptr); } - - -//================================================================================================= -// Random numbers: - - -// Returns a random float 0 <= x < 1. Seed must never be 0. -static inline double drand(double& seed) { - seed *= 1389796; - int 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); } - - -//================================================================================================= -// Time and Memory: - - -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#ifdef _MSC_VER - -#include - -static inline double cpuTime(void) { - return (double)clock() / CLOCKS_PER_SEC; } - -static inline int64 memUsed() { - return 0; } - -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#else - -#include -#include -#include - -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; } - -static inline int memReadStat(int field) -{ - char name[256]; - pid_t pid = getpid(); - sprintf(name, "/proc/%d/statm", pid); - FILE* in = fopen(name, "rb"); - if (in == NULL) return 0; - int value; - for (; field >= 0; field--) - fscanf(in, "%d", &value); - fclose(in); - return value; -} - -static inline int64 memUsed() { return (int64)memReadStat(0) * (int64)getpagesize(); } - -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#endif - - - -//================================================================================================= -// 'vec' -- automatically resizable arrays (via 'push()' method): - - -// NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc) - -template -class vec { - T* data; - int sz; - int cap; - - void init(int size, const T& pad); - void grow(int min_cap); - -public: - // Types: - typedef int Key; - typedef T Datum; - - // Constructors: - vec(void) : data(NULL) , sz(0) , cap(0) { } - vec(int size) : data(NULL) , sz(0) , cap(0) { growTo(size); } - vec(int size, const T& pad) : data(NULL) , sz(0) , cap(0) { growTo(size, pad); } - vec(T* array, int size) : data(array), sz(size), cap(size) { } // (takes ownership of array -- will be deallocated with 'xfree()') - ~vec(void) { clear(true); } - - // Ownership of underlying array: - T* release (void) { T* ret = data; data = NULL; sz = 0; cap = 0; return ret; } - operator T* (void) { return data; } // (unsafe but convenient) - operator const T* (void) const { return data; } - - // Size operations: - int size (void) const { return sz; } - void shrink (int nelems) { assert(nelems <= sz); for (int i = 0; i < nelems; i++) sz--, data[sz].~T(); } - void pop (void) { sz--, data[sz].~T(); } - void growTo (int size); - void growTo (int size, const T& pad); - void clear (bool dealloc = false); - void capacity (int size) { grow(size); } - - // Stack interface: - void push (void) { if (sz == cap) grow(sz+1); new (&data[sz]) T() ; sz++; } - void push (const T& elem) { if (sz == cap) grow(sz+1); new (&data[sz]) T(elem); sz++; } - const T& last (void) const { return data[sz-1]; } - T& last (void) { return data[sz-1]; } - - // Vector interface: - const T& operator [] (int index) const { return data[index]; } - T& operator [] (int index) { return data[index]; } - - // Don't allow copying (error prone): - vec& operator = (vec& other) { TEMPLATE_FAIL; } - vec (vec& other) { TEMPLATE_FAIL; } - - // Duplicatation (preferred instead): - void copyTo(vec& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) new (©[i]) T(data[i]); } - void moveTo(vec& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; } -}; - -template -void vec::grow(int min_cap) { - if (min_cap <= cap) return; - if (cap == 0) cap = (min_cap >= 2) ? min_cap : 2; - else do cap = (cap*3+1) >> 1; while (cap < min_cap); - data = xrealloc(data, cap); } - -template -void vec::growTo(int size, const T& pad) { - if (sz >= size) return; - grow(size); - for (int i = sz; i < size; i++) new (&data[i]) T(pad); - sz = size; } - -template -void vec::growTo(int size) { - if (sz >= size) return; - grow(size); - for (int i = sz; i < size; i++) new (&data[i]) T(); - sz = size; } - -template -void vec::clear(bool dealloc) { - if (data != NULL){ - for (int i = 0; i < sz; i++) data[i].~T(); - sz = 0; - if (dealloc) xfree(data), data = NULL, cap = 0; } } - - -//================================================================================================= -// Lifted booleans: - - -class lbool { - int value; - explicit lbool(int v) : value(v) { } - -public: - lbool() : value(0) { } - lbool(bool x) : value((int)x*2-1) { } - int toInt(void) const { return value; } - - bool operator == (const lbool& other) const { return value == other.value; } - bool operator != (const lbool& other) const { return value != other.value; } - lbool operator ~ (void) const { return lbool(-value); } - - friend int toInt (lbool l); - friend lbool toLbool(int v); -}; -inline int toInt (lbool l) { return l.toInt(); } -inline lbool toLbool(int v) { return lbool(v); } - -const lbool l_True = toLbool( 1); -const lbool l_False = toLbool(-1); -const lbool l_Undef = toLbool( 0); - - -//================================================================================================= -// Relation operators -- extend definitions from '==' and '<' - - -#ifndef __SGI_STL_INTERNAL_RELOPS // (be aware of SGI's STL implementation...) -#define __SGI_STL_INTERNAL_RELOPS -template static inline bool operator != (const T& x, const T& y) { return !(x == y); } -template static inline bool operator > (const T& x, const T& y) { return y < x; } -template static inline bool operator <= (const T& x, const T& y) { return !(y < x); } -template static inline bool operator >= (const T& x, const T& y) { return !(x < y); } -#endif - - -//================================================================================================= -#endif diff --git a/src/sat/Heap.h b/src/sat/Heap.h deleted file mode 100644 index cddf6693..00000000 --- a/src/sat/Heap.h +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************************[Heap.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Heap_h -#define Heap_h - - -//================================================================================================= - - -static inline int left (int i) { return i+i; } -static inline int right (int i) { return i+i + 1; } -static inline int parent(int i) { return i >> 1; } - -template -class Heap { - public: - C comp; - vec heap; // heap of ints - vec indices; // int -> index in heap - - inline void percolateUp(int i) - { - int x = heap[i]; - while (parent(i) != 0 && comp(x,heap[parent(i)])){ - heap[i] = heap[parent(i)]; - indices[heap[i]] = i; - i = parent(i); - } - heap [i] = x; - indices[x] = i; - } - - inline void percolateDown(int i) - { - int x = heap[i]; - while (left(i) < heap.size()){ - int child = right(i) < heap.size() && comp(heap[right(i)],heap[left(i)]) ? right(i) : left(i); - if (!comp(heap[child],x)) break; - heap[i] = heap[child]; - indices[heap[i]] = i; - i = child; - } - heap [i] = x; - indices[x] = i; - } - - bool ok(int n) { return n >= 0 && n < (int)indices.size(); } - - public: - Heap(C c) : comp(c) { heap.push(-1); } - - void setBounds (int size) { assert(size >= 0); indices.growTo(size,0); } - bool inHeap (int n) { assert(ok(n)); return indices[n] != 0; } - void increase (int n) { assert(ok(n)); assert(inHeap(n)); percolateUp(indices[n]); } - bool empty () { return heap.size() == 1; } - - void insert(int n) { - assert(ok(n)); - indices[n] = heap.size(); - heap.push(n); - percolateUp(indices[n]); } - - int getmin() { - int r = heap[1]; - heap[1] = heap.last(); - indices[heap[1]] = 1; - indices[r] = 0; - heap.pop(); - if (heap.size() > 1) - percolateDown(1); - return r; } - - bool heapProperty() { - return heapProperty(1); } - - bool heapProperty(int i) { - return (size_t)i >= heap.size() - || ((parent(i) == 0 || !comp(heap[i],heap[parent(i)])) && heapProperty(left(i)) && heapProperty(right(i))); } -}; - - -//================================================================================================= -#endif diff --git a/src/sat/NO_USE/sat.h b/src/sat/NO_USE/sat.h deleted file mode 100644 index be3af770..00000000 --- a/src/sat/NO_USE/sat.h +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** - FileName [ sat.h ] - PackageName [ sat ] - Synopsis [ Encapsulation of solver engines for inheritance. ] - Author [ Cheng-Yin Wu, Chung-Yang (Ric) Huang ] - Copyright [ Copyleft(c) 2010 LaDs(III), GIEE, NTU, Taiwan ] -****************************************************************************/ - -#ifndef SAT_H -#define SAT_H - -#include "verifyDefine.h" -#include "verifyStream.h" -#include "cktCell.h" - -// Base solver engine class, cannot be directly used! -class satSolver -{ - public : - satSolver(const satType); - virtual ~satSolver(); - - // Solver Interface Functions -* virtual bool setOutputFile(const string); - virtual void initialize(); -* virtual void assumeInit(); -* virtual void assertInit(); -* virtual void assumeRelease(); -* virtual void assumeProperty(CktOutPin*, bool); - virtual void assertProperty(CktOutPin*, bool); -* virtual void allProperty(CktOutPin*, bool); -* virtual void increaseBound(); - virtual bool solve(); -* virtual bool assump_solve(); -* virtual void printInfo() const; -* virtual void printSolver() const; -* virtual bool admitListSize(const unsigned&) const; - virtual bool existVerifyData(CktOutPin*, const unsigned& = 0) const; - // Cell Formula to Solver Functions - virtual void add_PI_Formula(CktCell*, const unsigned&); // PI, PO, PIO - virtual void add_AND_Formula(CktCell*, const unsigned&); - virtual void add_CONST_Formula(CktCell*, const unsigned&); // RTL Model - // Solver Basic Function - void addVerifyData(CktCell*, const unsigned&); -* // Static Functions -* static VerifySolver* newVerifySolver(const SolverType); - - private : - vector _DFFList; -}; - -// User-Introduced Solver Engine -/********** MiniSAT_Solver **********/ -class MiniSAT_Solver : public VerifySolver -{ - public : - MiniSAT_Solver(); - ~MiniSAT_Solver(); - // Solver Interface Functions Realization - void initialize(); -* void assumeInit(); -* void assertInit(); -* void assumeRelease(); -* void assumeProperty(CktOutPin*, bool); - void assertProperty(CktOutPin*, bool); -* void allProperty(CktOutPin*, bool); -* void increaseBound(); - bool solve(); -* bool assump_solve(); -* void printInfo() const; -* void printSolver() const; -* bool admitListSize(const unsigned&) const; - bool existVerifyData(CktOutPin*, const unsigned& = 0) const; - // Cell Formula to Solver Functions Realization - void add_PI_Formula(CktCell*, const unsigned&); // PI, PO, PIO - void add_AND_Formula(CktCell*, const unsigned&); - void add_CONST_Formula(CktCell*, const unsigned&); // RTL Model - // Inline Functions - inline void resetVerifyData() { resetDFFList(); _init.clear(); _vars.clear(); _assump.clear(); _curVar = 0; } - // MiniSat Functions - Var newVar(const unsigned&); - Var getVerifyData(CktOutPin*, const unsigned&) const; - private : - Solver* _Solver; // Pointer to a Minisat solver - Var _curVar; // Variable currently - vec _assump; // Assumption List for assumption solve - SATVarVec _init; // Initial state Var storage - SATVarMap _vars; // Mapping from CktOutPin* to Var -}; - -#endif // SAT_H - diff --git a/src/sat/NO_USE/satMiniSat.cpp b/src/sat/NO_USE/satMiniSat.cpp deleted file mode 100644 index 0828c635..00000000 --- a/src/sat/NO_USE/satMiniSat.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** - FileName [ satMiniSat.cpp ] - PackageName [ sat ] - Synopsis [ Implementation of interface functions for MiniSat. ] - Author [ Cheng-Yin Wu, Chung-Yang (Ric) Huang ] - Copyright [ Copyleft(c) 2010 LaDs(III), GIEE, NTU, Taiwan ] -****************************************************************************/ - -#include "satMiniSat.h" -#include "satCommon.h" - -Var -MiniSAT_Solver::newVar(const unsigned& width) { - Var cur_var = _curVar; - for (unsigned i = 0; i < width; ++i) _Solver->newVar(); - _curVar += width; - return cur_var; -} - -void -MiniSAT_Solver::add_PI_Formula(CktCell* cell, const unsigned& depth) { - check_PI_IO(cell); - CktOutPin* OutPin = cell->getOutPin(); - unsigned width = VLDesign.getBus(OutPin->getBusId())->getWidth(); - _vars[depth].insert(make_pair(OutPin, newVar(width))); // set SATVar -} - -void -MiniSAT_Solver::add_AND_Formula(CktCell* cell, const unsigned& depth) { - check_AND_IO(cell); - CktOutPin* OutPin = cell->getOutPin(); - unsigned width = VLDesign.getBus(OutPin->getBusId())->getWidth(); - Var var = _curVar; _vars[depth].insert(make_pair(OutPin, newVar(width))); // set SATVar - CktOutPin* aOutPin = cell->getInPin(0)->getOutPin(); - unsigned aWidth = VLDesign.getBus(aOutPin->getBusId())->getWidth(); - Var aVar = getVerifyData(aOutPin, depth); assert (aVar); - if (static_cast(cell)->getType() == CKT_RED) and_red(_Solver, aVar, var, aWidth); // Reduced - else { - CktOutPin* bOutPin = cell->getInPin(1)->getOutPin(); - Var bVar = getVerifyData(bOutPin, depth); assert (bVar); - if (static_cast(cell)->getType() == CKT_LOG) and_2(_Solver, aVar, bVar, var); // Logic - else for (unsigned i = 0; i < width; ++i) and_2(_Solver, aVar + i, bVar + i, var + i); // Bit-wise - } -} - diff --git a/src/sat/Proof.cpp b/src/sat/Proof.cpp deleted file mode 100644 index 9f5fedfe..00000000 --- a/src/sat/Proof.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/*****************************************************************************************[Proof.C] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#include "Proof.h" -#include "Sort.h" -#include - -//================================================================================================= -// Temporary files handling: - - -class TempFiles { - vec files; // For clean-up purposed on abnormal exit. - -public: - ~TempFiles() - { - for (int i = 0; i < files.size(); i++) - remove(files[i]); - //printf("Didn't delete:\n %s\n", files[i]); - } - - // Returns a read-only string with the filename of the temporary file. The pointer can be used to - // remove the file (which is otherwise done automatically upon program exit). - // - char* open(File& fp) - { -// char * name; -// char* name = "/tmp/fileXXXXXX"; - char* name = new char[64]; - strcpy(name, "/tmp/fileXXXXXX"); - for(;;){ -// name = tempnam(NULL, NULL); // (gcc complains about this... stupid gcc...) -// fp.open(name, "wx+"); - fp.open( mkstemp(name) , WRITE , true ); - assert(name != NULL); - if (fp.null()) - xfree(name); - else{ - files.push(name); - return name; - } - } - } -}; -static TempFiles temp_files; // (should be singleton) - - -//================================================================================================= -// Proof logging: - - -Proof::Proof() -{ - fp_name = temp_files.open(fp); - id_counter = 0; - trav = NULL; - TRA_INT = 0; - fpos =0 ; -} - - -Proof::Proof(ProofTraverser& t) -{ - id_counter = 0; - trav = &t; - TRA_INT = 0; - fpos = 0; -} - - -ClauseId Proof::addRoot(vec& cl, bool A) -{ - cl.copyTo(clause); - sortUnique(clause); - - if (trav != NULL) - trav->root(clause, A); - if (!fp.null()){ - putUInt(fp, index(clause[0]) << 1); - for (int i = 1; i < clause.size(); i++) - putUInt(fp, index(clause[i]) - index(clause[i-1])); - putUInt(fp, 0); // (0 is safe terminator since we removed duplicates) - if(A) putUInt(fp , 1); - else putUInt(fp , 2 ); - } - - return id_counter++; -} - - -void Proof::beginChain(ClauseId start) -{ - assert(start != ClauseId_NULL); - chain_id .clear(); - chain_lit.clear(); - chain_id.push(start); -} - - -void Proof::resolve(ClauseId next, Lit x) -{ - assert(next != ClauseId_NULL); - chain_id .push(next); - chain_lit.push(x); -} - - -ClauseId Proof::endChain() -{ - assert(chain_id.size() == chain_lit.size() + 1); - if (chain_id.size() == 1) - return chain_id[0]; - else{ - if (trav != NULL) - trav->chain(chain_id, chain_lit); - if (!fp.null()){ - putUInt(fp, ((id_counter - chain_id[0]) << 1) | 1); - for (int i = 0; i < chain_lit.size(); i++) - putUInt(fp, index(chain_lit[i])+1 ), - putUInt(fp, id_counter - chain_id[i+1]); - putUInt(fp, 0); - } - - return id_counter++; - } -} - - -void Proof::deleted(ClauseId gone) -{ - if (trav != NULL) - trav->deleted(gone); - if (!fp.null()){ - putUInt(fp, ((id_counter - gone) << 1) | 1); - putUInt(fp, 0); - } -} - - -//================================================================================================= -// Read-back methods: - - -void Proof::compress(Proof& dst, ClauseId goal) -{ - assert(!fp.null()); - assert(false); // Not yet! -} - - -bool Proof::save(cchar* filename) -{ - assert(!fp.null()); - - // Switch to read mode: - fp.setMode(READ); - fp.seek(0); - - // Copy file: - File out(filename, "wox"); - if (out.null()) - return false; - - while (!fp.eof()) - out.putChar(fp.getChar()); - - // Restore write (proof-logging) mode: - fp.seek(0, SEEK_END); - fp.setMode(WRITE); - return true; -} - - -void Proof::traverse(ProofTraverser& trav, ClauseId goal) -{ - assert(!fp.null()); - - // Switch to read mode: - fp.setMode(READ); - fp.seek( fpos ); - - // Traverse proof: - if (goal == ClauseId_NULL) - goal = last(); - - uint64 tmp; - int idx; - bool A; - - for(ClauseId id = TRA_INT ; id <= goal; id++){ - tmp = getUInt(fp); - if ((tmp & 1) == 0){ - // Root clause: - clause.clear(); - idx = tmp >> 1; - clause.push(toLit(idx)); - for(;;){ - tmp = getUInt(fp); - if (tmp == 0) break; - idx += tmp; - clause.push(toLit(idx)); - } - if( getUInt(fp) == 1 ) A = true; - else A = false; - //assert( false); - trav.root(clause ,A); - - - }else{ - // Derivation or Deletion: - - chain_id .clear(); - chain_lit.clear(); - chain_id.push(id - (tmp >> 1)); - for(;;){ - tmp = getUInt(fp); - if (tmp == 0) break; - chain_lit.push(toLit( tmp - 1)); - tmp = getUInt(fp); - chain_id.push(id - tmp); - } - - if (chain_lit.size() == 0) - id--, // (no new clause introduced) - trav.deleted(chain_id[0]); - else - trav.chain(chain_id, chain_lit); - } - } - TRA_INT = goal+1; - fpos = fp.tell(); - fp.seek(0, SEEK_END); - fp.setMode(WRITE); -} diff --git a/src/sat/Proof.h b/src/sat/Proof.h deleted file mode 100644 index b1dbe039..00000000 --- a/src/sat/Proof.h +++ /dev/null @@ -1,74 +0,0 @@ -/*****************************************************************************************[Proof.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Proof_h -#define Proof_h - -#include "SolverTypes.h" -#include "File.h" - - -//================================================================================================= - - -// A "listner" for the proof. Proof events will be passed onto (online mode) or replayed to -// (offline mode) this class. Each call to 'root()' or 'chain()' produces a new clause. The first -// clause has ID 0, the next 1 and so on. These are the IDs passed to 'chain()'s 'cs' parameter. -// -struct ProofTraverser { - virtual void root (const vec& c , bool A)=0;// {assert(false);}; - virtual void chain (const vec& cs, const vec& xs)=0;// {assert(false);}; - virtual void deleted(ClauseId c){} - virtual void done ()=0;//{assert(false);} - virtual ~ProofTraverser(){} -}; - - -class Proof { - File fp; - cchar* fp_name; - ClauseId id_counter; - ProofTraverser* trav; - - int TRA_INT; - int64 fpos; - - vec clause; - vec chain_id; - vec chain_lit; - -public: - Proof(); // Offline mode -- proof stored to a file, which can be saved, compressed, and/or traversed. - Proof(ProofTraverser& t); // Online mode -- proof will not be stored. - - ClauseId addRoot (vec& clause , bool A ); - void beginChain(ClauseId start); - void resolve (ClauseId next, Lit x); - ClauseId endChain (); - void deleted (ClauseId gone); - ClauseId last () { assert(id_counter != ClauseId_NULL); return id_counter - 1; } - - void compress (Proof& dst, ClauseId goal = ClauseId_NULL); // 'dst' should be a newly constructed, empty proof. - bool save (cchar* filename); - void traverse (ProofTraverser& trav, ClauseId goal = ClauseId_NULL) ; -}; - - -//================================================================================================= -#endif diff --git a/src/sat/README b/src/sat/README deleted file mode 100644 index 47c7b58e..00000000 --- a/src/sat/README +++ /dev/null @@ -1,76 +0,0 @@ -1. What can a SAT solver do? - - Given a circuit and a satisfiability target (e.g. a PO assignment), - SAT solver can find a PI assignemt to satisfy the target. If for all - input combinations such PI assignment does not exist, it will report - "unsatisfiable". - - -2. Why should we use SAT solver in this project? - - The FEC pairs identified by simulations are just "potential" - equivalent pairs of signals. We will use SAT solver to formally check - if they are indeed equivalent. - - -3. How to prove the equivalence of a FEC pair? - - We prove it by contraposition. That is, given a FEC pair (a, b), - we will create a new signal "f = a xor b" and use SAT solver to solve - "f = 1". If "f = 1" is satisfiable (i.e. an input assignment is found), - we will know that a and b are not equivalent and this assignment - is a counter-example. Otherwise (the proof returns "unsatisfiable"), we - can conclude that a and b must be equivalent. - - -4. What does a SAT solver look like? - - We will use the miniSat SAT solver (http://minisat.se/). The SAT - solver is defined as a C++ class and you don't really need to look into - it. When you want to use it, you need to first create a SAT solver - object, add clauses to the solver for the circuit under proof, specify - the target signal/value to prove, and call the solver to prove it. - - -5. What do we provide in the reference code? - - The miniSat SAT solver has been simplified and included in the "sat" - package. However, you don't need to study the code. All you need to - know and use is the interface functions defined in "sat.h". Just include - "sat.h" in the file you want to evoke SAT solver. - - -6. How to use the miniSat SAT solver? - -(1) Create a SAT solver object (e.g. SatSolver s;) -(2) Initialize it (by SatSolver::initialize()) -(3) Generate the proof model from the circuit. - - For each PI and AIG gate, assign a distinct "variable ID". - The var IDs for the POs should be the same as its single fanin. - - You should have a mechanism to record the mapping from your gates - to the variable IDs in the solver. The mapping can be stored as a - STL map (e.g. map), or recorded in a data member - in the class CirAigGate. - - For each AIG gate, construct the CNF formula for it and add to the - solver. You can use "SatSolver::addAndCNF(vf, va, fa, vb, fb)", - where vf, va and vb are the variable IDs for this gate and its two - fanins (f = a & b), and fa, fb are bool variables to indicate where - the inputs are inverted. - - Add the proof logic if necessary. For example, to prove "a == b", - you should add the clauses of "f = a xor b" to the solver, where - "f" is a new varaible and you can add the clauses by the function - "SatSolver::addXorCNF()". -(4) Add the SAT target as "assumption" to the solver instance. - - Call "SatSolver::assumeRelease()" to reset the assumptions. - - Add the SAT target(s) by "SatSolver::assumeProperty(varID, value)". - For example, "solver->assumeProperty(38, true)". - - Call "SatSolver::assumpSolve()" to solve. If it returns true, the - SAT target is satisfiable. You can get the input assignment by the - function "int SatSolver::getValue(Var)". - - If the above step returns unsatisfiable, we can conclude the FEC pair - must be equivalent and we can then merge them. -(5) Repeat (4) if you need to prove more SAT instances. - - -7. Please see "sat/test/satTest.cpp" for an example of using SAT. - diff --git a/src/sat/Solver.cpp b/src/sat/Solver.cpp deleted file mode 100644 index 7e6b34ba..00000000 --- a/src/sat/Solver.cpp +++ /dev/null @@ -1,854 +0,0 @@ -/****************************************************************************************[Solver.C] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#include "Solver.h" -#include "Sort.h" -#include - -int effLimit = INT_MAX; // 100000; // INT_MAX; - -//================================================================================================= -// Helper functions: - - -void removeWatch(vec& ws, Clause* elem) -{ - if (ws.size() == 0) return; // (skip lists that are already cleared) - int j = 0; - for (; ws[j] != elem ; j++) assert(j < ws.size()); - for (; j < ws.size()-1; j++) ws[j] = ws[j+1]; - ws.pop(); -} - - -//================================================================================================= -// Operations on clauses: - - -/*_________________________________________________________________________________________________ -| -| newClause : (ps : const vec&) (learnt : bool) (id : ClauseId) -> [void] -| -| Description: -| Allocate and add a new clause to the SAT solvers clause database. If a conflict is detected, -| the 'ok' flag is cleared and the solver is in an unusable state (must be disposed). -| -| Input: -| ps - The new clause as a vector of literals. -| learnt - Is the clause a learnt clause? For learnt clauses, 'ps[0]' is assumed to be the -| asserting literal. An appropriate 'enqueue()' operation will be performed on this -| literal. One of the watches will always be on this literal, the other will be set to -| the literal with the highest decision level. -| id - If logging proof, learnt clauses should be given an ID by caller. -| -| Effect: -| Activity heuristics are updated. -|________________________________________________________________________________________________@*/ -void Solver::newClause(const vec& ps_, bool learnt, ClauseId id , bool A) -{ - assert(learnt || id == ClauseId_NULL); - if (!ok) return; - - vec qs; - if (!learnt){ - assert(decisionLevel() == 0); - ps_.copyTo(qs); // Make a copy of the input vector. - - // Remove duplicates: - sortUnique(qs); - - // Check if clause is satisfied: - for (int i = 0; i < qs.size()-1; i++){ - if (qs[i] == ~qs[i+1]) - return; } - for (int i = 0; i < qs.size(); i++){ - if (value(qs[i]) == l_True) - return; } - - // Remove false literals: - int i, j; - if (proof != NULL) proof->beginChain(proof->addRoot(qs,A)); - for (i = j = 0; i < qs.size(); i++) - if (value(qs[i]) != l_False) - qs[j++] = qs[i]; - else - if (proof != NULL) proof->resolve(unit_id[var(qs[i])], qs[i]); - qs.shrink(i - j); - if (proof != NULL) id = proof->endChain(); - } - const vec& ps = learnt ? ps_ : qs; // 'ps' is now the (possibly) reduced vector of literals. - - if (ps.size() == 0){ - ok = false; - - }else if (ps.size() == 1){ - // NOTE: If enqueue takes place at root level, the assignment will be lost in incremental use (it doesn't seem to hurt much though). - if (id != ClauseId_NULL) - unit_id[var(ps[0])] = id; - if (!enqueue(ps[0])) - ok = false; - - }else{ - // Allocate clause: - Clause* c = Clause_new(learnt, ps, id); - - if (learnt){ - // Put the second watch on the literal with highest decision level: - int max_i = 1; - int max = level[var(ps[1])]; - for (int i = 2; i < ps.size(); i++) - if (level[var(ps[i])] > max) - max = level[var(ps[i])], - max_i = i; - (*c)[1] = ps[max_i]; - (*c)[max_i] = ps[1]; - - // Bumping: - claBumpActivity(c); // (newly learnt clauses should be considered active) - - // Enqueue asserting literal: - check(enqueue((*c)[0], c)); - - // Store clause: - watches[index(~(*c)[0])].push(c); - watches[index(~(*c)[1])].push(c); - learnts.push(c); - stats.learnts_literals += c->size(); - - }else{ - // Store clause: - watches[index(~(*c)[0])].push(c); - watches[index(~(*c)[1])].push(c); - clauses.push(c); - stats.clauses_literals += c->size(); - } - } -} - - -// Disposes a clauses and removes it from watcher lists. NOTE! Low-level; does NOT change the 'clauses' and 'learnts' vector. -// -void Solver::remove(Clause* c, bool just_dealloc) -{ - if (!just_dealloc){ - removeWatch(watches[index(~(*c)[0])], c), - removeWatch(watches[index(~(*c)[1])], c); - - if (c->learnt()) stats.learnts_literals -= c->size(); - else stats.clauses_literals -= c->size(); - - if (proof != NULL) proof->deleted(c->id()); - } - - xfree(c); -} - - -// Can assume everything has been propagated! (esp. the first two literals are != l_False, unless -// the clause is binary and satisfied, in which case the first literal is true) -// Returns True if clause is satisfied (will be removed), False otherwise. -// -bool Solver::simplify(Clause* c) const -{ - assert(decisionLevel() == 0); - for (int i = 0; i < c->size(); i++){ - if (value((*c)[i]) == l_True) - return true; - } - return false; -} - - -//================================================================================================= -// Minor methods: - - -// Creates a new SAT variable in the solver. If 'decision_var' is cleared, variable will not be -// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result). -// -Var Solver::newVar() { - int index; - index = nVars(); - watches .push(); // (list for positive literal) - watches .push(); // (list for negative literal) - reason .push(NULL); - assigns .push(toInt(l_Undef)); - level .push(-1); - trail_pos .push(-1); - activity .push(0); - order .newVar(); - analyze_seen.push(0); - if (proof != NULL) unit_id.push(ClauseId_NULL); - return index; } - - -// Returns FALSE if immediate conflict. -bool Solver::assume(Lit p) { - trail_lim.push(trail.size()); - return enqueue(p); } - - -// Revert to the state at given level. -void Solver::cancelUntil(int level) { - if (decisionLevel() > level){ - for (int c = trail.size()-1; c >= trail_lim[level]; c--){ - Var x = var(trail[c]); - assigns[x] = toInt(l_Undef); - reason [x] = NULL; - order.undo(x); } - trail.shrink(trail.size() - trail_lim[level]); - trail_lim.shrink(trail_lim.size() - level); - qhead = trail.size(); } } - - -//================================================================================================= -// Major methods: - - -/*_________________________________________________________________________________________________ -| -| analyze : (confl : Clause*) (out_learnt : vec&) (out_btlevel : int&) -> [void] -| -| Description: -| Analyze conflict and produce a reason clause ('out_learnt') and a backtracking level -| ('out_btlevel'). -| -| Pre-conditions: -| * 'out_learnt' is assumed to be cleared. -| * Current decision level must be greater than root level. -| -| Post-conditions: -| * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'. -| * If performing proof-logging, the last derived clause in the proof is the reason clause. -|________________________________________________________________________________________________@*/ - -class lastToFirst_lt { // Helper class to 'analyze' -- order literals from last to first occurance in 'trail[]'. - const vec& trail_pos; -public: - lastToFirst_lt(const vec& t) : trail_pos(t) {} - bool operator () (Lit p, Lit q) { return trail_pos[var(p)] > trail_pos[var(q)]; } -}; -void Solver::analyze(Clause* confl, vec& out_learnt, int& out_btlevel) -{ - vec& seen = analyze_seen; - int pathC = 0; - Lit p = lit_Undef; - - // Generate conflict clause: - // - if (proof != NULL) proof->beginChain(confl->id()); - out_learnt.push(); // (leave room for the asserting literal) - out_btlevel = 0; - int index = trail.size()-1; - for(;;){ - assert(confl != NULL); // (otherwise should be UIP) - - Clause& c = *confl; - if (c.learnt()) - claBumpActivity(&c); - - for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){ - Lit q = c[j]; - if (!seen[var(q)]){ - if (level[var(q)] > 0){ - varBumpActivity(q); - seen[var(q)] = 1; - if (level[var(q)] == decisionLevel()) - pathC++; - else{ - out_learnt.push(q); - out_btlevel = max(out_btlevel, level[var(q)]); - } - }else - if (proof != NULL) proof->resolve(unit_id[var(q)], q); - } - } - - // Select next clause to look at: - while (!seen[var(trail[index--])]); - p = trail[index+1]; - confl = reason[var(p)]; - seen[var(p)] = 0; - pathC--; - if (pathC == 0) break; - - if (proof != NULL) proof->resolve(confl->id(), ~p); - } - out_learnt[0] = ~p; - - // Conflict clause minimization: - // - int i=0 , j=0 ; - if (expensive_ccmin == 2){ - // Simplify conflict clause (a lot): - // - uint min_level = 0; - for (i = 1; i < out_learnt.size(); i++) - min_level |= 1 << (level[var(out_learnt[i])] & 31); // (maintain an abstraction of levels involved in conflict) - - analyze_toclear.clear(); - for (i = j = 1; i < out_learnt.size(); i++) - if (reason[var(out_learnt[i])] == NULL || !analyze_removable(out_learnt[i], min_level)) - out_learnt[j++] = out_learnt[i]; - }else if(expensive_ccmin == 1){ - // Simplify conflict clause (a little): - // - analyze_toclear.clear(); - for (i = j = 1; i < out_learnt.size(); i++){ - Clause* r = reason[var(out_learnt[i])]; - if (r == NULL) - out_learnt[j++] = out_learnt[i]; - else{ - Clause& c = *r; - for (int k = 1; k < c.size(); k++) - if (!seen[var(c[k])] && level[var(c[k])] != 0){ - out_learnt[j++] = out_learnt[i]; - goto Keep; - } - analyze_toclear.push(out_learnt[i]); - Keep:; - } - } - } - - // Finilize proof logging with conflict clause minimization steps: - // - if (proof != NULL){ - sort(analyze_toclear, lastToFirst_lt(trail_pos)); - for (int k = 0; k < analyze_toclear.size(); k++){ - Var v = var(analyze_toclear[k]); assert(level[v] > 0); - Lit l = analyze_toclear[k]; - Clause& c = *reason[v]; - proof->resolve(c.id(), l); - for (int k = 1; k < c.size(); k++) - if (level[var(c[k])] == 0) - proof->resolve(unit_id[var(c[k])], c[k]); - } - proof->endChain(); - } - // Clean up: - // - for (int j = 0; j < out_learnt.size() ; j++) seen[var(out_learnt [j])] = 0; - for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared) - - stats.max_literals += out_learnt.size(); - out_learnt.shrink(i - j); - stats.tot_literals += out_learnt.size(); -} - - -// Check if 'p' can be removed. 'min_level' is used to abort early if visiting literals at a level that cannot be removed. -// -bool Solver::analyze_removable(Lit p, uint min_level) -{ - assert(reason[var(p)] != NULL); - analyze_stack.clear(); analyze_stack.push(p); - int top = analyze_toclear.size(); - while (analyze_stack.size() > 0){ - assert(reason[var(analyze_stack.last())] != NULL); - Clause& c = *reason[var(analyze_stack.last())]; - analyze_stack.pop(); - for (int i = 1; i < c.size(); i++){ - Lit p = c[i]; - if (!analyze_seen[var(p)] && level[var(p)] != 0){ - if (reason[var(p)] != NULL && ((1 << (level[var(p)] & 31)) & min_level) != 0){ - analyze_seen[var(p)] = 1; - analyze_stack.push(p); - analyze_toclear.push(p); - }else{ - for (int j = top; j < analyze_toclear.size(); j++) - analyze_seen[var(analyze_toclear[j])] = 0; - analyze_toclear.shrink(analyze_toclear.size() - top); - return false; - } - } - } - } - analyze_toclear.push(p); - - return true; -} - - -/*_________________________________________________________________________________________________ -| -| analyzeFinal : (confl : Clause*) (skip_first : bool) -> [void] -| -| Description: -| Specialized analysis procedure to express the final conflict in terms of assumptions. -| 'root_level' is allowed to point beyond end of trace (useful if called after conflict while -| making assumptions). If 'skip_first' is TRUE, the first literal of 'confl' is ignored (needed -| if conflict arose before search even started). -|________________________________________________________________________________________________@*/ -void Solver::analyzeFinal(Clause* confl, bool skip_first) -{ - // -- NOTE! This code is relatively untested. Please report bugs! - conflict.clear(); - if (root_level == 0){ - if (proof != NULL) conflict_id = proof->last(); - return; } - //assert(false); - vec& seen = analyze_seen; - if (proof != NULL) proof->beginChain(confl->id()); - for (int i = skip_first ? 1 : 0; i < confl->size(); i++){ - Var x = var((*confl)[i]); - Lit l = (*confl)[i]; - if (level[x] > 0) - seen[x] = 1; - else - if (proof != NULL) proof->resolve(unit_id[x], l); - } - - int start = (root_level >= trail_lim.size()) ? trail.size()-1 : trail_lim[root_level]; - for (int i = start; i >= trail_lim[0]; i--){ - Var x = var(trail[i]); - Lit l = trail[i]; - if (seen[x]){ - Clause* r = reason[x]; - if (r == NULL){ - assert(level[x] > 0); - conflict.push(~trail[i]); - }else{ - Clause& c = *r; - if (proof != NULL) proof->resolve(c.id(), l); - for (int j = 1; j < c.size(); j++) - if (level[var(c[j])] > 0) - seen[var(c[j])] = 1; - else - if (proof != NULL) proof->resolve(unit_id[var(c[j])], c[j]); - } - seen[x] = 0; - } - } - if (proof != NULL) conflict_id = proof->endChain(); -} - - -/*_________________________________________________________________________________________________ -| -| enqueue : (p : Lit) (from : Clause*) -> [bool] -| -| Description: -| Puts a new fact on the propagation queue as well as immediately updating the variable's value. -| Should a conflict arise, FALSE is returned. -| -| Input: -| p - The fact to enqueue -| from - [Optional] Fact propagated from this (currently) unit clause. Stored in 'reason[]'. -| Default value is NULL (no reason). -| -| Output: -| TRUE if fact was enqueued without conflict, FALSE otherwise. -|________________________________________________________________________________________________@*/ -bool Solver::enqueue(Lit p, Clause* from) -{ - if (value(p) != l_Undef) - return value(p) != l_False; - else{ - Var x = var(p); - assigns [x] = toInt(lbool(!sign(p))); - level [x] = decisionLevel(); - trail_pos[x] = trail.size(); - reason [x] = from; - trail.push(p); - return true; - } -} - - - -/*_________________________________________________________________________________________________ -| -| propagate : [void] -> [Clause*] -| -| Description: -| Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned, -| otherwise NULL. NOTE! This method has been optimized for speed rather than readability. -| -| Post-conditions: -| * The propagation queue is empty, even if there was a conflict. -|________________________________________________________________________________________________@*/ -Clause* Solver::propagate() -{ - Clause* confl = NULL; - while (qhead < trail.size()){ - stats.propagations++; - simpDB_props--; - - Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. - vec& ws = watches[index(p)]; - Clause** i,** j,** end; - - for (i = j = (Clause**)ws, end = i + ws.size(); i != end;){ - Clause& c = **i; i++; - // Make sure the false literal is data[1]: - Lit false_lit = ~p; - if (c[0] == false_lit) - c[0] = c[1], c[1] = false_lit; - - assert(c[1] == false_lit); - - // If 0th watch is true, then clause is already satisfied. - Lit first = c[0]; - lbool val = value(first); - if (val == l_True){ - *j++ = &c; - }else{ - // Look for new watch: - for (int k = 2; k < c.size(); k++) - if (value(c[k]) != l_False){ - c[1] = c[k]; c[k] = false_lit; - watches[index(~c[1])].push(&c); - goto FoundWatch; } - - // Did not find watch -- clause is unit under assignment: - if (decisionLevel() == 0 && proof != NULL){ - // Log the production of this unit clause: - proof->beginChain(c.id()); - for (int k = 1; k < c.size(); k++) - proof->resolve(unit_id[var(c[k])], c[k]); - ClauseId id = proof->endChain(); - assert(unit_id[var(first)] == ClauseId_NULL || value(first) == l_False); // (if variable already has 'id', it must be with the other polarity and we should have derived the empty clause here) - if (value(first) != l_False) - unit_id[var(first)] = id; - else{ - // Empty clause derived: - proof->beginChain(unit_id[var(first)]); - proof->resolve(id, ~first); - proof->endChain(); - } - } - - *j++ = &c; - if (!enqueue(first, &c)){ - if (decisionLevel() == 0) - ok = false; - confl = &c; - qhead = trail.size(); - // Copy the remaining watches: - while (i < end) - *j++ = *i++; - } - FoundWatch:; - } - } - ws.shrink(i - j); - } - - return confl; -} - - -/*_________________________________________________________________________________________________ -| -| reduceDB : () -> [void] -| -| Description: -| Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked -| clauses are clauses that are reason to some assignment. Binary clauses are never removed. -|________________________________________________________________________________________________@*/ -struct reduceDB_lt { bool operator () (Clause* x, Clause* y) { return x->size() > 2 && (y->size() == 2 || x->activity() < y->activity()); } }; -void Solver::reduceDB() -{ - int i, j; - double extra_lim = cla_inc / learnts.size(); // Remove any clause below this activity - - sort(learnts, reduceDB_lt()); - for (i = j = 0; i < learnts.size() / 2; i++){ - if (learnts[i]->size() > 2 && !locked(learnts[i])) - remove(learnts[i]); - else - learnts[j++] = learnts[i]; - } - for (; i < learnts.size(); i++){ - if (learnts[i]->size() > 2 && !locked(learnts[i]) && learnts[i]->activity() < extra_lim) - remove(learnts[i]); - else - learnts[j++] = learnts[i]; - } - learnts.shrink(i - j); -} - - -/*_________________________________________________________________________________________________ -| -| simplifyDB : [void] -> [bool] -| -| Description: -| Simplify the clause database according to the current top-level assigment. Currently, the only -| thing done here is the removal of satisfied clauses, but more things can be put here. -|________________________________________________________________________________________________@*/ -void Solver::simplifyDB() -{ - if (!ok) return; // GUARD (public method) - assert(decisionLevel() == 0); - - if (propagate() != NULL){ - ok = false; - return; } - - if (nAssigns() == simpDB_assigns || simpDB_props > 0) // (nothing has changed or preformed a simplification too recently) - return; - - // Clear watcher lists: - for (int i = simpDB_assigns; i < nAssigns(); i++){ - Lit p = trail[i]; - watches[index( p)].clear(true); - watches[index(~p)].clear(true); - } - - // Remove satisfied clauses: - for (int type = 0; type < 2; type++){ - vec& cs = type ? learnts : clauses; - int j = 0; - for (int i = 0; i < cs.size(); i++){ - if (!locked(cs[i]) && simplify(cs[i])) - remove(cs[i]); - else - cs[j++] = cs[i]; - } - cs.shrink(cs.size()-j); - } - - simpDB_assigns = nAssigns(); - simpDB_props = stats.clauses_literals + stats.learnts_literals; // (shouldn't depend on 'stats' really, but it will do for now) -} - - -/*_________________________________________________________________________________________________ -| -| search : (nof_conflicts : int) (nof_learnts : int) (params : const SearchParams&) -> [lbool] -| -| Description: -| Search for a model the specified number of conflicts, keeping the number of learnt clauses -| below the provided limit. NOTE! Use negative value for 'nof_conflicts' or 'nof_learnts' to -| indicate infinity. -| -| Output: -| 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If -| all variables are decision variables, this means that the clause set is satisfiable. 'l_False' -| if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached. -|________________________________________________________________________________________________@*/ -lbool Solver::search(int nof_conflicts, int nof_learnts, const SearchParams& params) -{ - if (!ok) return l_False; // GUARD (public method) - assert(root_level == decisionLevel()); - - stats.starts++; - int conflictC = 0; - var_decay = 1 / params.var_decay; - cla_decay = 1 / params.clause_decay; - model.clear(); - - for (;;){ - Clause* confl = propagate(); - if (confl != NULL){ - // CONFLICT - - stats.conflicts++; conflictC++; - vec learnt_clause; - int backtrack_level; - if (decisionLevel() == root_level){ - // Contradiction found: - analyzeFinal(confl); - return l_False; } - analyze(confl, learnt_clause, backtrack_level); - cancelUntil(max(backtrack_level, root_level)); - newClause(learnt_clause, true, (proof != NULL) ? proof->last() : ClauseId_NULL); - if (learnt_clause.size() == 1) level[var(learnt_clause[0])] = 0; // (this is ugly (but needed for 'analyzeFinal()') -- in future versions, we will backtrack past the 'root_level' and redo the assumptions) - varDecayActivity(); - claDecayActivity(); - - }else{ - // NO CONFLICT - - if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ - // Reached bound on number of conflicts: - progress_estimate = progressEstimate(); - cancelUntil(root_level); - return l_Undef; } - - if (decisionLevel() == 0) - // Simplify the set of problem clauses: - simplifyDB(), assert(ok); - - if (nof_learnts >= 0 && learnts.size()-nAssigns() >= nof_learnts) - // Reduce the set of learnt clauses: - reduceDB(); - - // New variable decision: - stats.decisions++; - Var next = order.select(params.random_var_freq); - - if (next == var_Undef){ - // Model found: - model.growTo(nVars()); - for (int i = 0; i < nVars(); i++) model[i] = value(i); - cancelUntil(root_level); - return l_True; - } - - check(assume(~Lit(next))); - } - } -} - - -// Return search-space coverage. Not extremely reliable. -// -double Solver::progressEstimate() -{ - double progress = 0; - double F = 1.0 / nVars(); - for (int i = 0; i < nVars(); i++) - if (value(i) != l_Undef) - progress += pow(F, level[i]); - return progress / nVars(); -} - - -// Divide all variable activities by 1e100. -// -void Solver::varRescaleActivity() -{ - for (int i = 0; i < nVars(); i++) - activity[i] *= 1e-100; - var_inc *= 1e-100; -} - - -// Divide all constraint activities by 1e100. -// -void Solver::claRescaleActivity() -{ - for (int i = 0; i < learnts.size(); i++) - learnts[i]->activity() *= 1e-20; - cla_inc *= 1e-20; -} - - -/*_________________________________________________________________________________________________ -| -| solve : (assumps : const vec&) -> [bool] -| -| Description: -| Top-level solve. If using assumptions (non-empty 'assumps' vector), you must call -| 'simplifyDB()' first to see that no top-level conflict is present (which would put the solver -| in an undefined state). -| -| Input: -| A list of assumptions (unit clauses coded as literals). Pre-condition: The assumptions must -| not contain both 'x' and '~x' for any variable 'x'. -|________________________________________________________________________________________________@*/ -lbool Solver::solve(const vec& assumps) -{ - simplifyDB(); - if (!ok) return l_False; // false; - - SearchParams params(default_params); - double nof_conflicts = 100; - double nof_learnts = nClauses() / 3; - lbool status = l_Undef; - - // Perform assumptions: - root_level = assumps.size(); - for (int i = 0; i < assumps.size(); i++){ - Lit p = assumps[i]; - assert(var(p) < nVars()); - if (!assume(p)){ - if (reason[var(p)] != NULL){ - analyzeFinal(reason[var(p)], true); - conflict.push(~p); - }else{ - assert(proof == NULL || unit_id[var(p)] != ClauseId_NULL); // (this is the pre-condition above) - conflict.clear(); - conflict.push(~p); - if (proof != NULL) conflict_id = unit_id[var(p)]; - } - cancelUntil(0); - return l_False; } // false; } - Clause* confl = propagate(); - if (confl != NULL){ - analyzeFinal(confl), assert(conflict.size() > 0); - cancelUntil(0); - return l_False; } // false; } - } - assert(root_level == decisionLevel()); - - // Search: - if (verbosity >= 1){ - reportf("==================================[MINISAT]"); - reportf("===================================\n"); - reportf("| Conflicts | ORIGINAL | "); - reportf("LEARNT | Progress |\n"); - reportf("| | Clauses Literals | Limit Clauses "); - reportf("Literals Lit/Cl | |\n"); - reportf("==========================================="); - reportf("===================================\n"); - } - - while (status == l_Undef){ - if (verbosity >= 1){ - printStats(); - reportf("| %9d | %7d %8d | %7d %7d %8d %7.1f | %6.3f %% |\n", - (int)stats.conflicts, nClauses(), - (int)stats.clauses_literals, - (int)nof_learnts, nLearnts(), - (int)stats.learnts_literals, - (double)stats.learnts_literals/nLearnts(), - progress_estimate*100); - fflush(stdout); - } - status = search((int)nof_conflicts, (int)nof_learnts, params); - nof_conflicts *= 1.5; - nof_learnts *= 1.1; - -if ((int)stats.conflicts >= effLimit) { - cancelUntil(0); - return l_Undef; // status == l_True; -// return status == l_True; -} - } - if (verbosity >= 1) { - reportf("==========================================="); - reportf("===================================\n"); - } - - cancelUntil(0); - return status; -// return status == l_True; -} - -void Solver::printStats() -{ - reportf("==============================[MINISAT]"); - reportf("===============================\n"); - reportf("| Conflicts | ORIGINAL | "); - reportf("LEARNT | Progress |\n"); - reportf("| | Clauses Literals | Clauses "); - reportf("Literals Lit/Cl | |\n"); - reportf("======================================="); - reportf("===============================\n"); - reportf("| %9d | %7d %8d | %7d %8d %7.1f | %6.3f %% |\n", - (int)stats.conflicts, nClauses(), (int)stats.clauses_literals, - nLearnts(), (int)stats.learnts_literals, - (double)stats.learnts_literals/nLearnts(), progress_estimate*100); - reportf("======================================="); - reportf("===============================\n"); -} diff --git a/src/sat/Solver.h b/src/sat/Solver.h deleted file mode 100644 index b5343760..00000000 --- a/src/sat/Solver.h +++ /dev/null @@ -1,219 +0,0 @@ -/****************************************************************************************[Solver.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Solver_h -#define Solver_h - -#include "SolverTypes.h" -#include "VarOrder.h" -#include "Proof.h" - -// Redfine if you want output to go somewhere else: -#define reportf(format, args...) ( printf(format , ## args), fflush(stdout) ) - - -//================================================================================================= -// Solver -- the main class: - - -struct SolverStats { - int64 starts, decisions, propagations, conflicts; - int64 clauses_literals, learnts_literals, max_literals, tot_literals; - SolverStats() : starts(0), decisions(0), propagations(0), conflicts(0) - , clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0) { } -}; - - -struct SearchParams { - double var_decay, clause_decay, random_var_freq; // (reasonable values are: 0.95, 0.999, 0.02) - SearchParams(double v = 1, double c = 1, double r = 0) : var_decay(v), clause_decay(c), random_var_freq(r) { } -}; - - -class Solver { -protected: - // Solver state: - // - bool ok; // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used! - vec clauses; // List of problem clauses. - vec learnts; // List of learnt clauses. - vec unit_id; // 'unit_id[var]' is the clause ID for the unit literal 'var' or '~var' (if set at toplevel). - double cla_inc; // Amount to bump next clause with. - double cla_decay; // INVERSE decay factor for clause activity: stores 1/decay. - - vec activity; // A heuristic measurement of the activity of a variable. - double var_inc; // Amount to bump next variable with. - double var_decay; // INVERSE decay factor for variable activity: stores 1/decay. Use negative value for static variable order. - VarOrder order; // Keeps track of the decision variable order. - - vec > watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true). - vec assigns; // The current assignments (lbool:s stored as char:s). - vec trail; // Assignment stack; stores all assigments made in the order they were made. - vec trail_lim; // Separator indices for different decision levels in 'trail[]'. - vec reason; // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none. - vec level; // 'level[var]' is the decision level at which assignment was made. - vec trail_pos; // 'trail_pos[var]' is the variable's position in 'trail[]'. This supersedes 'level[]' in some sense, and 'level[]' will probably be removed in future releases. - int root_level; // Level of first proper decision. - int qhead; // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat). - int simpDB_assigns; // Number of top-level assignments since last execution of 'simplifyDB()'. - int64 simpDB_props; // Remaining number of propagations that must be made before next execution of 'simplifyDB()'. - - // Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which is used: - // - vec analyze_seen; - vec analyze_stack; - vec analyze_toclear; - Clause* propagate_tmpbin; - Clause* analyze_tmpbin; - vec addUnit_tmp; - vec addBinary_tmp; - vec addTernary_tmp; - - // Main internal methods: - // - bool assume (Lit p); - void cancelUntil (int level); - void record (const vec& clause); - - void analyze (Clause* confl, vec& out_learnt, int& out_btlevel); // (bt = backtrack) - bool analyze_removable(Lit p, uint min_level); // (helper method for 'analyze()') - void analyzeFinal (Clause* confl, bool skip_first = false); - bool enqueue (Lit fact, Clause* from = NULL); - Clause* propagate (); - void reduceDB (); - Lit pickBranchLit (const SearchParams& params); - lbool search (int nof_conflicts, int nof_learnts, const SearchParams& params); - double progressEstimate (); - - // Activity: - // - void varBumpActivity(Lit p) { - if (var_decay < 0) return; // (negative decay means static variable order -- don't bump) - if ( (activity[var(p)] += var_inc) > 1e100 ) varRescaleActivity(); - order.update(var(p)); } - void varDecayActivity () { if (var_decay >= 0) var_inc *= var_decay; } - void varRescaleActivity(); - void claDecayActivity () { cla_inc *= cla_decay; } - void claRescaleActivity(); - - // Operations on clauses: - // - void newClause(const vec& ps, bool learnt = false, ClauseId id = ClauseId_NULL, bool A = true); - void claBumpActivity (Clause* c) { if ( (c->activity() += cla_inc) > 1e20 ) claRescaleActivity(); } - void remove (Clause* c, bool just_dealloc = false); - bool locked (const Clause* c) const { return reason[var((*c)[0])] == c; } - bool simplify (Clause* c) const; - - int decisionLevel() const { return trail_lim.size(); } - -public: - Solver() : ok (true) - , cla_inc (1) - , cla_decay (1) - , var_inc (1) - , var_decay (1) - , order (assigns, activity) - , qhead (0) - , simpDB_assigns (0) - , simpDB_props (0) - , default_params (SearchParams(0.95, 0.999, 0.02)) - , expensive_ccmin (2) - , proof (NULL) - , verbosity (0) - , progress_estimate(0) - , conflict_id (ClauseId_NULL) - { - vec dummy(2,lit_Undef); - propagate_tmpbin = Clause_new(false, dummy); - analyze_tmpbin = Clause_new(false, dummy); - addUnit_tmp .growTo(1); - addBinary_tmp .growTo(2); - addTernary_tmp.growTo(3); - } - - ~Solver() { - for (int i = 0; i < learnts.size(); i++) remove(learnts[i], true); - for (int i = 0; i < clauses.size(); i++) if (clauses[i] != NULL) remove(clauses[i], true); - remove(propagate_tmpbin, true); - remove(analyze_tmpbin, true); - } - - // Helpers: (semi-internal) - // - lbool value(Var x) const { return toLbool(assigns[x]); } - lbool value(Lit p) const { return sign(p) ? ~toLbool(assigns[var(p)]) : toLbool(assigns[var(p)]); } - lbool modelValue(Var x) const { return model[x]; } -// lbool modelValue(Lit p) const { return model[var(p)] ^ sign(p); } - - int nAssigns() { return trail.size(); } - int nClauses() { return clauses.size(); } - int nLearnts() { return learnts.size(); } - - // Statistics: (read-only member variable) - // - SolverStats stats; - - // Mode of operation: - // - SearchParams default_params; // Restart frequency etc. - int expensive_ccmin; // Controls conflict clause minimization. TRUE by default. - Proof* proof; // Set this directly after constructing 'Solver' to enable proof logging. Initialized to NULL. - int verbosity; // Verbosity level. 0=silent, 1=some progress report, 2=everything - - // Problem specification: - // - Var newVar (); - int nVars () { return assigns.size(); } - void addUnit (Lit p) { addUnit_tmp [0] = p; addClause(addUnit_tmp); } - void addBinary (Lit p, Lit q) { addBinary_tmp [0] = p; addBinary_tmp [1] = q; addClause(addBinary_tmp); } - void addTernary(Lit p, Lit q, Lit r) { addTernary_tmp[0] = p; addTernary_tmp[1] = q; addTernary_tmp[2] = r; addClause(addTernary_tmp); } - void addClause (const vec& ps , bool A = true) { newClause(ps , false , ClauseId_NULL , A); } - // (used to be a difference between internal and external method...) - - // Solving: - // - bool okay() { return ok; } // FALSE means solver is in an conflicting state (must never be used again!) - void simplifyDB(); - lbool solve(const vec& assumps); - lbool solve() { vec tmp; return solve(tmp); } - - double progress_estimate; // Set by 'search()'. - vec model; // If problem is satisfiable, this vector contains the model (if any). - vec conflict; // If problem is unsatisfiable under assumptions, this vector represent the conflict clause expressed in the assumptions. - ClauseId conflict_id; // (In proof logging mode only.) ID for the clause 'conflict' (for proof traverseral). NOTE! The empty clause is always the last clause derived, but for conflicts under assumption, this is not necessarly true. - - // Printing: - // - void printStats(); -}; - - -//================================================================================================= -// Debug: - - -#define L_LIT "%s%d" -#define L_lit(p) sign(p)?"-":"", var(p)+1 - -// Just like 'assert()' but expression will be evaluated in the release version as well. -inline void check(bool expr) { assert(expr); } - - -//================================================================================================= -#endif diff --git a/src/sat/SolverTypes.h b/src/sat/SolverTypes.h deleted file mode 100644 index 74df73a8..00000000 --- a/src/sat/SolverTypes.h +++ /dev/null @@ -1,141 +0,0 @@ -/***********************************************************************************[SolverTypes.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - - -#ifndef SolverTypes_h -#define SolverTypes_h - -#ifndef Global_h -#include "Global.h" -#endif - - -//================================================================================================= -// Variables, literals, clause IDs: - - -// NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N, -// so that they can be used as array indices. - -typedef int Var; -#define var_Undef (-1) - - -class Lit { - int x; -public: - Lit() : x(2*var_Undef) {} // (lit_Undef) - explicit Lit(Var var, bool sgn = false) : x((var+var) + (int)sgn) {} - friend Lit operator ~ (Lit p); - - friend bool sign (Lit p); - friend int var (Lit p); - friend int index (Lit p); - friend Lit toLit (int i); - friend Lit unsign(Lit p); - friend Lit id (Lit p, bool sgn); - - friend bool operator == (Lit p, Lit q); - friend bool operator < (Lit p, Lit q); - - uint hash() const { return (uint)x; } -}; -inline Lit operator ~ (Lit p) { Lit q; q.x = p.x ^ 1; return q; } -inline bool sign (Lit p) { return p.x & 1; } -inline int var (Lit p) { return p.x >> 1; } -inline int index (Lit p) { return p.x; } // A "toInt" method that guarantees small, positive integers suitable for array indexing. -inline Lit toLit (int i) { Lit p; p.x = i; return p; } // Inverse of 'index()'. -inline Lit unsign(Lit p) { Lit q; q.x = p.x & ~1; return q; } -inline Lit id (Lit p, bool sgn) { Lit q; q.x = p.x ^ (int)sgn; return q; } -inline bool operator == (Lit p, Lit q) { return index(p) == index(q); } -inline bool operator < (Lit p, Lit q) { return index(p) < index(q); } // '<' guarantees that p, ~p are adjacent in the ordering. - -const Lit lit_Undef(var_Undef, false); // }- Useful special constants. -const Lit lit_Error(var_Undef, true ); // } - -inline int toDimacs(Lit p) { return sign(p) ? -var(p) - 1 : var(p) + 1; } - - -//================================================================================================= -// Clause -- a simple class for representing a clause: - - -typedef int ClauseId; // (might have to use uint64 one day...) -const int ClauseId_NULL = INT_MIN; - -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -class Clause { - uint size_learnt; - Lit data[1]; -public: - // NOTE: This constructor cannot be used directly (doesn't allocate enough memory). - Clause(bool learnt, const vec& ps, ClauseId id_ = ClauseId_NULL) { - size_learnt = (ps.size() << 1) | (int)learnt; - for (int i = 0; i < ps.size(); i++) data[i] = ps[i]; - if (learnt) activity() = 0; - if (id_ != ClauseId_NULL) id() = id_; } - - // -- use this function instead: - friend Clause* Clause_new(bool, const vec&, ClauseId); - - int size () const { return size_learnt >> 1; } - bool learnt () const { return size_learnt & 1; } - Lit operator [] (int i) const { return data[i]; } - Lit& operator [] (int i) { return data[i]; } - float& activity () const { - void *p = const_cast(&data[size()]); return *((float *)p); - } // return *((float*)&data[size()]); } - ClauseId& id () const { return *((ClauseId*)&data[size() + (int)learnt()]); } -}; - -inline Clause* Clause_new(bool learnt, const vec& ps, ClauseId id = ClauseId_NULL) { - assert(sizeof(Lit) == sizeof(uint)); - assert(sizeof(float) == sizeof(uint)); - assert(sizeof(ClauseId) == sizeof(uint)); - void* mem = xmalloc(sizeof(Clause) + sizeof(uint)*(ps.size() + (int)learnt + (int)(id != ClauseId_NULL))); - return new (mem) Clause(learnt, ps, id); } - - -//================================================================================================= -// GClause -- Generalize clause: - - -// Either a pointer to a clause or a literal. -class GClause { - void* data; - GClause(void* d) : data(d) {} -public: - friend GClause GClause_new(Lit p); - friend GClause GClause_new(Clause* c); - - bool isLit () const { return ((uintp)data & 1) == 1; } - Lit lit () const { return toLit(((intp)data) >> 1); } - Clause* clause () const { return (Clause*)data; } - bool operator == (GClause c) const { return data == c.data; } - bool operator != (GClause c) const { return data != c.data; } -}; -inline GClause GClause_new(Lit p) { return GClause((void*)(((intp)index(p) << 1) + 1)); } -inline GClause GClause_new(Clause* c) { assert(((uintp)c & 1) == 0); return GClause((void*)c); } - -#define GClause_NULL GClause_new((Clause*)NULL) - - -//================================================================================================= -#endif diff --git a/src/sat/Sort.h b/src/sat/Sort.h deleted file mode 100644 index e4191cc7..00000000 --- a/src/sat/Sort.h +++ /dev/null @@ -1,131 +0,0 @@ -/******************************************************************************************[Sort.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Sort_h -#define Sort_h - - -//================================================================================================= - - -template -struct LessThan_default { - bool operator () (T x, T y) { return x < y; } -}; - - -//================================================================================================= - - -template -void selectionSort(T* array, int size, LessThan lt) -{ - int i, j, best_i; - T tmp; - - for (i = 0; i < size-1; i++){ - best_i = i; - for (j = i+1; j < size; j++){ - if (lt(array[j], array[best_i])) - best_i = j; - } - tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; - } -} -template static inline void selectionSort(T* array, int size) { - selectionSort(array, size, LessThan_default()); } - - -template -void sort(T* array, int size, LessThan lt, double& seed) -{ - if (size <= 15) - selectionSort(array, size, lt); - - else{ - T pivot = array[irand(seed, size)]; - T tmp; - int i = -1; - int j = size; - - for(;;){ - do i++; while(lt(array[i], pivot)); - do j--; while(lt(pivot, array[j])); - - if (i >= j) break; - - tmp = array[i]; array[i] = array[j]; array[j] = tmp; - } - - sort(array , i , lt, seed); - sort(&array[i], size-i, lt, seed); - } -} -template void sort(T* array, int size, LessThan lt) { - double seed = 91648253; sort(array, size, lt, seed); } -template static inline void sort(T* array, int size) { - sort(array, size, LessThan_default()); } - - -template -void sortUnique(T* array, int& size, LessThan lt) -{ - int i, j; - T last; - - if (size == 0) return; - - sort(array, size, lt); - - i = 1; - last = array[0]; - for (j = 1; j < size; j++){ - if (lt(last, array[j])){ - last = array[i] = array[j]; - i++; } - } - - size = i; -} -template static inline void sortUnique(T* array, int& size) { - sortUnique(array, size, LessThan_default()); } - - -//================================================================================================= -// For 'vec's: - - -template void sort(vec& v, LessThan lt) { - sort((T*)v, v.size(), lt); } -template void sort(vec& v) { - sort(v, LessThan_default()); } - - -template void sortUnique(vec& v, LessThan lt) { - int size = v.size(); - T* data = v.release(); - sortUnique(data, size, lt); - v.~vec(); - new (&v) vec(data, size); } -template void sortUnique(vec& v) { - sortUnique(v, LessThan_default()); } - - -//================================================================================================= -#endif diff --git a/src/sat/VarOrder.h b/src/sat/VarOrder.h deleted file mode 100644 index ad6c77ce..00000000 --- a/src/sat/VarOrder.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************************[VarOrder.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef VarOrder_h -#define VarOrder_h - -#include "SolverTypes.h" -#include "Heap.h" - - -//================================================================================================= - - -struct VarOrder_lt { - const vec& activity; - bool operator () (Var x, Var y) { return activity[x] > activity[y]; } - VarOrder_lt(const vec& act) : activity(act) { } -}; - -class VarOrder { - const vec& assigns; // var->val. Pointer to external assignment table. -// const vec& activity; // var->act. Pointer to external activity table. - Heap heap; - double random_seed; // For the internal random number generator - -public: - VarOrder(const vec& ass, const vec& act) : -// assigns(ass), activity(act), heap(VarOrder_lt(act)), random_seed(91648253) - assigns(ass), heap(VarOrder_lt(act)), random_seed(91648253) - { } - - inline void newVar(void); - inline void update(Var x); // Called when variable increased in activity. - inline void undo(Var x); // Called when variable is unassigned and may be selected again. - inline Var select(double random_freq =.0); // Selects a new, unassigned variable (or 'var_Undef' if none exists). -}; - - -void VarOrder::newVar(void) -{ - heap.setBounds(assigns.size()); - heap.insert(assigns.size()-1); -} - - -void VarOrder::update(Var x) -{ - if (heap.inHeap(x)) - heap.increase(x); -} - - -void VarOrder::undo(Var x) -{ - if (!heap.inHeap(x)) - heap.insert(x); -} - - -Var VarOrder::select(double random_var_freq) -{ - // Random decision: - if (drand(random_seed) < random_var_freq && !heap.empty()){ - Var next = irand(random_seed,assigns.size()); - if (toLbool(assigns[next]) == l_Undef) - return next; - } - - // Activity based decision: - while (!heap.empty()){ - Var next = heap.getmin(); - if (toLbool(assigns[next]) == l_Undef) - return next; - } - - return var_Undef; -} - - -//================================================================================================= -#endif diff --git a/src/sat/make.sat b/src/sat/make.sat deleted file mode 100644 index 756bc512..00000000 --- a/src/sat/make.sat +++ /dev/null @@ -1,7 +0,0 @@ -PKGFLAG = -EXTHDRS = sat.h Solver.h SolverTypes.h VarOrder.h Proof.h Global.h \ - File.h Heap.h Sort.h - - -include ../Makefile.in -include ../Makefile.lib diff --git a/src/sat/minisat/LICENSE b/src/sat/minisat/LICENSE deleted file mode 100644 index 22816ff3..00000000 --- a/src/sat/minisat/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson - Copyright (c) 2007-2010 Niklas Sorensson - -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. diff --git a/src/sat/minisat/README b/src/sat/minisat/README deleted file mode 100644 index e5e5617d..00000000 --- a/src/sat/minisat/README +++ /dev/null @@ -1,24 +0,0 @@ -================================================================================ -DIRECTORY OVERVIEW: - -mtl/ Mini Template Library -utils/ Generic helper code (I/O, Parsing, CPU-time, etc) -core/ A core version of the solver -simp/ An extended solver with simplification capabilities -README -LICENSE - -================================================================================ -BUILDING: (release version: without assertions, statically linked, etc) - -export MROOT= (or setenv in cshell) -cd { core | simp } -gmake rs -cp minisat_static /minisat - -================================================================================ -EXAMPLES: - -Run minisat with same heuristics as version 2.0: - -> minisat -no-luby -rinc=1.5 -phase-saving=0 -rnd-freq=0.02 diff --git a/src/sat/minisat/core/Dimacs.h b/src/sat/minisat/core/Dimacs.h deleted file mode 100644 index a05e900c..00000000 --- a/src/sat/minisat/core/Dimacs.h +++ /dev/null @@ -1,89 +0,0 @@ -/****************************************************************************************[Dimacs.h] -Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_Dimacs_h -#define Minisat_Dimacs_h - -#include - -#include "utils/ParseUtils.h" -#include "core/SolverTypes.h" - -namespace Minisat { - -//================================================================================================= -// DIMACS Parser: - -template -static void readClause(B& in, Solver& S, vec& lits) { - int parsed_lit, var; - lits.clear(); - for (;;){ - parsed_lit = parseInt(in); - if (parsed_lit == 0) break; - var = abs(parsed_lit)-1; - while (var >= S.nVars()) S.newVar(); - lits.push( (parsed_lit > 0) ? mkLit(var) : ~mkLit(var) ); - } -} - -template -static void parse_DIMACS_main(B& in, Solver& S) { - vec lits; - int vars = 0; - int clauses = 0; - int cnt = 0; - for (;;){ - skipWhitespace(in); - if (*in == EOF) break; - else if (*in == 'p'){ - if (eagerMatch(in, "p cnf")){ - vars = parseInt(in); - clauses = parseInt(in); - // SATRACE'06 hack - // if (clauses > 4000000) - // S.eliminate(true); - }else{ - printf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3); - } - } else if (*in == 'c' || *in == 'p') - skipLine(in); - else{ - cnt++; - readClause(in, S, lits); - S.addClause_(lits); } - } - if (vars != S.nVars()) - fprintf(stderr, "WARNING! DIMACS header mismatch: wrong number of variables.\n"); - if (cnt != clauses) - fprintf(stderr, "WARNING! DIMACS header mismatch: wrong number of clauses.\n"); -} - -// Inserts problem into solver. -// -template -static void parse_DIMACS(gzFile input_stream, Solver& S) { - StreamBuffer in(input_stream); - parse_DIMACS_main(in, S); } - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/core/Main.cc b/src/sat/minisat/core/Main.cc deleted file mode 100644 index 4388c3e0..00000000 --- a/src/sat/minisat/core/Main.cc +++ /dev/null @@ -1,192 +0,0 @@ -/*****************************************************************************************[Main.cc] -Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#include - -#include -#include - -#include "utils/System.h" -#include "utils/ParseUtils.h" -#include "utils/Options.h" -#include "core/Dimacs.h" -#include "core/Solver.h" - -using namespace Minisat; - -//================================================================================================= - - -void printStats(Solver& solver) -{ - double cpu_time = cpuTime(); - double mem_used = memUsedPeak(); - printf("restarts : %"PRIu64"\n", solver.starts); - printf("conflicts : %-12"PRIu64" (%.0f /sec)\n", solver.conflicts , solver.conflicts /cpu_time); - printf("decisions : %-12"PRIu64" (%4.2f %% random) (%.0f /sec)\n", solver.decisions, (float)solver.rnd_decisions*100 / (float)solver.decisions, solver.decisions /cpu_time); - printf("propagations : %-12"PRIu64" (%.0f /sec)\n", solver.propagations, solver.propagations/cpu_time); - printf("conflict literals : %-12"PRIu64" (%4.2f %% deleted)\n", solver.tot_literals, (solver.max_literals - solver.tot_literals)*100 / (double)solver.max_literals); - if (mem_used != 0) printf("Memory used : %.2f MB\n", mem_used); - printf("CPU time : %g s\n", cpu_time); -} - - -static Solver* solver; -// Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case -// for this feature of the Solver as it may take longer than an immediate call to '_exit()'. -static void SIGINT_interrupt(int signum) { solver->interrupt(); } - -// Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls -// destructors and may cause deadlocks if a malloc/free function happens to be running (these -// functions are guarded by locks for multithreaded use). -static void SIGINT_exit(int signum) { - printf("\n"); printf("*** INTERRUPTED ***\n"); - if (solver->verbosity > 0){ - printStats(*solver); - printf("\n"); printf("*** INTERRUPTED ***\n"); } - _exit(1); } - - -//================================================================================================= -// Main: - - -int main(int argc, char** argv) -{ - try { - setUsageHelp("USAGE: %s [options] \n\n where input may be either in plain or gzipped DIMACS.\n"); - // printf("This is MiniSat 2.0 beta\n"); - -#if defined(__linux__) - fpu_control_t oldcw, newcw; - _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw); - printf("WARNING: for repeatability, setting FPU to use double precision\n"); -#endif - // Extra options: - // - IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2)); - IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", INT32_MAX, IntRange(0, INT32_MAX)); - IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", INT32_MAX, IntRange(0, INT32_MAX)); - - parseOptions(argc, argv, true); - - Solver S; - double initial_time = cpuTime(); - - S.verbosity = verb; - - solver = &S; - // Use signal handlers that forcibly quit until the solver will be able to respond to - // interrupts: - signal(SIGINT, SIGINT_exit); - signal(SIGXCPU,SIGINT_exit); - - // Set limit on CPU-time: - if (cpu_lim != INT32_MAX){ - rlimit rl; - getrlimit(RLIMIT_CPU, &rl); - if (rl.rlim_max == RLIM_INFINITY || (rlim_t)cpu_lim < rl.rlim_max){ - rl.rlim_cur = cpu_lim; - if (setrlimit(RLIMIT_CPU, &rl) == -1) - printf("WARNING! Could not set resource limit: CPU-time.\n"); - } } - - // Set limit on virtual memory: - if (mem_lim != INT32_MAX){ - rlim_t new_mem_lim = (rlim_t)mem_lim * 1024*1024; - rlimit rl; - getrlimit(RLIMIT_AS, &rl); - if (rl.rlim_max == RLIM_INFINITY || new_mem_lim < rl.rlim_max){ - rl.rlim_cur = new_mem_lim; - if (setrlimit(RLIMIT_AS, &rl) == -1) - printf("WARNING! Could not set resource limit: Virtual memory.\n"); - } } - - if (argc == 1) - printf("Reading from standard input... Use '--help' for help.\n"); - - gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb"); - if (in == NULL) - printf("ERROR! Could not open file: %s\n", argc == 1 ? "" : argv[1]), exit(1); - - if (S.verbosity > 0){ - printf("============================[ Problem Statistics ]=============================\n"); - printf("| |\n"); } - - parse_DIMACS(in, S); - gzclose(in); - FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL; - - if (S.verbosity > 0){ - printf("| Number of variables: %12d |\n", S.nVars()); - printf("| Number of clauses: %12d |\n", S.nClauses()); } - - double parsed_time = cpuTime(); - if (S.verbosity > 0){ - printf("| Parse time: %12.2f s |\n", parsed_time - initial_time); - printf("| |\n"); } - - // Change to signal-handlers that will only notify the solver and allow it to terminate - // voluntarily: - signal(SIGINT, SIGINT_interrupt); - signal(SIGXCPU,SIGINT_interrupt); - - if (!S.simplify()){ - if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res); - if (S.verbosity > 0){ - printf("===============================================================================\n"); - printf("Solved by unit propagation\n"); - printStats(S); - printf("\n"); } - printf("UNSATISFIABLE\n"); - exit(20); - } - - vec dummy; - lbool ret = S.solveLimited(dummy); - if (S.verbosity > 0){ - printStats(S); - printf("\n"); } - printf(ret == l_True ? "SATISFIABLE\n" : ret == l_False ? "UNSATISFIABLE\n" : "INDETERMINATE\n"); - if (res != NULL){ - if (ret == l_True){ - fprintf(res, "SAT\n"); - for (int i = 0; i < S.nVars(); i++) - if (S.model[i] != l_Undef) - fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1); - fprintf(res, " 0\n"); - }else if (ret == l_False) - fprintf(res, "UNSAT\n"); - else - fprintf(res, "INDET\n"); - fclose(res); - } - -#ifdef NDEBUG - exit(ret == l_True ? 10 : ret == l_False ? 20 : 0); // (faster than "return", which will invoke the destructor for 'Solver') -#else - return (ret == l_True ? 10 : ret == l_False ? 20 : 0); -#endif - } catch (OutOfMemoryException&){ - printf("===============================================================================\n"); - printf("INDETERMINATE\n"); - exit(0); - } -} diff --git a/src/sat/minisat/core/Main.or b/src/sat/minisat/core/Main.or deleted file mode 100644 index e586ee8396421cfbeb2835ccc192775bc595a024..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 98728 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 diff --git a/src/sat/minisat/core/Makefile b/src/sat/minisat/core/Makefile deleted file mode 100644 index 5de1f729..00000000 --- a/src/sat/minisat/core/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -EXEC = minisat -DEPDIR = mtl utils - -include $(MROOT)/mtl/template.mk diff --git a/src/sat/minisat/core/Solver.cc b/src/sat/minisat/core/Solver.cc deleted file mode 100644 index 7da7f189..00000000 --- a/src/sat/minisat/core/Solver.cc +++ /dev/null @@ -1,923 +0,0 @@ -/***************************************************************************************[Solver.cc] -Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#include - -#include "mtl/Sort.h" -#include "core/Solver.h" - -using namespace Minisat; - -//================================================================================================= -// Options: - - -static const char* _cat = "CORE"; - -static DoubleOption opt_var_decay (_cat, "var-decay", "The variable activity decay factor", 0.95, DoubleRange(0, false, 1, false)); -static DoubleOption opt_clause_decay (_cat, "cla-decay", "The clause activity decay factor", 0.999, DoubleRange(0, false, 1, false)); -static DoubleOption opt_random_var_freq (_cat, "rnd-freq", "The frequency with which the decision heuristic tries to choose a random variable", 0, DoubleRange(0, true, 1, true)); -static DoubleOption opt_random_seed (_cat, "rnd-seed", "Used by the random variable selection", 91648253, DoubleRange(0, false, HUGE_VAL, false)); -static IntOption opt_ccmin_mode (_cat, "ccmin-mode", "Controls conflict clause minimization (0=none, 1=basic, 2=deep)", 2, IntRange(0, 2)); -static IntOption opt_phase_saving (_cat, "phase-saving", "Controls the level of phase saving (0=none, 1=limited, 2=full)", 2, IntRange(0, 2)); -static BoolOption opt_rnd_init_act (_cat, "rnd-init", "Randomize the initial activity", false); -static BoolOption opt_luby_restart (_cat, "luby", "Use the Luby restart sequence", true); -static IntOption opt_restart_first (_cat, "rfirst", "The base restart interval", 100, IntRange(1, INT32_MAX)); -static DoubleOption opt_restart_inc (_cat, "rinc", "Restart interval increase factor", 2, DoubleRange(1, false, HUGE_VAL, false)); -static DoubleOption opt_garbage_frac (_cat, "gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered", 0.20, DoubleRange(0, false, HUGE_VAL, false)); - - -//================================================================================================= -// Constructor/Destructor: - - -Solver::Solver() : - - // Parameters (user settable): - // - verbosity (0) - , var_decay (opt_var_decay) - , clause_decay (opt_clause_decay) - , random_var_freq (opt_random_var_freq) - , random_seed (opt_random_seed) - , luby_restart (opt_luby_restart) - , ccmin_mode (opt_ccmin_mode) - , phase_saving (opt_phase_saving) - , rnd_pol (false) - , rnd_init_act (opt_rnd_init_act) - , garbage_frac (opt_garbage_frac) - , restart_first (opt_restart_first) - , restart_inc (opt_restart_inc) - - // Parameters (the rest): - // - , learntsize_factor((double)1/(double)3), learntsize_inc(1.1) - - // Parameters (experimental): - // - , learntsize_adjust_start_confl (100) - , learntsize_adjust_inc (1.5) - - // Statistics: (formerly in 'SolverStats') - // - , solves(0), starts(0), decisions(0), rnd_decisions(0), propagations(0), conflicts(0) - , dec_vars(0), clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0) - - , ok (true) - , cla_inc (1) - , var_inc (1) - , watches (WatcherDeleted(ca)) - , qhead (0) - , simpDB_assigns (-1) - , simpDB_props (0) - , order_heap (VarOrderLt(activity)) - , progress_estimate (0) - , remove_satisfied (true) - - // Resource constraints: - // - , conflict_budget (-1) - , propagation_budget (-1) - , asynch_interrupt (false) -{} - - -Solver::~Solver() -{ -} - - -//================================================================================================= -// Minor methods: - - -// Creates a new SAT variable in the solver. If 'decision' is cleared, variable will not be -// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result). -// -Var Solver::newVar(bool sign, bool dvar) -{ - int v = nVars(); - watches .init(mkLit(v, false)); - watches .init(mkLit(v, true )); - assigns .push(l_Undef); - vardata .push(mkVarData(CRef_Undef, 0)); - //activity .push(0); - activity .push(rnd_init_act ? drand(random_seed) * 0.00001 : 0); - seen .push(0); - polarity .push(sign); - decision .push(); - trail .capacity(v+1); - setDecisionVar(v, dvar); - return v; -} - - -bool Solver::addClause_(vec& ps) -{ - assert(decisionLevel() == 0); - if (!ok) return false; - - // Check if clause is satisfied and remove false/duplicate literals: - sort(ps); - Lit p; int i, j; - for (i = j = 0, p = lit_Undef; i < ps.size(); i++) - if (value(ps[i]) == l_True || ps[i] == ~p) - return true; - else if (value(ps[i]) != l_False && ps[i] != p) - ps[j++] = p = ps[i]; - ps.shrink(i - j); - - if (ps.size() == 0) - return ok = false; - else if (ps.size() == 1){ - uncheckedEnqueue(ps[0]); - return ok = (propagate() == CRef_Undef); - }else{ - CRef cr = ca.alloc(ps, false); - clauses.push(cr); - attachClause(cr); - } - - return true; -} - - -void Solver::attachClause(CRef cr) { - const Clause& c = ca[cr]; - assert(c.size() > 1); - watches[~c[0]].push(Watcher(cr, c[1])); - watches[~c[1]].push(Watcher(cr, c[0])); - if (c.learnt()) learnts_literals += c.size(); - else clauses_literals += c.size(); } - - -void Solver::detachClause(CRef cr, bool strict) { - const Clause& c = ca[cr]; - assert(c.size() > 1); - - if (strict){ - remove(watches[~c[0]], Watcher(cr, c[1])); - remove(watches[~c[1]], Watcher(cr, c[0])); - }else{ - // Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause) - watches.smudge(~c[0]); - watches.smudge(~c[1]); - } - - if (c.learnt()) learnts_literals -= c.size(); - else clauses_literals -= c.size(); } - - -void Solver::removeClause(CRef cr) { - Clause& c = ca[cr]; - detachClause(cr); - // Don't leave pointers to free'd memory! - if (locked(c)) vardata[var(c[0])].reason = CRef_Undef; - c.mark(1); - ca.free(cr); -} - - -bool Solver::satisfied(const Clause& c) const { - for (int i = 0; i < c.size(); i++) - if (value(c[i]) == l_True) - return true; - return false; } - - -// Revert to the state at given level (keeping all assignment at 'level' but not beyond). -// -void Solver::cancelUntil(int level) { - if (decisionLevel() > level){ - for (int c = trail.size()-1; c >= trail_lim[level]; c--){ - Var x = var(trail[c]); - assigns [x] = l_Undef; - if (phase_saving > 1 || (phase_saving == 1) && c > trail_lim.last()) - polarity[x] = sign(trail[c]); - insertVarOrder(x); } - qhead = trail_lim[level]; - trail.shrink(trail.size() - trail_lim[level]); - trail_lim.shrink(trail_lim.size() - level); - } } - - -//================================================================================================= -// Major methods: - - -Lit Solver::pickBranchLit() -{ - Var next = var_Undef; - - // Random decision: - if (drand(random_seed) < random_var_freq && !order_heap.empty()){ - next = order_heap[irand(random_seed,order_heap.size())]; - if (value(next) == l_Undef && decision[next]) - rnd_decisions++; } - - // Activity based decision: - while (next == var_Undef || value(next) != l_Undef || !decision[next]) - if (order_heap.empty()){ - next = var_Undef; - break; - }else - next = order_heap.removeMin(); - - return next == var_Undef ? lit_Undef : mkLit(next, rnd_pol ? drand(random_seed) < 0.5 : polarity[next]); -} - - -/*_________________________________________________________________________________________________ -| -| analyze : (confl : Clause*) (out_learnt : vec&) (out_btlevel : int&) -> [void] -| -| Description: -| Analyze conflict and produce a reason clause. -| -| Pre-conditions: -| * 'out_learnt' is assumed to be cleared. -| * Current decision level must be greater than root level. -| -| Post-conditions: -| * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'. -| * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the -| rest of literals. There may be others from the same level though. -| -|________________________________________________________________________________________________@*/ -void Solver::analyze(CRef confl, vec& out_learnt, int& out_btlevel) -{ - int pathC = 0; - Lit p = lit_Undef; - - // Generate conflict clause: - // - out_learnt.push(); // (leave room for the asserting literal) - int index = trail.size() - 1; - - do{ - assert(confl != CRef_Undef); // (otherwise should be UIP) - Clause& c = ca[confl]; - - if (c.learnt()) - claBumpActivity(c); - - for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){ - Lit q = c[j]; - - if (!seen[var(q)] && level(var(q)) > 0){ - varBumpActivity(var(q)); - seen[var(q)] = 1; - if (level(var(q)) >= decisionLevel()) - pathC++; - else - out_learnt.push(q); - } - } - - // Select next clause to look at: - while (!seen[var(trail[index--])]); - p = trail[index+1]; - confl = reason(var(p)); - seen[var(p)] = 0; - pathC--; - - }while (pathC > 0); - out_learnt[0] = ~p; - - // Simplify conflict clause: - // - int i, j; - out_learnt.copyTo(analyze_toclear); - if (ccmin_mode == 2){ - uint32_t abstract_level = 0; - for (i = 1; i < out_learnt.size(); i++) - abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict) - - for (i = j = 1; i < out_learnt.size(); i++) - if (reason(var(out_learnt[i])) == CRef_Undef || !litRedundant(out_learnt[i], abstract_level)) - out_learnt[j++] = out_learnt[i]; - - }else if (ccmin_mode == 1){ - for (i = j = 1; i < out_learnt.size(); i++){ - Var x = var(out_learnt[i]); - - if (reason(x) == CRef_Undef) - out_learnt[j++] = out_learnt[i]; - else{ - Clause& c = ca[reason(var(out_learnt[i]))]; - for (int k = 1; k < c.size(); k++) - if (!seen[var(c[k])] && level(var(c[k])) > 0){ - out_learnt[j++] = out_learnt[i]; - break; } - } - } - }else - i = j = out_learnt.size(); - - max_literals += out_learnt.size(); - out_learnt.shrink(i - j); - tot_literals += out_learnt.size(); - - // Find correct backtrack level: - // - if (out_learnt.size() == 1) - out_btlevel = 0; - else{ - int max_i = 1; - // Find the first literal assigned at the next-highest level: - for (int i = 2; i < out_learnt.size(); i++) - if (level(var(out_learnt[i])) > level(var(out_learnt[max_i]))) - max_i = i; - // Swap-in this literal at index 1: - Lit p = out_learnt[max_i]; - out_learnt[max_i] = out_learnt[1]; - out_learnt[1] = p; - out_btlevel = level(var(p)); - } - - for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared) -} - - -// Check if 'p' can be removed. 'abstract_levels' is used to abort early if the algorithm is -// visiting literals at levels that cannot be removed later. -bool Solver::litRedundant(Lit p, uint32_t abstract_levels) -{ - analyze_stack.clear(); analyze_stack.push(p); - int top = analyze_toclear.size(); - while (analyze_stack.size() > 0){ - assert(reason(var(analyze_stack.last())) != CRef_Undef); - Clause& c = ca[reason(var(analyze_stack.last()))]; analyze_stack.pop(); - - for (int i = 1; i < c.size(); i++){ - Lit p = c[i]; - if (!seen[var(p)] && level(var(p)) > 0){ - if (reason(var(p)) != CRef_Undef && (abstractLevel(var(p)) & abstract_levels) != 0){ - seen[var(p)] = 1; - analyze_stack.push(p); - analyze_toclear.push(p); - }else{ - for (int j = top; j < analyze_toclear.size(); j++) - seen[var(analyze_toclear[j])] = 0; - analyze_toclear.shrink(analyze_toclear.size() - top); - return false; - } - } - } - } - - return true; -} - - -/*_________________________________________________________________________________________________ -| -| analyzeFinal : (p : Lit) -> [void] -| -| Description: -| Specialized analysis procedure to express the final conflict in terms of assumptions. -| Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and -| stores the result in 'out_conflict'. -|________________________________________________________________________________________________@*/ -void Solver::analyzeFinal(Lit p, vec& out_conflict) -{ - out_conflict.clear(); - out_conflict.push(p); - - if (decisionLevel() == 0) - return; - - seen[var(p)] = 1; - - for (int i = trail.size()-1; i >= trail_lim[0]; i--){ - Var x = var(trail[i]); - if (seen[x]){ - if (reason(x) == CRef_Undef){ - assert(level(x) > 0); - out_conflict.push(~trail[i]); - }else{ - Clause& c = ca[reason(x)]; - for (int j = 1; j < c.size(); j++) - if (level(var(c[j])) > 0) - seen[var(c[j])] = 1; - } - seen[x] = 0; - } - } - - seen[var(p)] = 0; -} - - -void Solver::uncheckedEnqueue(Lit p, CRef from) -{ - assert(value(p) == l_Undef); - assigns[var(p)] = lbool(!sign(p)); - vardata[var(p)] = mkVarData(from, decisionLevel()); - trail.push_(p); -} - - -/*_________________________________________________________________________________________________ -| -| propagate : [void] -> [Clause*] -| -| Description: -| Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned, -| otherwise CRef_Undef. -| -| Post-conditions: -| * the propagation queue is empty, even if there was a conflict. -|________________________________________________________________________________________________@*/ -CRef Solver::propagate() -{ - CRef confl = CRef_Undef; - int num_props = 0; - watches.cleanAll(); - - while (qhead < trail.size()){ - Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. - vec& ws = watches[p]; - Watcher *i, *j, *end; - num_props++; - - for (i = j = (Watcher*)ws, end = i + ws.size(); i != end;){ - // Try to avoid inspecting the clause: - Lit blocker = i->blocker; - if (value(blocker) == l_True){ - *j++ = *i++; continue; } - - // Make sure the false literal is data[1]: - CRef cr = i->cref; - Clause& c = ca[cr]; - Lit false_lit = ~p; - if (c[0] == false_lit) - c[0] = c[1], c[1] = false_lit; - assert(c[1] == false_lit); - i++; - - // If 0th watch is true, then clause is already satisfied. - Lit first = c[0]; - Watcher w = Watcher(cr, first); - if (first != blocker && value(first) == l_True){ - *j++ = w; continue; } - - // Look for new watch: - for (int k = 2; k < c.size(); k++) - if (value(c[k]) != l_False){ - c[1] = c[k]; c[k] = false_lit; - watches[~c[1]].push(w); - goto NextClause; } - - // Did not find watch -- clause is unit under assignment: - *j++ = w; - if (value(first) == l_False){ - confl = cr; - qhead = trail.size(); - // Copy the remaining watches: - while (i < end) - *j++ = *i++; - }else - uncheckedEnqueue(first, cr); - - NextClause:; - } - ws.shrink(i - j); - } - propagations += num_props; - simpDB_props -= num_props; - - return confl; -} - - -/*_________________________________________________________________________________________________ -| -| reduceDB : () -> [void] -| -| Description: -| Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked -| clauses are clauses that are reason to some assignment. Binary clauses are never removed. -|________________________________________________________________________________________________@*/ -struct reduceDB_lt { - ClauseAllocator& ca; - reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {} - bool operator () (CRef x, CRef y) { - return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); } -}; -void Solver::reduceDB() -{ - int i, j; - double extra_lim = cla_inc / learnts.size(); // Remove any clause below this activity - - sort(learnts, reduceDB_lt(ca)); - // Don't delete binary or locked clauses. From the rest, delete clauses from the first half - // and clauses with activity smaller than 'extra_lim': - for (i = j = 0; i < learnts.size(); i++){ - Clause& c = ca[learnts[i]]; - if (c.size() > 2 && !locked(c) && (i < learnts.size() / 2 || c.activity() < extra_lim)) - removeClause(learnts[i]); - else - learnts[j++] = learnts[i]; - } - learnts.shrink(i - j); - checkGarbage(); -} - - -void Solver::removeSatisfied(vec& cs) -{ - int i, j; - for (i = j = 0; i < cs.size(); i++){ - Clause& c = ca[cs[i]]; - if (satisfied(c)) - removeClause(cs[i]); - else - cs[j++] = cs[i]; - } - cs.shrink(i - j); -} - - -void Solver::rebuildOrderHeap() -{ - vec vs; - for (Var v = 0; v < nVars(); v++) - if (decision[v] && value(v) == l_Undef) - vs.push(v); - order_heap.build(vs); -} - - -/*_________________________________________________________________________________________________ -| -| simplify : [void] -> [bool] -| -| Description: -| Simplify the clause database according to the current top-level assigment. Currently, the only -| thing done here is the removal of satisfied clauses, but more things can be put here. -|________________________________________________________________________________________________@*/ -bool Solver::simplify() -{ - assert(decisionLevel() == 0); - - if (!ok || propagate() != CRef_Undef) - return ok = false; - - if (nAssigns() == simpDB_assigns || (simpDB_props > 0)) - return true; - - // Remove satisfied clauses: - removeSatisfied(learnts); - if (remove_satisfied) // Can be turned off. - removeSatisfied(clauses); - checkGarbage(); - rebuildOrderHeap(); - - simpDB_assigns = nAssigns(); - simpDB_props = clauses_literals + learnts_literals; // (shouldn't depend on stats really, but it will do for now) - - return true; -} - - -/*_________________________________________________________________________________________________ -| -| search : (nof_conflicts : int) (params : const SearchParams&) -> [lbool] -| -| Description: -| Search for a model the specified number of conflicts. -| NOTE! Use negative value for 'nof_conflicts' indicate infinity. -| -| Output: -| 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If -| all variables are decision variables, this means that the clause set is satisfiable. 'l_False' -| if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached. -|________________________________________________________________________________________________@*/ -lbool Solver::search(int nof_conflicts) -{ - assert(ok); - int backtrack_level; - int conflictC = 0; - vec learnt_clause; - starts++; - - for (;;){ - CRef confl = propagate(); - if (confl != CRef_Undef){ - // CONFLICT - conflicts++; conflictC++; - if (decisionLevel() == 0) return l_False; - - learnt_clause.clear(); - analyze(confl, learnt_clause, backtrack_level); - cancelUntil(backtrack_level); - - if (learnt_clause.size() == 1){ - uncheckedEnqueue(learnt_clause[0]); - }else{ - CRef cr = ca.alloc(learnt_clause, true); - learnts.push(cr); - attachClause(cr); - claBumpActivity(ca[cr]); - uncheckedEnqueue(learnt_clause[0], cr); - } - - varDecayActivity(); - claDecayActivity(); - - if (--learntsize_adjust_cnt == 0){ - learntsize_adjust_confl *= learntsize_adjust_inc; - learntsize_adjust_cnt = (int)learntsize_adjust_confl; - max_learnts *= learntsize_inc; - - if (verbosity >= 1) - printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n", - (int)conflicts, - (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]), nClauses(), (int)clauses_literals, - (int)max_learnts, nLearnts(), (double)learnts_literals/nLearnts(), progressEstimate()*100); - } - - }else{ - // NO CONFLICT - if (nof_conflicts >= 0 && conflictC >= nof_conflicts || !withinBudget()){ - // Reached bound on number of conflicts: - progress_estimate = progressEstimate(); - cancelUntil(0); - return l_Undef; } - - // Simplify the set of problem clauses: - if (decisionLevel() == 0 && !simplify()) - return l_False; - - if (learnts.size()-nAssigns() >= max_learnts) - // Reduce the set of learnt clauses: - reduceDB(); - - Lit next = lit_Undef; - while (decisionLevel() < assumptions.size()){ - // Perform user provided assumption: - Lit p = assumptions[decisionLevel()]; - if (value(p) == l_True){ - // Dummy decision level: - newDecisionLevel(); - }else if (value(p) == l_False){ - analyzeFinal(~p, conflict); - return l_False; - }else{ - next = p; - break; - } - } - - if (next == lit_Undef){ - // New variable decision: - decisions++; - next = pickBranchLit(); - - if (next == lit_Undef) - // Model found: - return l_True; - } - - // Increase decision level and enqueue 'next' - newDecisionLevel(); - uncheckedEnqueue(next); - } - } -} - - -double Solver::progressEstimate() const -{ - double progress = 0; - double F = 1.0 / nVars(); - - for (int i = 0; i <= decisionLevel(); i++){ - int beg = i == 0 ? 0 : trail_lim[i - 1]; - int end = i == decisionLevel() ? trail.size() : trail_lim[i]; - progress += pow(F, i) * (end - beg); - } - - return progress / nVars(); -} - -/* - Finite subsequences of the Luby-sequence: - - 0: 1 - 1: 1 1 2 - 2: 1 1 2 1 1 2 4 - 3: 1 1 2 1 1 2 4 1 1 2 1 1 2 4 8 - ... - - - */ - -static double luby(double y, int x){ - - // Find the finite subsequence that contains index 'x', and the - // size of that subsequence: - int size, seq; - for (size = 1, seq = 0; size < x+1; seq++, size = 2*size+1); - - while (size-1 != x){ - size = (size-1)>>1; - seq--; - x = x % size; - } - - return pow(y, seq); -} - -// NOTE: assumptions passed in member-variable 'assumptions'. -lbool Solver::solve_() -{ - model.clear(); - conflict.clear(); - if (!ok) return l_False; - - solves++; - - max_learnts = nClauses() * learntsize_factor; - learntsize_adjust_confl = learntsize_adjust_start_confl; - learntsize_adjust_cnt = (int)learntsize_adjust_confl; - lbool status = l_Undef; - - if (verbosity >= 1){ - printf("============================[ Search Statistics ]==============================\n"); - printf("| Conflicts | ORIGINAL | LEARNT | Progress |\n"); - printf("| | Vars Clauses Literals | Limit Clauses Lit/Cl | |\n"); - printf("===============================================================================\n"); - } - - // Search: - int curr_restarts = 0; - while (status == l_Undef){ - double rest_base = luby_restart ? luby(restart_inc, curr_restarts) : pow(restart_inc, curr_restarts); - status = search(rest_base * restart_first); - if (!withinBudget()) break; - curr_restarts++; - } - - if (verbosity >= 1) - printf("===============================================================================\n"); - - - if (status == l_True){ - // Extend & copy model: - model.growTo(nVars()); - for (int i = 0; i < nVars(); i++) model[i] = value(i); - }else if (status == l_False && conflict.size() == 0) - ok = false; - - cancelUntil(0); - return status; -} - -//================================================================================================= -// Writing CNF to DIMACS: -// -// FIXME: this needs to be rewritten completely. - -static Var mapVar(Var x, vec& map, Var& max) -{ - if (map.size() <= x || map[x] == -1){ - map.growTo(x+1, -1); - map[x] = max++; - } - return map[x]; -} - - -void Solver::toDimacs(FILE* f, Clause& c, vec& map, Var& max) -{ - if (satisfied(c)) return; - - for (int i = 0; i < c.size(); i++) - if (value(c[i]) != l_False) - fprintf(f, "%s%d ", sign(c[i]) ? "-" : "", mapVar(var(c[i]), map, max)+1); - fprintf(f, "0\n"); -} - - -void Solver::toDimacs(const char *file, const vec& assumps) -{ - FILE* f = fopen(file, "wr"); - if (f == NULL) - fprintf(stderr, "could not open file %s\n", file), exit(1); - toDimacs(f, assumps); - fclose(f); -} - - -void Solver::toDimacs(FILE* f, const vec& assumps) -{ - // Handle case when solver is in contradictory state: - if (!ok){ - fprintf(f, "p cnf 1 2\n1 0\n-1 0\n"); - return; } - - vec map; Var max = 0; - - // Cannot use removeClauses here because it is not safe - // to deallocate them at this point. Could be improved. - int cnt = 0; - for (int i = 0; i < clauses.size(); i++) - if (!satisfied(ca[clauses[i]])) - cnt++; - - for (int i = 0; i < clauses.size(); i++) - if (!satisfied(ca[clauses[i]])){ - Clause& c = ca[clauses[i]]; - for (int j = 0; j < c.size(); j++) - if (value(c[j]) != l_False) - mapVar(var(c[j]), map, max); - } - - // Assumptions are added as unit clauses: - cnt += assumptions.size(); - - fprintf(f, "p cnf %d %d\n", max, cnt); - - for (int i = 0; i < assumptions.size(); i++){ - assert(value(assumptions[i]) != l_False); - fprintf(f, "%s%d 0\n", sign(assumptions[i]) ? "-" : "", mapVar(var(assumptions[i]), map, max)+1); - } - - for (int i = 0; i < clauses.size(); i++) - toDimacs(f, ca[clauses[i]], map, max); - - if (verbosity > 0) - printf("Wrote %d clauses with %d variables.\n", cnt, max); -} - - -//================================================================================================= -// Garbage Collection methods: - -void Solver::relocAll(ClauseAllocator& to) -{ - // All watchers: - // - // for (int i = 0; i < watches.size(); i++) - watches.cleanAll(); - for (int v = 0; v < nVars(); v++) - for (int s = 0; s < 2; s++){ - Lit p = mkLit(v, s); - // printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1); - vec& ws = watches[p]; - for (int j = 0; j < ws.size(); j++) - ca.reloc(ws[j].cref, to); - } - - // All reasons: - // - for (int i = 0; i < trail.size(); i++){ - Var v = var(trail[i]); - - if (reason(v) != CRef_Undef && (ca[reason(v)].reloced() || locked(ca[reason(v)]))) - ca.reloc(vardata[v].reason, to); - } - - // All learnt: - // - for (int i = 0; i < learnts.size(); i++) - ca.reloc(learnts[i], to); - - // All original: - // - for (int i = 0; i < clauses.size(); i++) - ca.reloc(clauses[i], to); -} - - -void Solver::garbageCollect() -{ - // Initialize the next region to a size corresponding to the estimated utilization degree. This - // is not precise but should avoid some unnecessary reallocations for the new region: - ClauseAllocator to(ca.size() - ca.wasted()); - - relocAll(to); - if (verbosity >= 2) - printf("| Garbage collection: %12d bytes => %12d bytes |\n", - ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size); - to.moveTo(ca); -} diff --git a/src/sat/minisat/core/Solver.h b/src/sat/minisat/core/Solver.h deleted file mode 100644 index 90119e58..00000000 --- a/src/sat/minisat/core/Solver.h +++ /dev/null @@ -1,373 +0,0 @@ -/****************************************************************************************[Solver.h] -Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_Solver_h -#define Minisat_Solver_h - -#include "mtl/Vec.h" -#include "mtl/Heap.h" -#include "mtl/Alg.h" -#include "utils/Options.h" -#include "core/SolverTypes.h" - - -namespace Minisat { - -//================================================================================================= -// Solver -- the main class: - -class Solver { -public: - - // Constructor/Destructor: - // - Solver(); - virtual ~Solver(); - - // Problem specification: - // - Var newVar (bool polarity = true, bool dvar = true); // Add a new variable with parameters specifying variable mode. - - bool addClause (const vec& ps); // Add a clause to the solver. - bool addEmptyClause(); // Add the empty clause, making the solver contradictory. - bool addClause (Lit p); // Add a unit clause to the solver. - bool addClause (Lit p, Lit q); // Add a binary clause to the solver. - bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver. - bool addClause_( vec& ps); // Add a clause to the solver without making superflous internal copy. Will - // change the passed vector 'ps'. - - // Solving: - // - bool simplify (); // Removes already satisfied clauses. - bool solve (const vec& assumps); // Search for a model that respects a given set of assumptions. - lbool solveLimited (const vec& assumps); // Search for a model that respects a given set of assumptions (With resource constraints). - bool solve (); // Search without assumptions. - bool solve (Lit p); // Search for a model that respects a single assumption. - bool solve (Lit p, Lit q); // Search for a model that respects two assumptions. - bool solve (Lit p, Lit q, Lit r); // Search for a model that respects three assumptions. - bool okay () const; // FALSE means solver is in a conflicting state - - void toDimacs (FILE* f, const vec& assumps); // Write CNF to file in DIMACS-format. - void toDimacs (const char *file, const vec& assumps); - void toDimacs (FILE* f, Clause& c, vec& map, Var& max); - - // Convenience versions of 'toDimacs()': - void toDimacs (const char* file); - void toDimacs (const char* file, Lit p); - void toDimacs (const char* file, Lit p, Lit q); - void toDimacs (const char* file, Lit p, Lit q, Lit r); - - // Variable mode: - // - void setPolarity (Var v, bool b); // Declare which polarity the decision heuristic should use for a variable. Requires mode 'polarity_user'. - void setDecisionVar (Var v, bool b); // Declare if a variable should be eligible for selection in the decision heuristic. - - // Read state: - // - lbool value (Var x) const; // The current value of a variable. - lbool value (Lit p) const; // The current value of a literal. - lbool modelValue (Var x) const; // The value of a variable in the last model. The last call to solve must have been satisfiable. - lbool modelValue (Lit p) const; // The value of a literal in the last model. The last call to solve must have been satisfiable. - int nAssigns () const; // The current number of assigned literals. - int nClauses () const; // The current number of original clauses. - int nLearnts () const; // The current number of learnt clauses. - int nVars () const; // The current number of variables. - int nFreeVars () const; - - // Resource contraints: - // - void setConfBudget(int64_t x); - void setPropBudget(int64_t x); - void budgetOff(); - void interrupt(); // Trigger a (potentially asynchronous) interruption of the solver. - void clearInterrupt(); // Clear interrupt indicator flag. - - // Memory managment: - // - virtual void garbageCollect(); - void checkGarbage(double gf); - void checkGarbage(); - - // Extra results: (read-only member variable) - // - vec model; // If problem is satisfiable, this vector contains the model (if any). - vec conflict; // If problem is unsatisfiable (possibly under assumptions), - // this vector represent the final conflict clause expressed in the assumptions. - - // Mode of operation: - // - int verbosity; - double var_decay; - double clause_decay; - double random_var_freq; - double random_seed; - bool luby_restart; - int ccmin_mode; // Controls conflict clause minimization (0=none, 1=basic, 2=deep). - int phase_saving; // Controls the level of phase saving (0=none, 1=limited, 2=full). - bool rnd_pol; // Use random polarities for branching heuristics. - bool rnd_init_act; // Initialize variable activities with a small random value. - double garbage_frac; // The fraction of wasted memory allowed before a garbage collection is triggered. - - int restart_first; // The initial restart limit. (default 100) - double restart_inc; // The factor with which the restart limit is multiplied in each restart. (default 1.5) - double learntsize_factor; // The intitial limit for learnt clauses is a factor of the original clauses. (default 1 / 3) - double learntsize_inc; // The limit for learnt clauses is multiplied with this factor each restart. (default 1.1) - - int learntsize_adjust_start_confl; - double learntsize_adjust_inc; - - // Statistics: (read-only member variable) - // - uint64_t solves, starts, decisions, rnd_decisions, propagations, conflicts; - uint64_t dec_vars, clauses_literals, learnts_literals, max_literals, tot_literals; - -protected: - - // Helper structures: - // - struct VarData { CRef reason; int level; }; - static inline VarData mkVarData(CRef cr, int l){ VarData d = {cr, l}; return d; } - - struct Watcher { - CRef cref; - Lit blocker; - Watcher(CRef cr, Lit p) : cref(cr), blocker(p) {} - bool operator==(const Watcher& w) const { return cref == w.cref; } - bool operator!=(const Watcher& w) const { return cref != w.cref; } - }; - - struct WatcherDeleted - { - const ClauseAllocator& ca; - WatcherDeleted(const ClauseAllocator& _ca) : ca(_ca) {} - bool operator()(const Watcher& w) const { return ca[w.cref].mark() == 1; } - }; - - struct VarOrderLt { - const vec& activity; - bool operator () (Var x, Var y) const { return activity[x] > activity[y]; } - VarOrderLt(const vec& act) : activity(act) { } - }; - - // Solver state: - // - bool ok; // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used! - vec clauses; // List of problem clauses. - vec learnts; // List of learnt clauses. - double cla_inc; // Amount to bump next clause with. - vec activity; // A heuristic measurement of the activity of a variable. - double var_inc; // Amount to bump next variable with. - OccLists, WatcherDeleted> - watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true). - vec assigns; // The current assignments. - vec polarity; // The preferred polarity of each variable. - vec decision; // Declares if a variable is eligible for selection in the decision heuristic. - vec trail; // Assignment stack; stores all assigments made in the order they were made. - vec trail_lim; // Separator indices for different decision levels in 'trail'. - vec vardata; // Stores reason and level for each variable. - int qhead; // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat). - int simpDB_assigns; // Number of top-level assignments since last execution of 'simplify()'. - int64_t simpDB_props; // Remaining number of propagations that must be made before next execution of 'simplify()'. - vec assumptions; // Current set of assumptions provided to solve by the user. - Heap order_heap; // A priority queue of variables ordered with respect to the variable activity. - double progress_estimate;// Set by 'search()'. - bool remove_satisfied; // Indicates whether possibly inefficient linear scan for satisfied clauses should be performed in 'simplify'. - - ClauseAllocator ca; - - // Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is - // used, exept 'seen' wich is used in several places. - // - vec seen; - vec analyze_stack; - vec analyze_toclear; - vec add_tmp; - - double max_learnts; - double learntsize_adjust_confl; - int learntsize_adjust_cnt; - - // Resource contraints: - // - int64_t conflict_budget; // -1 means no budget. - int64_t propagation_budget; // -1 means no budget. - bool asynch_interrupt; - - // Main internal methods: - // - void insertVarOrder (Var x); // Insert a variable in the decision order priority queue. - Lit pickBranchLit (); // Return the next decision variable. - void newDecisionLevel (); // Begins a new decision level. - void uncheckedEnqueue (Lit p, CRef from = CRef_Undef); // Enqueue a literal. Assumes value of literal is undefined. - bool enqueue (Lit p, CRef from = CRef_Undef); // Test if fact 'p' contradicts current state, enqueue otherwise. - CRef propagate (); // Perform unit propagation. Returns possibly conflicting clause. - void cancelUntil (int level); // Backtrack until a certain level. - void analyze (CRef confl, vec& out_learnt, int& out_btlevel); // (bt = backtrack) - void analyzeFinal (Lit p, vec& out_conflict); // COULD THIS BE IMPLEMENTED BY THE ORDINARIY "analyze" BY SOME REASONABLE GENERALIZATION? - bool litRedundant (Lit p, uint32_t abstract_levels); // (helper method for 'analyze()') - lbool search (int nof_conflicts); // Search for a given number of conflicts. - lbool solve_ (); // Main solve method (assumptions given in 'assumptions'). - void reduceDB (); // Reduce the set of learnt clauses. - void removeSatisfied (vec& cs); // Shrink 'cs' to contain only non-satisfied clauses. - void rebuildOrderHeap (); - - // Maintaining Variable/Clause activity: - // - void varDecayActivity (); // Decay all variables with the specified factor. Implemented by increasing the 'bump' value instead. - void varBumpActivity (Var v, double inc); // Increase a variable with the current 'bump' value. - void varBumpActivity (Var v); // Increase a variable with the current 'bump' value. - void claDecayActivity (); // Decay all clauses with the specified factor. Implemented by increasing the 'bump' value instead. - void claBumpActivity (Clause& c); // Increase a clause with the current 'bump' value. - - // Operations on clauses: - // - void attachClause (CRef cr); // Attach a clause to watcher lists. - void detachClause (CRef cr, bool strict = false); // Detach a clause to watcher lists. - void removeClause (CRef cr); // Detach and free a clause. - bool locked (const Clause& c) const; // Returns TRUE if a clause is a reason for some implication in the current state. - bool satisfied (const Clause& c) const; // Returns TRUE if a clause is satisfied in the current state. - - void relocAll (ClauseAllocator& to); - - // Misc: - // - int decisionLevel () const; // Gives the current decisionlevel. - uint32_t abstractLevel (Var x) const; // Used to represent an abstraction of sets of decision levels. - CRef reason (Var x) const; - int level (Var x) const; - double progressEstimate () const; // DELETE THIS ?? IT'S NOT VERY USEFUL ... - bool withinBudget () const; - - // Static helpers: - // - - // Returns a random float 0 <= x < 1. Seed must never be 0. - static inline double drand(double& seed) { - seed *= 1389796; - int 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); } -}; - - -//================================================================================================= -// Implementation of inline methods: - -inline CRef Solver::reason(Var x) const { return vardata[x].reason; } -inline int Solver::level (Var x) const { return vardata[x].level; } - -inline void Solver::insertVarOrder(Var x) { - if (!order_heap.inHeap(x) && decision[x]) order_heap.insert(x); } - -inline void Solver::varDecayActivity() { var_inc *= (1 / var_decay); } -inline void Solver::varBumpActivity(Var v) { varBumpActivity(v, var_inc); } -inline void Solver::varBumpActivity(Var v, double inc) { - if ( (activity[v] += inc) > 1e100 ) { - // Rescale: - for (int i = 0; i < nVars(); i++) - activity[i] *= 1e-100; - var_inc *= 1e-100; } - - // Update order_heap with respect to new activity: - if (order_heap.inHeap(v)) - order_heap.decrease(v); } - -inline void Solver::claDecayActivity() { cla_inc *= (1 / clause_decay); } -inline void Solver::claBumpActivity (Clause& c) { - if ( (c.activity() += cla_inc) > 1e20 ) { - // Rescale: - for (int i = 0; i < learnts.size(); i++) - ca[learnts[i]].activity() *= 1e-20; - cla_inc *= 1e-20; } } - -inline void Solver::checkGarbage(void){ return checkGarbage(garbage_frac); } -inline void Solver::checkGarbage(double gf){ - if (ca.wasted() > ca.size() * gf) - garbageCollect(); } - -// NOTE: enqueue does not set the ok flag! (only public methods do) -inline bool Solver::enqueue (Lit p, CRef from) { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true); } -inline bool Solver::addClause (const vec& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); } -inline bool Solver::addEmptyClause () { add_tmp.clear(); return addClause_(add_tmp); } -inline bool Solver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); } -inline bool Solver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); } -inline bool Solver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); } -inline bool Solver::locked (const Clause& c) const { return value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && ca.lea(reason(var(c[0]))) == &c; } -inline void Solver::newDecisionLevel() { trail_lim.push(trail.size()); } - -inline int Solver::decisionLevel () const { return trail_lim.size(); } -inline uint32_t Solver::abstractLevel (Var x) const { return 1 << (level(x) & 31); } -inline lbool Solver::value (Var x) const { return assigns[x]; } -inline lbool Solver::value (Lit p) const { return assigns[var(p)] ^ sign(p); } -inline lbool Solver::modelValue (Var x) const { return model[x]; } -inline lbool Solver::modelValue (Lit p) const { return model[var(p)] ^ sign(p); } -inline int Solver::nAssigns () const { return trail.size(); } -inline int Solver::nClauses () const { return clauses.size(); } -inline int Solver::nLearnts () const { return learnts.size(); } -inline int Solver::nVars () const { return vardata.size(); } -inline int Solver::nFreeVars () const { return (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]); } -inline void Solver::setPolarity (Var v, bool b) { polarity[v] = b; } -inline void Solver::setDecisionVar(Var v, bool b) -{ - if ( b && !decision[v]) dec_vars++; - else if (!b && decision[v]) dec_vars--; - - decision[v] = b; - insertVarOrder(v); -} -inline void Solver::setConfBudget(int64_t x){ conflict_budget = conflicts + x; } -inline void Solver::setPropBudget(int64_t x){ propagation_budget = propagations + x; } -inline void Solver::interrupt(){ asynch_interrupt = true; } -inline void Solver::clearInterrupt(){ asynch_interrupt = false; } -inline void Solver::budgetOff(){ conflict_budget = propagation_budget = -1; } -inline bool Solver::withinBudget() const { - return !asynch_interrupt && - (conflict_budget < 0 || conflicts < (uint64_t)conflict_budget) && - (propagation_budget < 0 || propagations < (uint64_t)propagation_budget); } - -// FIXME: after the introduction of asynchronous interrruptions the solve-versions that return a -// pure bool do not give a safe interface. Either interrupts must be possible to turn off here, or -// all calls to solve must return an 'lbool'. I'm not yet sure which I prefer. -inline bool Solver::solve () { budgetOff(); assumptions.clear(); return solve_() == l_True; } -inline bool Solver::solve (Lit p) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_() == l_True; } -inline bool Solver::solve (Lit p, Lit q) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_() == l_True; } -inline bool Solver::solve (Lit p, Lit q, Lit r) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_() == l_True; } -inline bool Solver::solve (const vec& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_() == l_True; } -inline lbool Solver::solveLimited (const vec& assumps){ assumps.copyTo(assumptions); return solve_(); } -inline bool Solver::okay () const { return ok; } - -inline void Solver::toDimacs (const char* file){ vec as; toDimacs(file, as); } -inline void Solver::toDimacs (const char* file, Lit p){ vec as; as.push(p); toDimacs(file, as); } -inline void Solver::toDimacs (const char* file, Lit p, Lit q){ vec as; as.push(p); as.push(q); toDimacs(file, as); } -inline void Solver::toDimacs (const char* file, Lit p, Lit q, Lit r){ vec as; as.push(p); as.push(q); as.push(r); toDimacs(file, as); } - - -//================================================================================================= -// Debug etc: - - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/core/Solver.or b/src/sat/minisat/core/Solver.or deleted file mode 100644 index aa7f611426a2406635f5edf7bf0e05c2fc2cc86d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 501400 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 >{U?F?pSz_t_UhYhMH~pm zHh!1dG$OTe=hpAWHU5zD;4et2mp6@FqNQ$pM^9}W+t(P|ba+brV{Ag>TVosFNnL*I z`Au;fcf{6zr*~U%5n4)Zn%38twEW-$Q<@SQpWOIyZ2b>-~8x@pMUvf zLgUXV%g6t+WJ9+VHv?gE>q%-SVc4fOeuYstFzU4x%TGZcYjP(v{xELn_6Mn3 z!*`Br{CDGLlN+C#ynIGX&Cp4WukK7tY5cPOaWuX$X82b%|1%+bO zV$RR)cIa4`U(;j^$D?fA@QsW5El+{zr7n*-zo~ouM=Z7R@znYqF=K~6Qv3PX;s37b z+ISYMH8HjRv6!8k#}0UJY~u$P#Pk&d+V~bm_kx41LZn&JK_D=w-=Lwx$^)YU{RW*_ z9_W|d@7Sba!9Y?{KxF!52m0fo-mGw8Xhfi2a6r7RxN&EmIpxg50u@<>VKb22uY7bM zuRIVcE)EoCl?BZ}ZgE+lSUjj4=+m#fPm)8XwMtihZdPGo>vZX5#UV4$FDHP<%){ko zd7v^cG>^&^S!H=ya|`k8v}j{dpx^ME0InzG1p1w5{YS~p^*cUkNG{bLpL9%apkKeh zB1f=MyGb(xQ_ZZh?0JEyp{!6|c_=TtJTQAV_^8qr1x_h0$}P;x4wa+5NSboygz*zj zOPLe_xaua2OF8qjX^|R`onBTPEHlf&0sNv#+~mOR(`^ z1j_I8xL55a;GCfI*@C{zFC;6&INU14Bp6%_`5!9vB!lD#tWS z21Mye-a@m&EDRLq21@2-LALU&ioBwro4Ak$-pnEL+;Cyx08KknNT0XB6q2INP+nGH zL}jQq%R^aZp#YxpH_I@ak;yJIiMw0djvi@1ATA`R%qmAifpg7si_5A4n7YN4q!1Gm zpOhAqY(e;kvb#QPRnyfga!%HuWiLFEGjgNlmrS1T^kigR-{m)9wW*YWzPnHsuU zr1d*CMsJm}p$&=GN&?wMxq+d9Vevx)L*fU~#fAZ) zUrxM*31DTJmR%e!%n1|~hv3T0qCjq5Av_S|h07TvEK*C(DGtN;jMiX^HmIy9XAl{j zMwxOGea+5>q=U{a#_K1^Q1davMr&gH23g}L5NTkv5?@Z2g5_9aGa5()wM z05M4T{YbK7Q!C5OD=QBP!xwK5E&7R-huS=rhtQ_dV`o2_=%y&T!b|2#y1 zsi}=W($crMb~sCIni5EDN;h_O>z+OamnlPV8Q*{0L0eMl|NYeB+7p2RMdFtz4%(1X zzj1a-{X0*m)Nhz6)|W92pN99b)|E}EO;fwusG^af8w5&f({V&iNDq_KojDsH89=Bp zedvai#%}~Bg0Kez1e-RY@u#zfema%pv00@yZWU~H?q@T4m@oxs0wNEiaVOS2Cd!i< zKTc&EQU^SeI{byQtrB|5;zfP?BPbJ{xfe_{5fBIoQoD_P&X#vv!#CkBPT;U<0%AB- zuN(xY73!Jj7xAT(`UGBval!2JCIV8D$}}88G%XY_q$7>dFLc?xU9usxLzGgVpx0_d zQssmyM9+qP6Qz!Fv`NVXnrgc??i&7W_34d2-%BCS)}IG_SO2)qo~!@h=lXYkZrnBC zk&Qnb+PL+wNA5*$pA@DeA`LQEXn?^R4cTLUyCUxTnF{0VjB^y#3 zc}SnRsacfkPwX20>S1CnibJ1IZG1xLTNG_ctUsMB5C5IXqj#n}llE}DJhF&*Q^07v zKL2C9V9%XuKmQMoSEt%@C-|RE9j{K1XOH!Bma|5~Ne}Z;m?*IIsBQ*56Bfi(>Sp!EZ5cYW1%Bb8;`b^XVkVjvm=xLxt;j-t4L=J z-QWoptVNlE1+h#Cnx?7!&-(%Ri@P=4k3Y)ge_!Ia9`BKA579~xU6Y!o4m|G%T3ABa z3c{wTLu}~K4be5D;{iu%Q>%jPyg0XcH`O1V2qEc^D7Eq1`=~RbA9P}5EIw&asK?IY zZigbi5$6JIM9hfroNjlgV3)qDVMBOFDs#~+KB*|wbLWI^hmL81e_~7g`$h0MRzL(1&CF~d@qr?KX6dAGY`hNm_@ ziB9bV!LSr7gd)7fqeq3h?L0HJ{t=vYY=8=ehR3CJyL$|DuodVZrY;`{CZWFFhi+L< zffCLnMAuU57vU%=bkN9C2G$-j@|6CIk{eGMfZ(FpoSdC}3-rin&sU2~) z-Ig=};L^~0Q4JwPYN4Fjh{h)l$?cZ3v8?;zg~PQ_7UgrB7i5Ohsj5GUn_+)tqZThb z5uqd1E{Mr(4h?eaBQleO-lIAjx`9*-O$&|h>bBo0V|IS(CfxZLB&Fmto{hx7Qhe)) zhl%I*V~hyAd*ie|(#$9TGIcf7p;I;n0-a$>M-w-27}) zoJQ_OvJN%ZCQ(G5;S-8Nd#B60l_App&|zc6S%pW2UZBRr`vvz+=6CP9kI_ty9EsrW zV-uaVfXT~Oqn#h_Sx=wS@Y4TLZz;&pkJnDBqWXhf)#Lu7WhY*|?za63drFJiQ?gC({J}@jL=tv> zdTVxmPQ=c=?Ob8gi+0XP>^&Bi&H?k{x#T(3l6y+x5Cz_ZsN5~^_SBx+YyS?uS6}0) zb4bwF$wFJ?3&=x|Z%84Zu$a~FLr%iN^Xj3u-M{I}`LdX$vGs9hBo0}DiQsLg%%&IP zV)-9xX+mQEWwB%JmM|(yo%!zd6A#a6)BKF{STpWFR;}f0r#M}Pe(e**KItV@0?{jLa?I%F@l+gY}#jIPYPb6E4 z>e<`=+tL18dUM+$nV%S^F&!SK*2dLq&#zkD&?eQ#F4w0g4q3*Rik^Apt&Qqyr9L6C z_c+HIUF#{0*BG0hm%hkN4~?(j;IKT#HSbP$PdjPdywBzv8SfObFvr-U>!!Ee1ES;9 zG7b=Pz1g1YqH_GZTj_*O$iBi<#}kOSQ){jeG+1xI!lfAW$7IIk)d*|D* zMB6`FqoW>|?asI?*Zh@?)*u$9T(yq5wCdr-_1t!%9j)!r?VaTtQErX zz2uW;C9bvY+DktqNx6fwjYl!Mz!SlaD@X@?ApXB$<57(6@M|qdr+#*|$DT|~;NvgB``U0a z0XICk75Fq8PO-Vbhp`f$LK{BZ1t?gX1CQ~mXA)IZur{q{EM@hLr#T5G>= z8}(z`sLyGmzM+l!>vvP%7m`0}*H?yiaUAihUitrMfE^2hOqh-^*S* zC>9rZ!hUxjj1&J!Hr*8toi_*vobW<6o?DIj|=n?hTucV(Z<}xr1w>>t%0ZD5iGk+6t

lMUoE)v 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 - -#include "mtl/IntTypes.h" -#include "mtl/Alg.h" -#include "mtl/Vec.h" -#include "mtl/Map.h" -#include "mtl/Alloc.h" - -namespace Minisat { - -//================================================================================================= -// Variables, literals, lifted booleans, clauses: - - -// NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N, -// so that they can be used as array indices. - -typedef int Var; -#define var_Undef (-1) - - -struct Lit { - int x; - - // Use this as a constructor: - friend Lit mkLit(Var var, bool sign = false); - - bool operator == (Lit p) const { return x == p.x; } - bool operator != (Lit p) const { return x != p.x; } - bool operator < (Lit p) const { return x < p.x; } // '<' makes p, ~p adjacent in the ordering. -}; - - -inline Lit mkLit (Var var, bool sign) { Lit p; p.x = var + var + (int)sign; return p; } -inline Lit operator ~(Lit p) { Lit q; q.x = p.x ^ 1; return q; } -inline Lit operator ^(Lit p, bool b) { Lit q; q.x = p.x ^ (unsigned int)b; return q; } -inline bool sign (Lit p) { return p.x & 1; } -inline int var (Lit p) { return p.x >> 1; } - -// Mapping Literals to and from compact integers suitable for array indexing: -inline int toInt (Var v) { return v; } -inline int toInt (Lit p) { return p.x; } -inline Lit toLit (int i) { Lit p; p.x = i; return p; } - -//const Lit lit_Undef = mkLit(var_Undef, false); // }- Useful special constants. -//const Lit lit_Error = mkLit(var_Undef, true ); // } - -const Lit lit_Undef = { -2 }; // }- Useful special constants. -const Lit lit_Error = { -1 }; // } - - -//================================================================================================= -// Lifted booleans: -// -// NOTE: this implementation is optimized for the case when comparisons between values are mostly -// between one variable and one constant. Some care had to be taken to make sure that gcc -// does enough constant propagation to produce sensible code, and this appears to be somewhat -// fragile unfortunately. - -#define l_True (lbool((uint8_t)0)) // gcc does not do constant propagation if these are real constants. -#define l_False (lbool((uint8_t)1)) -#define l_Undef (lbool((uint8_t)2)) - -class lbool { - uint8_t value; - -public: - explicit lbool(uint8_t v) : value(v) { } - - lbool() : value(0) { } - explicit lbool(bool x) : value(!x) { } - - bool operator == (lbool b) const { return ((b.value&2) & (value&2)) | (!(b.value&2)&(value == b.value)); } - bool operator != (lbool b) const { return !(*this == b); } - lbool operator ^ (bool b) const { return lbool((uint8_t)(value^(uint8_t)b)); } - - lbool operator && (lbool b) const { - uint8_t sel = (this->value << 1) | (b.value << 3); - uint8_t v = (0xF7F755F4 >> sel) & 3; - return lbool(v); } - - lbool operator || (lbool b) const { - uint8_t sel = (this->value << 1) | (b.value << 3); - uint8_t v = (0xFCFCF400 >> sel) & 3; - return lbool(v); } - - friend int toInt (lbool l); - friend lbool toLbool(int v); -}; -inline int toInt (lbool l) { return l.value; } -inline lbool toLbool(int v) { return lbool((uint8_t)v); } - -//================================================================================================= -// Clause -- a simple class for representing a clause: - -class Clause; -typedef RegionAllocator::Ref CRef; - -class Clause { - struct { - unsigned mark : 2; - unsigned learnt : 1; - unsigned has_extra : 1; - unsigned reloced : 1; - unsigned size : 27; } header; - union { Lit lit; float act; uint32_t abs; CRef rel; } data[0]; - - friend class ClauseAllocator; - - // NOTE: This constructor cannot be used directly (doesn't allocate enough memory). - template - Clause(const V& ps, bool use_extra, bool learnt) { - header.mark = 0; - header.learnt = learnt; - header.has_extra = use_extra; - header.reloced = 0; - header.size = ps.size(); - - for (int i = 0; i < ps.size(); i++) - data[i].lit = ps[i]; - - if (header.has_extra){ - if (header.learnt) - data[header.size].act = 0; - else - calcAbstraction(); } - } - -public: - void calcAbstraction() { - assert(header.has_extra); - uint32_t abstraction = 0; - for (int i = 0; i < size(); i++) - abstraction |= 1 << (var(data[i].lit) & 31); - data[header.size].abs = abstraction; } - - - int size () const { return header.size; } - void shrink (int i) { assert(i <= size()); if (header.has_extra) data[header.size-i] = data[header.size]; header.size -= i; } - void pop () { shrink(1); } - bool learnt () const { return header.learnt; } - bool has_extra () const { return header.has_extra; } - uint32_t mark () const { return header.mark; } - void mark (uint32_t m) { header.mark = m; } - const Lit& last () const { return data[header.size-1].lit; } - - bool reloced () const { return header.reloced; } - CRef relocation () const { return data[0].rel; } - void relocate (CRef c) { header.reloced = 1; data[0].rel = c; } - - // NOTE: somewhat unsafe to change the clause in-place! Must manually call 'calcAbstraction' afterwards for - // subsumption operations to behave correctly. - Lit& operator [] (int i) { return data[i].lit; } - Lit operator [] (int i) const { return data[i].lit; } - operator const Lit* (void) const { return (Lit*)data; } - - float& activity () { assert(header.has_extra); return data[header.size].act; } - uint32_t abstraction () const { assert(header.has_extra); return data[header.size].abs; } - - Lit subsumes (const Clause& other) const; - void strengthen (Lit p); -}; - - -//================================================================================================= -// ClauseAllocator -- a simple class for allocating memory for clauses: - - -const CRef CRef_Undef = RegionAllocator::Ref_Undef; -class ClauseAllocator : public RegionAllocator -{ - static int clauseWord32Size(int size, bool has_extra){ - return (sizeof(Clause) + (sizeof(Lit) * (size + (int)has_extra))) / sizeof(uint32_t); } - public: - bool extra_clause_field; - - ClauseAllocator(uint32_t start_cap) : RegionAllocator(start_cap), extra_clause_field(false){} - ClauseAllocator() : extra_clause_field(false){} - - void moveTo(ClauseAllocator& to){ - to.extra_clause_field = extra_clause_field; - RegionAllocator::moveTo(to); } - - template - CRef alloc(const Lits& ps, bool learnt = false) - { - assert(sizeof(Lit) == sizeof(uint32_t)); - assert(sizeof(float) == sizeof(uint32_t)); - bool use_extra = learnt | extra_clause_field; - - CRef cid = RegionAllocator::alloc(clauseWord32Size(ps.size(), use_extra)); - new (lea(cid)) Clause(ps, use_extra, learnt); - - return cid; - } - - // Deref, Load Effective Address (LEA), Inverse of LEA (AEL): - Clause& operator[](Ref r) { return (Clause&)RegionAllocator::operator[](r); } - const Clause& operator[](Ref r) const { return (Clause&)RegionAllocator::operator[](r); } - Clause* lea (Ref r) { return (Clause*)RegionAllocator::lea(r); } - const Clause* lea (Ref r) const { return (Clause*)RegionAllocator::lea(r); } - Ref ael (const Clause* t){ return RegionAllocator::ael((uint32_t*)t); } - - void free(CRef cid) - { - Clause& c = operator[](cid); - RegionAllocator::free(clauseWord32Size(c.size(), c.has_extra())); - } - - void reloc(CRef& cr, ClauseAllocator& to) - { - Clause& c = operator[](cr); - - if (c.reloced()) { cr = c.relocation(); return; } - - cr = to.alloc(c, c.learnt()); - c.relocate(cr); - - // Copy extra data-fields: - // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?) - to[cr].mark(c.mark()); - if (to[cr].learnt()) to[cr].activity() = c.activity(); - else if (to[cr].has_extra()) to[cr].calcAbstraction(); - } -}; - - -//================================================================================================= -// OccLists -- a class for maintaining occurence lists with lazy deletion: - -template -class OccLists -{ - vec occs; - vec dirty; - vec dirties; - Deleted deleted; - - public: - OccLists(const Deleted& d) : deleted(d) {} - - void init (const Idx& idx){ occs.growTo(toInt(idx)+1); dirty.growTo(toInt(idx)+1, 0); } - // Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; } - Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; } - Vec& lookup (const Idx& idx){ if (dirty[toInt(idx)]) clean(idx); return occs[toInt(idx)]; } - - void cleanAll (); - void clean (const Idx& idx); - void smudge (const Idx& idx){ - if (dirty[toInt(idx)] == 0){ - dirty[toInt(idx)] = 1; - dirties.push(idx); - } - } - - void clear(bool free = true){ - occs .clear(free); - dirty .clear(free); - dirties.clear(free); - } -}; - - -template -void OccLists::cleanAll() -{ - for (int i = 0; i < dirties.size(); i++) - // Dirties may contain duplicates so check here if a variable is already cleaned: - if (dirty[toInt(dirties[i])]) - clean(dirties[i]); - dirties.clear(); -} - - -template -void OccLists::clean(const Idx& idx) -{ - Vec& vec = occs[toInt(idx)]; - int i, j; - for (i = j = 0; i < vec.size(); i++) - if (!deleted(vec[i])) - vec[j++] = vec[i]; - vec.shrink(i - j); - dirty[toInt(idx)] = 0; -} - - -//================================================================================================= -// CMap -- a class for mapping clauses to values: - - -template -class CMap -{ - struct CRefHash { - uint32_t operator()(CRef cr) const { return (uint32_t)cr; } }; - - typedef Map HashTable; - HashTable map; - - public: - // Size-operations: - void clear () { map.clear(); } - int size () const { return map.elems(); } - - - // Insert/Remove/Test mapping: - void insert (CRef cr, const T& t){ map.insert(cr, t); } - void growTo (CRef cr, const T& t){ map.insert(cr, t); } // NOTE: for compatibility - void remove (CRef cr) { map.remove(cr); } - bool has (CRef cr, T& t) { return map.peek(cr, t); } - - // Vector interface (the clause 'c' must already exist): - const T& operator [] (CRef cr) const { return map[cr]; } - T& operator [] (CRef cr) { return map[cr]; } - - // Iteration (not transparent at all at the moment): - int bucket_count() const { return map.bucket_count(); } - const vec& bucket(int i) const { return map.bucket(i); } - - // Move contents to other map: - void moveTo(CMap& other){ map.moveTo(other.map); } - - // TMP debug: - void debug(){ - printf(" --- size = %d, bucket_count = %d\n", size(), map.bucket_count()); } -}; - - -/*_________________________________________________________________________________________________ -| -| subsumes : (other : const Clause&) -> Lit -| -| Description: -| Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other' -| by subsumption resolution. -| -| Result: -| lit_Error - No subsumption or simplification -| lit_Undef - Clause subsumes 'other' -| p - The literal p can be deleted from 'other' -|________________________________________________________________________________________________@*/ -inline Lit Clause::subsumes(const Clause& other) const -{ - //if (other.size() < size() || (extra.abst & ~other.extra.abst) != 0) - //if (other.size() < size() || (!learnt() && !other.learnt() && (extra.abst & ~other.extra.abst) != 0)) - assert(!header.learnt); assert(!other.header.learnt); - assert(header.has_extra); assert(other.header.has_extra); - if (other.header.size < header.size || (data[header.size].abs & ~other.data[other.header.size].abs) != 0) - return lit_Error; - - Lit ret = lit_Undef; - const Lit* c = (const Lit*)(*this); - const Lit* d = (const Lit*)other; - - for (unsigned i = 0; i < header.size; i++) { - // search for c[i] or ~c[i] - for (unsigned j = 0; j < other.header.size; j++) - if (c[i] == d[j]) - goto ok; - else if (ret == lit_Undef && c[i] == ~d[j]){ - ret = c[i]; - goto ok; - } - - // did not find it - return lit_Error; - ok:; - } - - return ret; -} - -inline void Clause::strengthen(Lit p) -{ - remove(*this, p); - calcAbstraction(); -} - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/core/depend.mk b/src/sat/minisat/core/depend.mk deleted file mode 100644 index 26302da5..00000000 --- a/src/sat/minisat/core/depend.mk +++ /dev/null @@ -1,37 +0,0 @@ -/home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Main.o /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Main.or /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Main.od /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Main.op: /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Main.cc \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/utils/System.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/IntTypes.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/utils/ParseUtils.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/utils/Options.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Vec.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/IntTypes.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/XAlloc.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/utils/ParseUtils.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Dimacs.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/SolverTypes.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/IntTypes.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Alg.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Vec.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Vec.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Map.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Alloc.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Solver.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Heap.h -/home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Solver.o /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Solver.or /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Solver.od /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Solver.op: \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Solver.cc \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Sort.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Vec.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/IntTypes.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/XAlloc.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/Solver.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Vec.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Heap.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Alg.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/utils/Options.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/IntTypes.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Vec.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/utils/ParseUtils.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/core/SolverTypes.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/IntTypes.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Map.h \ - /home/ric/class/dspf10/fraig/sol/src/sat/minisat/mtl/Alloc.h diff --git a/src/sat/minisat/doc/ReleaseNotes-2.2.0.txt b/src/sat/minisat/doc/ReleaseNotes-2.2.0.txt deleted file mode 100644 index 7f084de2..00000000 --- a/src/sat/minisat/doc/ReleaseNotes-2.2.0.txt +++ /dev/null @@ -1,79 +0,0 @@ -Release Notes for MiniSat 2.2.0 -=============================== - -Changes since version 2.0: - - * Started using a more standard release numbering. - - * Includes some now well-known heuristics: phase-saving and luby - restarts. The old heuristics are still present and can be activated - if needed. - - * Detection/Handling of out-of-memory and vector capacity - overflow. This is fairly new and relatively untested. - - * Simple resource controls: CPU-time, memory, number of - conflicts/decisions. - - * CPU-time limiting is implemented by a more general, but simple, - asynchronous interruption feature. This means that the solving - procedure can be interrupted from another thread or in a signal - handler. - - * Improved portability with respect to building on Solaris and with - Visual Studio. This is not regularly tested and chances are that - this have been broken since, but should be fairly easy to fix if - so. - - * Changed C++ file-extention to the less problematic ".cc". - - * Source code is now namespace-protected - - * Introducing a new Clause Memory Allocator that brings reduced - memory consumption on 64-bit architechtures and improved - performance (to some extent). The allocator uses a region-based - approach were all references to clauses are represented as a 32-bit - index into a global memory region that contains all clauses. To - free up and compact memory it uses a simple copying garbage - collector. - - * Improved unit-propagation by Blocking Literals. For each entry in - the watcher lists, pair the pointer to a clause with some - (arbitrary) literal from the clause. The idea is that if the - literal is currently true (i.e. the clause is satisfied) the - watchers of the clause does not need to be altered. This can thus - be detected without touching the clause's memory at all. As often - as can be done cheaply, the blocking literal for entries to the - watcher list of a literal 'p' is set to the other literal watched - in the corresponding clause. - - * Basic command-line/option handling system. Makes it easy to specify - options in the class that they affect, and whenever that class is - used in an executable, parsing of options and help messages are - brought in automatically. - - * General clean-up and various minor bug-fixes. - - * Changed implementation of variable-elimination/model-extension: - - - The interface is changed so that arbitrary remembering is no longer - possible. If you need to mention some variable again in the future, - this variable has to be frozen. - - - When eliminating a variable, only clauses that contain the variable - with one sign is necessary to store. Thereby making the other sign - a "default" value when extending models. - - - The memory consumption for eliminated clauses is further improved - by storing all eliminated clauses in a single contiguous vector. - - * Some common utility code (I/O, Parsing, CPU-time, etc) is ripped - out and placed in a separate "utils" directory. - - * The DIMACS parse is refactored so that it can be reused in other - applications (not very elegant, but at least possible). - - * Some simple improvements to scalability of preprocessing, using - more lazy clause removal from data-structures and a couple of - ad-hoc limits (the longest clause that can be produced in variable - elimination, and the longest clause used in backward subsumption). diff --git a/src/sat/minisat/mtl/Alg.h b/src/sat/minisat/mtl/Alg.h deleted file mode 100644 index bb1ee5ad..00000000 --- a/src/sat/minisat/mtl/Alg.h +++ /dev/null @@ -1,84 +0,0 @@ -/*******************************************************************************************[Alg.h] -Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_Alg_h -#define Minisat_Alg_h - -#include "mtl/Vec.h" - -namespace Minisat { - -//================================================================================================= -// Useful functions on vector-like types: - -//================================================================================================= -// Removing and searching for elements: -// - -template -static inline void remove(V& ts, const T& t) -{ - int j = 0; - for (; j < ts.size() && ts[j] != t; j++); - assert(j < ts.size()); - for (; j < ts.size()-1; j++) ts[j] = ts[j+1]; - ts.pop(); -} - - -template -static inline bool find(V& ts, const T& t) -{ - int j = 0; - for (; j < ts.size() && ts[j] != t; j++); - return j < ts.size(); -} - - -//================================================================================================= -// Copying vectors with support for nested vector types: -// - -// Base case: -template -static inline void copy(const T& from, T& to) -{ - to = from; -} - -// Recursive case: -template -static inline void copy(const vec& from, vec& to, bool append = false) -{ - if (!append) - to.clear(); - for (int i = 0; i < from.size(); i++){ - to.push(); - copy(from[i], to.last()); - } -} - -template -static inline void append(const vec& from, vec& to){ copy(from, to, true); } - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/mtl/Alloc.h b/src/sat/minisat/mtl/Alloc.h deleted file mode 100644 index 76322b8b..00000000 --- a/src/sat/minisat/mtl/Alloc.h +++ /dev/null @@ -1,131 +0,0 @@ -/*****************************************************************************************[Alloc.h] -Copyright (c) 2008-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - - -#ifndef Minisat_Alloc_h -#define Minisat_Alloc_h - -#include "mtl/XAlloc.h" -#include "mtl/Vec.h" - -namespace Minisat { - -//================================================================================================= -// Simple Region-based memory allocator: - -template -class RegionAllocator -{ - T* memory; - uint32_t sz; - uint32_t cap; - uint32_t wasted_; - - void capacity(uint32_t min_cap); - - public: - // TODO: make this a class for better type-checking? - typedef uint32_t Ref; - enum { Ref_Undef = UINT32_MAX }; - enum { Unit_Size = sizeof(uint32_t) }; - - explicit RegionAllocator(uint32_t start_cap = 1024*1024) : memory(NULL), sz(0), cap(0), wasted_(0){ capacity(start_cap); } - ~RegionAllocator() - { - if (memory != NULL) - ::free(memory); - } - - - uint32_t size () const { return sz; } - uint32_t wasted () const { return wasted_; } - - Ref alloc (int size); - void free (int size) { wasted_ += size; } - - // Deref, Load Effective Address (LEA), Inverse of LEA (AEL): - T& operator[](Ref r) { assert(r >= 0 && r < sz); return memory[r]; } - const T& operator[](Ref r) const { assert(r >= 0 && r < sz); return memory[r]; } - - T* lea (Ref r) { assert(r >= 0 && r < sz); return &memory[r]; } - const T* lea (Ref r) const { assert(r >= 0 && r < sz); return &memory[r]; } - Ref ael (const T* t) { assert((void*)t >= (void*)&memory[0] && (void*)t < (void*)&memory[sz-1]); - return (Ref)(t - &memory[0]); } - - void moveTo(RegionAllocator& to) { - if (to.memory != NULL) ::free(to.memory); - to.memory = memory; - to.sz = sz; - to.cap = cap; - to.wasted_ = wasted_; - - memory = NULL; - sz = cap = wasted_ = 0; - } - - -}; - -template -void RegionAllocator::capacity(uint32_t min_cap) -{ - if (cap >= min_cap) return; - - uint32_t prev_cap = cap; - while (cap < min_cap){ - // NOTE: Multiply by a factor (13/8) without causing overflow, then add 2 and make the - // result even by clearing the least significant bit. The resulting sequence of capacities - // is carefully chosen to hit a maximum capacity that is close to the '2^32-1' limit when - // using 'uint32_t' as indices so that as much as possible of this space can be used. - uint32_t delta = ((cap >> 1) + (cap >> 3) + 2) & ~1; - cap += delta; - - if (cap <= prev_cap) - throw OutOfMemoryException(); - } - // printf(" .. (%p) cap = %u\n", this, cap); - - assert(cap > 0); - memory = (T*)xrealloc(memory, sizeof(T)*cap); -} - - -template -typename RegionAllocator::Ref -RegionAllocator::alloc(int size) -{ - // printf("ALLOC called (this = %p, size = %d)\n", this, size); fflush(stdout); - assert(size > 0); - capacity(sz + size); - - uint32_t prev_sz = sz; - sz += size; - - // Handle overflow: - if (sz < prev_sz) - throw OutOfMemoryException(); - - return prev_sz; -} - - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/mtl/Heap.h b/src/sat/minisat/mtl/Heap.h deleted file mode 100644 index 226407e7..00000000 --- a/src/sat/minisat/mtl/Heap.h +++ /dev/null @@ -1,148 +0,0 @@ -/******************************************************************************************[Heap.h] -Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_Heap_h -#define Minisat_Heap_h - -#include "mtl/Vec.h" - -namespace Minisat { - -//================================================================================================= -// A heap implementation with support for decrease/increase key. - - -template -class Heap { - Comp lt; // The heap is a minimum-heap with respect to this comparator - vec heap; // Heap of integers - vec indices; // Each integers position (index) in the Heap - - // Index "traversal" functions - static inline int left (int i) { return i*2+1; } - static inline int right (int i) { return (i+1)*2; } - static inline int parent(int i) { return (i-1) >> 1; } - - - void percolateUp(int i) - { - int x = heap[i]; - int p = parent(i); - - while (i != 0 && lt(x, heap[p])){ - heap[i] = heap[p]; - indices[heap[p]] = i; - i = p; - p = parent(p); - } - heap [i] = x; - indices[x] = i; - } - - - void percolateDown(int i) - { - int x = heap[i]; - while (left(i) < heap.size()){ - int child = right(i) < heap.size() && lt(heap[right(i)], heap[left(i)]) ? right(i) : left(i); - if (!lt(heap[child], x)) break; - heap[i] = heap[child]; - indices[heap[i]] = i; - i = child; - } - heap [i] = x; - indices[x] = i; - } - - - public: - Heap(const Comp& c) : lt(c) { } - - int size () const { return heap.size(); } - bool empty () const { return heap.size() == 0; } - bool inHeap (int n) const { return n < indices.size() && indices[n] >= 0; } - int operator[](int index) const { assert(index < heap.size()); return heap[index]; } - - - void decrease (int n) { assert(inHeap(n)); percolateUp (indices[n]); } - void increase (int n) { assert(inHeap(n)); percolateDown(indices[n]); } - - - // Safe variant of insert/decrease/increase: - void update(int n) - { - if (!inHeap(n)) - insert(n); - else { - percolateUp(indices[n]); - percolateDown(indices[n]); } - } - - - void insert(int n) - { - indices.growTo(n+1, -1); - assert(!inHeap(n)); - - indices[n] = heap.size(); - heap.push(n); - percolateUp(indices[n]); - } - - - int removeMin() - { - int x = heap[0]; - heap[0] = heap.last(); - indices[heap[0]] = 0; - indices[x] = -1; - heap.pop(); - if (heap.size() > 1) percolateDown(0); - return x; - } - - - // Rebuild the heap from scratch, using the elements in 'ns': - void build(vec& ns) { - for (int i = 0; i < heap.size(); i++) - indices[heap[i]] = -1; - heap.clear(); - - for (int i = 0; i < ns.size(); i++){ - indices[ns[i]] = i; - heap.push(ns[i]); } - - for (int i = heap.size() / 2 - 1; i >= 0; i--) - percolateDown(i); - } - - void clear(bool dealloc = false) - { - for (int i = 0; i < heap.size(); i++) - indices[heap[i]] = -1; - heap.clear(dealloc); - } -}; - - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/mtl/IntTypes.h b/src/sat/minisat/mtl/IntTypes.h deleted file mode 100644 index c4881628..00000000 --- a/src/sat/minisat/mtl/IntTypes.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************************[IntTypes.h] -Copyright (c) 2009-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_IntTypes_h -#define Minisat_IntTypes_h - -#ifdef __sun - // Not sure if there are newer versions that support C99 headers. The - // needed features are implemented in the headers below though: - -# include -# include -# include - -#else - -# include -# include - -#endif - -#include - -//================================================================================================= - -#endif diff --git a/src/sat/minisat/mtl/Map.h b/src/sat/minisat/mtl/Map.h deleted file mode 100644 index 8a82d0e2..00000000 --- a/src/sat/minisat/mtl/Map.h +++ /dev/null @@ -1,193 +0,0 @@ -/*******************************************************************************************[Map.h] -Copyright (c) 2006-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_Map_h -#define Minisat_Map_h - -#include "mtl/IntTypes.h" -#include "mtl/Vec.h" - -namespace Minisat { - -//================================================================================================= -// Default hash/equals functions -// - -template struct Hash { uint32_t operator()(const K& k) const { return hash(k); } }; -template struct Equal { bool operator()(const K& k1, const K& k2) const { return k1 == k2; } }; - -template struct DeepHash { uint32_t operator()(const K* k) const { return hash(*k); } }; -template struct DeepEqual { bool operator()(const K* k1, const K* k2) const { return *k1 == *k2; } }; - -static inline uint32_t hash(uint32_t x){ return x; } -static inline uint32_t hash(uint64_t x){ return (uint32_t)x; } -static inline uint32_t hash(int32_t x) { return (uint32_t)x; } -static inline uint32_t hash(int64_t x) { return (uint32_t)x; } - - -//================================================================================================= -// Some primes -// - -static const int nprimes = 25; -static const int primes [nprimes] = { 31, 73, 151, 313, 643, 1291, 2593, 5233, 10501, 21013, 42073, 84181, 168451, 337219, 674701, 1349473, 2699299, 5398891, 10798093, 21596719, 43193641, 86387383, 172775299, 345550609, 691101253 }; - -//================================================================================================= -// Hash table implementation of Maps -// - -template, class E = Equal > -class Map { - public: - struct Pair { K key; D data; }; - - private: - H hash; - E equals; - - vec* table; - int cap; - int size; - - // Don't allow copying (error prone): - Map& operator = (Map& other) { assert(0); } - Map (Map& other) { assert(0); } - - bool checkCap(int new_size) const { return new_size > cap; } - - int32_t index (const K& k) const { return hash(k) % cap; } - void _insert (const K& k, const D& d) { - vec& ps = table[index(k)]; - ps.push(); ps.last().key = k; ps.last().data = d; } - - void rehash () { - const vec* old = table; - - int old_cap = cap; - int newsize = primes[0]; - for (int i = 1; newsize <= cap && i < nprimes; i++) - newsize = primes[i]; - - table = new vec[newsize]; - cap = newsize; - - for (int i = 0; i < old_cap; i++){ - for (int j = 0; j < old[i].size(); j++){ - _insert(old[i][j].key, old[i][j].data); }} - - delete [] old; - - // printf(" --- rehashing, old-cap=%d, new-cap=%d\n", cap, newsize); - } - - - public: - - Map () : table(NULL), cap(0), size(0) {} - Map (const H& h, const E& e) : hash(h), equals(e), table(NULL), cap(0), size(0){} - ~Map () { delete [] table; } - - // PRECONDITION: the key must already exist in the map. - const D& operator [] (const K& k) const - { - assert(size != 0); - const D* res = NULL; - const vec& ps = table[index(k)]; - for (int i = 0; i < ps.size(); i++) - if (equals(ps[i].key, k)) - res = &ps[i].data; - assert(res != NULL); - return *res; - } - - // PRECONDITION: the key must already exist in the map. - D& operator [] (const K& k) - { - assert(size != 0); - D* res = NULL; - vec& ps = table[index(k)]; - for (int i = 0; i < ps.size(); i++) - if (equals(ps[i].key, k)) - res = &ps[i].data; - assert(res != NULL); - return *res; - } - - // PRECONDITION: the key must *NOT* exist in the map. - void insert (const K& k, const D& d) { if (checkCap(size+1)) rehash(); _insert(k, d); size++; } - bool peek (const K& k, D& d) const { - if (size == 0) return false; - const vec& ps = table[index(k)]; - for (int i = 0; i < ps.size(); i++) - if (equals(ps[i].key, k)){ - d = ps[i].data; - return true; } - return false; - } - - bool has (const K& k) const { - if (size == 0) return false; - const vec& ps = table[index(k)]; - for (int i = 0; i < ps.size(); i++) - if (equals(ps[i].key, k)) - return true; - return false; - } - - // PRECONDITION: the key must exist in the map. - void remove(const K& k) { - assert(table != NULL); - vec& ps = table[index(k)]; - int j = 0; - for (; j < ps.size() && !equals(ps[j].key, k); j++); - assert(j < ps.size()); - ps[j] = ps.last(); - ps.pop(); - size--; - } - - void clear () { - cap = size = 0; - delete [] table; - table = NULL; - } - - int elems() const { return size; } - int bucket_count() const { return cap; } - - // NOTE: the hash and equality objects are not moved by this method: - void moveTo(Map& other){ - delete [] other.table; - - other.table = table; - other.cap = cap; - other.size = size; - - table = NULL; - size = cap = 0; - } - - // NOTE: given a bit more time, I could make a more C++-style iterator out of this: - const vec& bucket(int i) const { return table[i]; } -}; - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/mtl/Queue.h b/src/sat/minisat/mtl/Queue.h deleted file mode 100644 index 17567d69..00000000 --- a/src/sat/minisat/mtl/Queue.h +++ /dev/null @@ -1,69 +0,0 @@ -/*****************************************************************************************[Queue.h] -Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_Queue_h -#define Minisat_Queue_h - -#include "mtl/Vec.h" - -namespace Minisat { - -//================================================================================================= - -template -class Queue { - vec buf; - int first; - int end; - -public: - typedef T Key; - - Queue() : buf(1), first(0), end(0) {} - - void clear (bool dealloc = false) { buf.clear(dealloc); buf.growTo(1); first = end = 0; } - int size () const { return (end >= first) ? end - first : end - first + buf.size(); } - - const T& operator [] (int index) const { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; } - T& operator [] (int index) { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; } - - T peek () const { assert(first != end); return buf[first]; } - void pop () { assert(first != end); first++; if (first == buf.size()) first = 0; } - void insert(T elem) { // INVARIANT: buf[end] is always unused - buf[end++] = elem; - if (end == buf.size()) end = 0; - if (first == end){ // Resize: - vec tmp((buf.size()*3 + 1) >> 1); - //**/printf("queue alloc: %d elems (%.1f MB)\n", tmp.size(), tmp.size() * sizeof(T) / 1000000.0); - int i = 0; - for (int j = first; j < buf.size(); j++) tmp[i++] = buf[j]; - for (int j = 0 ; j < end ; j++) tmp[i++] = buf[j]; - first = 0; - end = buf.size(); - tmp.moveTo(buf); - } - } -}; - - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/mtl/Sort.h b/src/sat/minisat/mtl/Sort.h deleted file mode 100644 index e9313ef8..00000000 --- a/src/sat/minisat/mtl/Sort.h +++ /dev/null @@ -1,98 +0,0 @@ -/******************************************************************************************[Sort.h] -Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_Sort_h -#define Minisat_Sort_h - -#include "mtl/Vec.h" - -//================================================================================================= -// Some sorting algorithms for vec's - - -namespace Minisat { - -template -struct LessThan_default { - bool operator () (T x, T y) { return x < y; } -}; - - -template -void selectionSort(T* array, int size, LessThan lt) -{ - int i, j, best_i; - T tmp; - - for (i = 0; i < size-1; i++){ - best_i = i; - for (j = i+1; j < size; j++){ - if (lt(array[j], array[best_i])) - best_i = j; - } - tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; - } -} -template static inline void selectionSort(T* array, int size) { - selectionSort(array, size, LessThan_default()); } - -template -void sort(T* array, int size, LessThan lt) -{ - if (size <= 15) - selectionSort(array, size, lt); - - else{ - T pivot = array[size / 2]; - T tmp; - int i = -1; - int j = size; - - for(;;){ - do i++; while(lt(array[i], pivot)); - do j--; while(lt(pivot, array[j])); - - if (i >= j) break; - - tmp = array[i]; array[i] = array[j]; array[j] = tmp; - } - - sort(array , i , lt); - sort(&array[i], size-i, lt); - } -} -template static inline void sort(T* array, int size) { - sort(array, size, LessThan_default()); } - - -//================================================================================================= -// For 'vec's: - - -template void sort(vec& v, LessThan lt) { - sort((T*)v, v.size(), lt); } -template void sort(vec& v) { - sort(v, LessThan_default()); } - - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/mtl/Vec.h b/src/sat/minisat/mtl/Vec.h deleted file mode 100644 index 9e220852..00000000 --- a/src/sat/minisat/mtl/Vec.h +++ /dev/null @@ -1,130 +0,0 @@ -/*******************************************************************************************[Vec.h] -Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_Vec_h -#define Minisat_Vec_h - -#include -#include - -#include "mtl/IntTypes.h" -#include "mtl/XAlloc.h" - -namespace Minisat { - -//================================================================================================= -// Automatically resizable arrays -// -// NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc) - -template -class vec { - T* data; - int sz; - int cap; - - // Don't allow copying (error prone): - vec& operator = (vec& other) { assert(0); return *this; } - vec (vec& other) { assert(0); } - - // Helpers for calculating next capacity: - static inline int imax (int x, int y) { int mask = (y-x) >> (sizeof(int)*8-1); return (x&mask) + (y&(~mask)); } - //static inline void nextCap(int& cap){ cap += ((cap >> 1) + 2) & ~1; } - static inline void nextCap(int& cap){ cap += ((cap >> 1) + 2) & ~1; } - -public: - // Constructors: - vec() : data(NULL) , sz(0) , cap(0) { } - explicit vec(int size) : data(NULL) , sz(0) , cap(0) { growTo(size); } - vec(int size, const T& pad) : data(NULL) , sz(0) , cap(0) { growTo(size, pad); } - ~vec() { clear(true); } - - // Pointer to first element: - operator T* (void) { return data; } - - // Size operations: - int size (void) const { return sz; } - void shrink (int nelems) { assert(nelems <= sz); for (int i = 0; i < nelems; i++) sz--, data[sz].~T(); } - void shrink_ (int nelems) { assert(nelems <= sz); sz -= nelems; } - int capacity (void) const { return cap; } - void capacity (int min_cap); - void growTo (int size); - void growTo (int size, const T& pad); - void clear (bool dealloc = false); - - // Stack interface: - void push (void) { if (sz == cap) capacity(sz+1); new (&data[sz]) T(); sz++; } - void push (const T& elem) { if (sz == cap) capacity(sz+1); data[sz++] = elem; } - void push_ (const T& elem) { assert(sz < cap); data[sz++] = elem; } - void pop (void) { assert(sz > 0); sz--, data[sz].~T(); } - // NOTE: it seems possible that overflow can happen in the 'sz+1' expression of 'push()', but - // in fact it can not since it requires that 'cap' is equal to INT_MAX. This in turn can not - // happen given the way capacities are calculated (below). Essentially, all capacities are - // even, but INT_MAX is odd. - - const T& last (void) const { return data[sz-1]; } - T& last (void) { return data[sz-1]; } - - // Vector interface: - const T& operator [] (int index) const { return data[index]; } - T& operator [] (int index) { return data[index]; } - - // Duplicatation (preferred instead): - void copyTo(vec& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) copy[i] = data[i]; } - void moveTo(vec& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; } -}; - - -template -void vec::capacity(int min_cap) { - if (cap >= min_cap) return; - int add = imax((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2 - if (add > INT_MAX - cap || ((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM) - throw OutOfMemoryException(); - } - - -template -void vec::growTo(int size, const T& pad) { - if (sz >= size) return; - capacity(size); - for (int i = sz; i < size; i++) data[i] = pad; - sz = size; } - - -template -void vec::growTo(int size) { - if (sz >= size) return; - capacity(size); - for (int i = sz; i < size; i++) new (&data[i]) T(); - sz = size; } - - -template -void vec::clear(bool dealloc) { - if (data != NULL){ - for (int i = 0; i < sz; i++) data[i].~T(); - sz = 0; - if (dealloc) free(data), data = NULL, cap = 0; } } - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/mtl/XAlloc.h b/src/sat/minisat/mtl/XAlloc.h deleted file mode 100644 index 1da17602..00000000 --- a/src/sat/minisat/mtl/XAlloc.h +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************************[XAlloc.h] -Copyright (c) 2009-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - - -#ifndef Minisat_XAlloc_h -#define Minisat_XAlloc_h - -#include -#include - -namespace Minisat { - -//================================================================================================= -// Simple layer on top of malloc/realloc to catch out-of-memory situtaions and provide some typing: - -class OutOfMemoryException{}; -static inline void* xrealloc(void *ptr, size_t size) -{ - void* mem = realloc(ptr, size); - if (mem == NULL && errno == ENOMEM){ - throw OutOfMemoryException(); - }else - return mem; -} - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/mtl/config.mk b/src/sat/minisat/mtl/config.mk deleted file mode 100644 index b5c36fc6..00000000 --- a/src/sat/minisat/mtl/config.mk +++ /dev/null @@ -1,6 +0,0 @@ -## -## This file is for system specific configurations. For instance, on -## some systems the path to zlib needs to be added. Example: -## -## CFLAGS += -I/usr/local/include -## LFLAGS += -L/usr/local/lib diff --git a/src/sat/minisat/mtl/template.mk b/src/sat/minisat/mtl/template.mk deleted file mode 100644 index 3f443fc3..00000000 --- a/src/sat/minisat/mtl/template.mk +++ /dev/null @@ -1,107 +0,0 @@ -## -## Template makefile for Standard, Profile, Debug, Release, and Release-static versions -## -## eg: "make rs" for a statically linked release version. -## "make d" for a debug version (no optimizations). -## "make" for the standard version (optimized, but with debug information and assertions active) - -PWD = $(shell pwd) -EXEC ?= $(notdir $(PWD)) - -CSRCS = $(wildcard $(PWD)/*.cc) -DSRCS = $(foreach dir, $(DEPDIR), $(filter-out $(MROOT)/$(dir)/Main.cc, $(wildcard $(MROOT)/$(dir)/*.cc))) -CHDRS = $(wildcard $(PWD)/*.h) -COBJS = $(CSRCS:.cc=.o) $(DSRCS:.cc=.o) - -PCOBJS = $(addsuffix p, $(COBJS)) -DCOBJS = $(addsuffix d, $(COBJS)) -RCOBJS = $(addsuffix r, $(COBJS)) - - -CXX ?= g++ -CFLAGS ?= -Wall -Wno-parentheses -LFLAGS ?= -Wall - -COPTIMIZE ?= -O3 - -CFLAGS += -I$(MROOT) -D __STDC_LIMIT_MACROS -D __STDC_FORMAT_MACROS -LFLAGS += -lz - -.PHONY : s p d r rs clean - -s: $(EXEC) -p: $(EXEC)_profile -d: $(EXEC)_debug -r: $(EXEC)_release -rs: $(EXEC)_static - -libs: lib$(LIB)_standard.a -libp: lib$(LIB)_profile.a -libd: lib$(LIB)_debug.a -libr: lib$(LIB)_release.a - -## Compile options -%.o: CFLAGS +=$(COPTIMIZE) -g -D DEBUG -%.op: CFLAGS +=$(COPTIMIZE) -pg -g -D NDEBUG -%.od: CFLAGS +=-O0 -g -D DEBUG -%.or: CFLAGS +=$(COPTIMIZE) -g -D NDEBUG - -## Link options -$(EXEC): LFLAGS += -g -$(EXEC)_profile: LFLAGS += -g -pg -$(EXEC)_debug: LFLAGS += -g -#$(EXEC)_release: LFLAGS += ... -$(EXEC)_static: LFLAGS += --static - -## Dependencies -$(EXEC): $(COBJS) -$(EXEC)_profile: $(PCOBJS) -$(EXEC)_debug: $(DCOBJS) -$(EXEC)_release: $(RCOBJS) -$(EXEC)_static: $(RCOBJS) - -lib$(LIB)_standard.a: $(filter-out */Main.o, $(COBJS)) -lib$(LIB)_profile.a: $(filter-out */Main.op, $(PCOBJS)) -lib$(LIB)_debug.a: $(filter-out */Main.od, $(DCOBJS)) -lib$(LIB)_release.a: $(filter-out */Main.or, $(RCOBJS)) - - -## Build rule -%.o %.op %.od %.or: %.cc - @echo Compiling: $(subst $(MROOT)/,,$@) - @$(CXX) $(CFLAGS) -c -o $@ $< - -## Linking rules (standard/profile/debug/release) -$(EXEC) $(EXEC)_profile $(EXEC)_debug $(EXEC)_release $(EXEC)_static: - @echo Linking: "$@ ( $(foreach f,$^,$(subst $(MROOT)/,,$f)) )" - @$(CXX) $^ $(LFLAGS) -o $@ - -## Library rules (standard/profile/debug/release) -lib$(LIB)_standard.a lib$(LIB)_profile.a lib$(LIB)_release.a lib$(LIB)_debug.a: - @echo Making library: "$@ ( $(foreach f,$^,$(subst $(MROOT)/,,$f)) )" - @$(AR) -rcsv $@ $^ - -## Library Soft Link rule: -libs libp libd libr: - @echo "Making Soft Link: $^ -> lib$(LIB).a" - @ln -sf $^ lib$(LIB).a - -## Clean rule -clean: - @rm -f $(EXEC) $(EXEC)_profile $(EXEC)_debug $(EXEC)_release $(EXEC)_static \ - $(COBJS) $(PCOBJS) $(DCOBJS) $(RCOBJS) *.core depend.mk - -## Make dependencies -depend.mk: $(CSRCS) $(CHDRS) - @echo Making dependencies - @$(CXX) $(CFLAGS) -I$(MROOT) \ - $(CSRCS) -MM | sed 's|\(.*\):|$(PWD)/\1 $(PWD)/\1r $(PWD)/\1d $(PWD)/\1p:|' > depend.mk - @for dir in $(DEPDIR); do \ - if [ -r $(MROOT)/$${dir}/depend.mk ]; then \ - echo Depends on: $${dir}; \ - cat $(MROOT)/$${dir}/depend.mk >> depend.mk; \ - fi; \ - done - --include $(MROOT)/mtl/config.mk --include depend.mk diff --git a/src/sat/minisat/simp/Main.cc b/src/sat/minisat/simp/Main.cc deleted file mode 100644 index e59d73be..00000000 --- a/src/sat/minisat/simp/Main.cc +++ /dev/null @@ -1,211 +0,0 @@ -/*****************************************************************************************[Main.cc] -Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007, Niklas Sorensson - -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. -**************************************************************************************************/ - -#include - -#include -#include -#include - -#include "utils/System.h" -#include "utils/ParseUtils.h" -#include "utils/Options.h" -#include "core/Dimacs.h" -#include "simp/SimpSolver.h" - -using namespace Minisat; - -//================================================================================================= - - -void printStats(Solver& solver) -{ - double cpu_time = cpuTime(); - double mem_used = memUsedPeak(); - printf("restarts : %"PRIu64"\n", solver.starts); - printf("conflicts : %-12"PRIu64" (%.0f /sec)\n", solver.conflicts , solver.conflicts /cpu_time); - printf("decisions : %-12"PRIu64" (%4.2f %% random) (%.0f /sec)\n", solver.decisions, (float)solver.rnd_decisions*100 / (float)solver.decisions, solver.decisions /cpu_time); - printf("propagations : %-12"PRIu64" (%.0f /sec)\n", solver.propagations, solver.propagations/cpu_time); - printf("conflict literals : %-12"PRIu64" (%4.2f %% deleted)\n", solver.tot_literals, (solver.max_literals - solver.tot_literals)*100 / (double)solver.max_literals); - if (mem_used != 0) printf("Memory used : %.2f MB\n", mem_used); - printf("CPU time : %g s\n", cpu_time); -} - - -static Solver* solver; -// Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case -// for this feature of the Solver as it may take longer than an immediate call to '_exit()'. -static void SIGINT_interrupt(int signum) { solver->interrupt(); } - -// Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls -// destructors and may cause deadlocks if a malloc/free function happens to be running (these -// functions are guarded by locks for multithreaded use). -static void SIGINT_exit(int signum) { - printf("\n"); printf("*** INTERRUPTED ***\n"); - if (solver->verbosity > 0){ - printStats(*solver); - printf("\n"); printf("*** INTERRUPTED ***\n"); } - _exit(1); } - - -//================================================================================================= -// Main: - -int main(int argc, char** argv) -{ - try { - setUsageHelp("USAGE: %s [options] \n\n where input may be either in plain or gzipped DIMACS.\n"); - // printf("This is MiniSat 2.0 beta\n"); - -#if defined(__linux__) - fpu_control_t oldcw, newcw; - _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw); - printf("WARNING: for repeatability, setting FPU to use double precision\n"); -#endif - // Extra options: - // - IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2)); - BoolOption pre ("MAIN", "pre", "Completely turn on/off any preprocessing.", true); - StringOption dimacs ("MAIN", "dimacs", "If given, stop after preprocessing and write the result to this file."); - IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", INT32_MAX, IntRange(0, INT32_MAX)); - IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", INT32_MAX, IntRange(0, INT32_MAX)); - - parseOptions(argc, argv, true); - - SimpSolver S; - double initial_time = cpuTime(); - - if (!pre) S.eliminate(true); - - S.verbosity = verb; - - solver = &S; - // Use signal handlers that forcibly quit until the solver will be able to respond to - // interrupts: - signal(SIGINT, SIGINT_exit); - signal(SIGXCPU,SIGINT_exit); - - // Set limit on CPU-time: - if (cpu_lim != INT32_MAX){ - rlimit rl; - getrlimit(RLIMIT_CPU, &rl); - if (rl.rlim_max == RLIM_INFINITY || (rlim_t)cpu_lim < rl.rlim_max){ - rl.rlim_cur = cpu_lim; - if (setrlimit(RLIMIT_CPU, &rl) == -1) - printf("WARNING! Could not set resource limit: CPU-time.\n"); - } } - - // Set limit on virtual memory: - if (mem_lim != INT32_MAX){ - rlim_t new_mem_lim = (rlim_t)mem_lim * 1024*1024; - rlimit rl; - getrlimit(RLIMIT_AS, &rl); - if (rl.rlim_max == RLIM_INFINITY || new_mem_lim < rl.rlim_max){ - rl.rlim_cur = new_mem_lim; - if (setrlimit(RLIMIT_AS, &rl) == -1) - printf("WARNING! Could not set resource limit: Virtual memory.\n"); - } } - - if (argc == 1) - printf("Reading from standard input... Use '--help' for help.\n"); - - gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb"); - if (in == NULL) - printf("ERROR! Could not open file: %s\n", argc == 1 ? "" : argv[1]), exit(1); - - if (S.verbosity > 0){ - printf("============================[ Problem Statistics ]=============================\n"); - printf("| |\n"); } - - parse_DIMACS(in, S); - gzclose(in); - FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL; - - if (S.verbosity > 0){ - printf("| Number of variables: %12d |\n", S.nVars()); - printf("| Number of clauses: %12d |\n", S.nClauses()); } - - double parsed_time = cpuTime(); - if (S.verbosity > 0) - printf("| Parse time: %12.2f s |\n", parsed_time - initial_time); - - // Change to signal-handlers that will only notify the solver and allow it to terminate - // voluntarily: - signal(SIGINT, SIGINT_interrupt); - signal(SIGXCPU,SIGINT_interrupt); - - S.eliminate(true); - double simplified_time = cpuTime(); - if (S.verbosity > 0){ - printf("| Simplification time: %12.2f s |\n", simplified_time - parsed_time); - printf("| |\n"); } - - if (!S.okay()){ - if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res); - if (S.verbosity > 0){ - printf("===============================================================================\n"); - printf("Solved by simplification\n"); - printStats(S); - printf("\n"); } - printf("UNSATISFIABLE\n"); - exit(20); - } - - if (dimacs){ - if (S.verbosity > 0) - printf("==============================[ Writing DIMACS ]===============================\n"); - S.toDimacs((const char*)dimacs); - if (S.verbosity > 0) - printStats(S); - exit(0); - } - - vec dummy; - lbool ret = S.solveLimited(dummy); - - if (S.verbosity > 0){ - printStats(S); - printf("\n"); } - printf(ret == l_True ? "SATISFIABLE\n" : ret == l_False ? "UNSATISFIABLE\n" : "INDETERMINATE\n"); - if (res != NULL){ - if (ret == l_True){ - fprintf(res, "SAT\n"); - for (int i = 0; i < S.nVars(); i++) - if (S.model[i] != l_Undef) - fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1); - fprintf(res, " 0\n"); - }else if (ret == l_False) - fprintf(res, "UNSAT\n"); - else - fprintf(res, "INDET\n"); - fclose(res); - } - -#ifdef NDEBUG - exit(ret == l_True ? 10 : ret == l_False ? 20 : 0); // (faster than "return", which will invoke the destructor for 'Solver') -#else - return (ret == l_True ? 10 : ret == l_False ? 20 : 0); -#endif - } catch (OutOfMemoryException&){ - printf("===============================================================================\n"); - printf("INDETERMINATE\n"); - exit(0); - } -} diff --git a/src/sat/minisat/simp/Makefile b/src/sat/minisat/simp/Makefile deleted file mode 100644 index 27b45f49..00000000 --- a/src/sat/minisat/simp/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -EXEC = minisat -DEPDIR = mtl utils core - -include $(MROOT)/mtl/template.mk diff --git a/src/sat/minisat/simp/SimpSolver.cc b/src/sat/minisat/simp/SimpSolver.cc deleted file mode 100644 index a1dc16d3..00000000 --- a/src/sat/minisat/simp/SimpSolver.cc +++ /dev/null @@ -1,717 +0,0 @@ -/***********************************************************************************[SimpSolver.cc] -Copyright (c) 2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#include "mtl/Sort.h" -#include "simp/SimpSolver.h" -#include "utils/System.h" - -using namespace Minisat; - -//================================================================================================= -// Options: - - -static const char* _cat = "SIMP"; - -static BoolOption opt_use_asymm (_cat, "asymm", "Shrink clauses by asymmetric branching.", false); -static BoolOption opt_use_rcheck (_cat, "rcheck", "Check if a clause is already implied. (costly)", false); -static BoolOption opt_use_elim (_cat, "elim", "Perform variable elimination.", true); -static IntOption opt_grow (_cat, "grow", "Allow a variable elimination step to grow by a number of clauses.", 0); -static IntOption opt_clause_lim (_cat, "cl-lim", "Variables are not eliminated if it produces a resolvent with a length above this limit. -1 means no limit", 20, IntRange(-1, INT32_MAX)); -static IntOption opt_subsumption_lim (_cat, "sub-lim", "Do not check if subsumption against a clause larger than this. -1 means no limit.", 1000, IntRange(-1, INT32_MAX)); -static DoubleOption opt_simp_garbage_frac(_cat, "simp-gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered during simplification.", 0.5, DoubleRange(0, false, HUGE_VAL, false)); - - -//================================================================================================= -// Constructor/Destructor: - - -SimpSolver::SimpSolver() : - grow (opt_grow) - , clause_lim (opt_clause_lim) - , subsumption_lim (opt_subsumption_lim) - , simp_garbage_frac (opt_simp_garbage_frac) - , use_asymm (opt_use_asymm) - , use_rcheck (opt_use_rcheck) - , use_elim (opt_use_elim) - , merges (0) - , asymm_lits (0) - , eliminated_vars (0) - , elimorder (1) - , use_simplification (true) - , occurs (ClauseDeleted(ca)) - , elim_heap (ElimLt(n_occ)) - , bwdsub_assigns (0) - , n_touched (0) -{ - vec dummy(1,lit_Undef); - ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below. - bwdsub_tmpunit = ca.alloc(dummy); - remove_satisfied = false; -} - - -SimpSolver::~SimpSolver() -{ -} - - -Var SimpSolver::newVar(bool sign, bool dvar) { - Var v = Solver::newVar(sign, dvar); - - frozen .push((char)false); - eliminated.push((char)false); - - if (use_simplification){ - n_occ .push(0); - n_occ .push(0); - occurs .init(v); - touched .push(0); - elim_heap .insert(v); - } - return v; } - - - -lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp) -{ - vec extra_frozen; - lbool result = l_True; - - do_simp &= use_simplification; - - if (do_simp){ - // Assumptions must be temporarily frozen to run variable elimination: - for (int i = 0; i < assumptions.size(); i++){ - Var v = var(assumptions[i]); - - // If an assumption has been eliminated, remember it. - assert(!isEliminated(v)); - - if (!frozen[v]){ - // Freeze and store. - setFrozen(v, true); - extra_frozen.push(v); - } } - - result = lbool(eliminate(turn_off_simp)); - } - - if (result == l_True) - result = Solver::solve_(); - else if (verbosity >= 1) - printf("===============================================================================\n"); - - if (result == l_True) - extendModel(); - - if (do_simp) - // Unfreeze the assumptions that were frozen: - for (int i = 0; i < extra_frozen.size(); i++) - setFrozen(extra_frozen[i], false); - - return result; -} - - - -bool SimpSolver::addClause_(vec& ps) -{ -#ifndef NDEBUG - for (int i = 0; i < ps.size(); i++) - assert(!isEliminated(var(ps[i]))); -#endif - - int nclauses = clauses.size(); - - if (use_rcheck && implied(ps)) - return true; - - if (!Solver::addClause_(ps)) - return false; - - if (use_simplification && clauses.size() == nclauses + 1){ - CRef cr = clauses.last(); - const Clause& c = ca[cr]; - - // NOTE: the clause is added to the queue immediately and then - // again during 'gatherTouchedClauses()'. If nothing happens - // in between, it will only be checked once. Otherwise, it may - // be checked twice unnecessarily. This is an unfortunate - // consequence of how backward subsumption is used to mimic - // forward subsumption. - subsumption_queue.insert(cr); - for (int i = 0; i < c.size(); i++){ - occurs[var(c[i])].push(cr); - n_occ[toInt(c[i])]++; - touched[var(c[i])] = 1; - n_touched++; - if (elim_heap.inHeap(var(c[i]))) - elim_heap.increase(var(c[i])); - } - } - - return true; -} - - -void SimpSolver::removeClause(CRef cr) -{ - const Clause& c = ca[cr]; - - if (use_simplification) - for (int i = 0; i < c.size(); i++){ - n_occ[toInt(c[i])]--; - updateElimHeap(var(c[i])); - occurs.smudge(var(c[i])); - } - - Solver::removeClause(cr); -} - - -bool SimpSolver::strengthenClause(CRef cr, Lit l) -{ - Clause& c = ca[cr]; - assert(decisionLevel() == 0); - assert(use_simplification); - - // FIX: this is too inefficient but would be nice to have (properly implemented) - // if (!find(subsumption_queue, &c)) - subsumption_queue.insert(cr); - - if (c.size() == 2){ - removeClause(cr); - c.strengthen(l); - }else{ - detachClause(cr, true); - c.strengthen(l); - attachClause(cr); - remove(occurs[var(l)], cr); - n_occ[toInt(l)]--; - updateElimHeap(var(l)); - } - - return c.size() == 1 ? enqueue(c[0]) && propagate() == CRef_Undef : true; -} - - -// Returns FALSE if clause is always satisfied ('out_clause' should not be used). -bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, vec& out_clause) -{ - merges++; - out_clause.clear(); - - bool ps_smallest = _ps.size() < _qs.size(); - const Clause& ps = ps_smallest ? _qs : _ps; - const Clause& qs = ps_smallest ? _ps : _qs; - - for (int i = 0; i < qs.size(); i++){ - if (var(qs[i]) != v){ - for (int j = 0; j < ps.size(); j++) - if (var(ps[j]) == var(qs[i])) - if (ps[j] == ~qs[i]) - return false; - else - goto next; - out_clause.push(qs[i]); - } - next:; - } - - for (int i = 0; i < ps.size(); i++) - if (var(ps[i]) != v) - out_clause.push(ps[i]); - - return true; -} - - -// Returns FALSE if clause is always satisfied. -bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, int& size) -{ - merges++; - - bool ps_smallest = _ps.size() < _qs.size(); - const Clause& ps = ps_smallest ? _qs : _ps; - const Clause& qs = ps_smallest ? _ps : _qs; - const Lit* __ps = (const Lit*)ps; - const Lit* __qs = (const Lit*)qs; - - size = ps.size()-1; - - for (int i = 0; i < qs.size(); i++){ - if (var(__qs[i]) != v){ - for (int j = 0; j < ps.size(); j++) - if (var(__ps[j]) == var(__qs[i])) - if (__ps[j] == ~__qs[i]) - return false; - else - goto next; - size++; - } - next:; - } - - return true; -} - - -void SimpSolver::gatherTouchedClauses() -{ - if (n_touched == 0) return; - - int i,j; - for (i = j = 0; i < subsumption_queue.size(); i++) - if (ca[subsumption_queue[i]].mark() == 0) - ca[subsumption_queue[i]].mark(2); - - for (i = 0; i < touched.size(); i++) - if (touched[i]){ - const vec& cs = occurs.lookup(i); - for (j = 0; j < cs.size(); j++) - if (ca[cs[j]].mark() == 0){ - subsumption_queue.insert(cs[j]); - ca[cs[j]].mark(2); - } - touched[i] = 0; - } - - for (i = 0; i < subsumption_queue.size(); i++) - if (ca[subsumption_queue[i]].mark() == 2) - ca[subsumption_queue[i]].mark(0); - - n_touched = 0; -} - - -bool SimpSolver::implied(const vec& c) -{ - assert(decisionLevel() == 0); - - trail_lim.push(trail.size()); - for (int i = 0; i < c.size(); i++) - if (value(c[i]) == l_True){ - cancelUntil(0); - return false; - }else if (value(c[i]) != l_False){ - assert(value(c[i]) == l_Undef); - uncheckedEnqueue(~c[i]); - } - - bool result = propagate() != CRef_Undef; - cancelUntil(0); - return result; -} - - -// Backward subsumption + backward subsumption resolution -bool SimpSolver::backwardSubsumptionCheck(bool verbose) -{ - int cnt = 0; - int subsumed = 0; - int deleted_literals = 0; - assert(decisionLevel() == 0); - - while (subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()){ - - // Empty subsumption queue and return immediately on user-interrupt: - if (asynch_interrupt){ - subsumption_queue.clear(); - bwdsub_assigns = trail.size(); - break; } - - // Check top-level assignments by creating a dummy clause and placing it in the queue: - if (subsumption_queue.size() == 0 && bwdsub_assigns < trail.size()){ - Lit l = trail[bwdsub_assigns++]; - ca[bwdsub_tmpunit][0] = l; - ca[bwdsub_tmpunit].calcAbstraction(); - subsumption_queue.insert(bwdsub_tmpunit); } - - CRef cr = subsumption_queue.peek(); subsumption_queue.pop(); - Clause& c = ca[cr]; - - if (c.mark()) continue; - - if (verbose && verbosity >= 2 && cnt++ % 1000 == 0) - printf("subsumption left: %10d (%10d subsumed, %10d deleted literals)\r", subsumption_queue.size(), subsumed, deleted_literals); - - assert(c.size() > 1 || value(c[0]) == l_True); // Unit-clauses should have been propagated before this point. - - // Find best variable to scan: - Var best = var(c[0]); - for (int i = 1; i < c.size(); i++) - if (occurs[var(c[i])].size() < occurs[best].size()) - best = var(c[i]); - - // Search all candidates: - vec& _cs = occurs.lookup(best); - CRef* cs = (CRef*)_cs; - - for (int j = 0; j < _cs.size(); j++) - if (c.mark()) - break; - else if (!ca[cs[j]].mark() && cs[j] != cr && (subsumption_lim == -1 || ca[cs[j]].size() < subsumption_lim)){ - Lit l = c.subsumes(ca[cs[j]]); - - if (l == lit_Undef) - subsumed++, removeClause(cs[j]); - else if (l != lit_Error){ - deleted_literals++; - - if (!strengthenClause(cs[j], ~l)) - return false; - - // Did current candidate get deleted from cs? Then check candidate at index j again: - if (var(l) == best) - j--; - } - } - } - - return true; -} - - -bool SimpSolver::asymm(Var v, CRef cr) -{ - Clause& c = ca[cr]; - assert(decisionLevel() == 0); - - if (c.mark() || satisfied(c)) return true; - - trail_lim.push(trail.size()); - Lit l = lit_Undef; - for (int i = 0; i < c.size(); i++) - if (var(c[i]) != v && value(c[i]) != l_False) - uncheckedEnqueue(~c[i]); - else - l = c[i]; - - if (propagate() != CRef_Undef){ - cancelUntil(0); - asymm_lits++; - if (!strengthenClause(cr, l)) - return false; - }else - cancelUntil(0); - - return true; -} - - -bool SimpSolver::asymmVar(Var v) -{ - assert(use_simplification); - - const vec& cls = occurs.lookup(v); - - if (value(v) != l_Undef || cls.size() == 0) - return true; - - for (int i = 0; i < cls.size(); i++) - if (!asymm(v, cls[i])) - return false; - - return backwardSubsumptionCheck(); -} - - -static void mkElimClause(vec& elimclauses, Lit x) -{ - elimclauses.push(toInt(x)); - elimclauses.push(1); -} - - -static void mkElimClause(vec& elimclauses, Var v, Clause& c) -{ - int first = elimclauses.size(); - int v_pos = -1; - - // Copy clause to elimclauses-vector. Remember position where the - // variable 'v' occurs: - for (int i = 0; i < c.size(); i++){ - elimclauses.push(toInt(c[i])); - if (var(c[i]) == v) - v_pos = i + first; - } - assert(v_pos != -1); - - // Swap the first literal with the 'v' literal, so that the literal - // containing 'v' will occur first in the clause: - uint32_t tmp = elimclauses[v_pos]; - elimclauses[v_pos] = elimclauses[first]; - elimclauses[first] = tmp; - - // Store the length of the clause last: - elimclauses.push(c.size()); -} - - - -bool SimpSolver::eliminateVar(Var v) -{ - assert(!frozen[v]); - assert(!isEliminated(v)); - assert(value(v) == l_Undef); - - // Split the occurrences into positive and negative: - // - const vec& cls = occurs.lookup(v); - vec pos, neg; - for (int i = 0; i < cls.size(); i++) - (find(ca[cls[i]], mkLit(v)) ? pos : neg).push(cls[i]); - - // Check wether the increase in number of clauses stays within the allowed ('grow'). Moreover, no - // clause must exceed the limit on the maximal clause size (if it is set): - // - int cnt = 0; - int clause_size = 0; - - for (int i = 0; i < pos.size(); i++) - for (int j = 0; j < neg.size(); j++) - if (merge(ca[pos[i]], ca[neg[j]], v, clause_size) && - (++cnt > cls.size() + grow || (clause_lim != -1 && clause_size > clause_lim))) - return true; - - // Delete and store old clauses: - eliminated[v] = true; - setDecisionVar(v, false); - eliminated_vars++; - - if (pos.size() > neg.size()){ - for (int i = 0; i < neg.size(); i++) - mkElimClause(elimclauses, v, ca[neg[i]]); - mkElimClause(elimclauses, mkLit(v)); - }else{ - for (int i = 0; i < pos.size(); i++) - mkElimClause(elimclauses, v, ca[pos[i]]); - mkElimClause(elimclauses, ~mkLit(v)); - } - - for (int i = 0; i < cls.size(); i++) - removeClause(cls[i]); - - // Produce clauses in cross product: - vec& resolvent = add_tmp; - for (int i = 0; i < pos.size(); i++) - for (int j = 0; j < neg.size(); j++) - if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) && !addClause_(resolvent)) - return false; - - // Free occurs list for this variable: - occurs[v].clear(true); - - // Free watchers lists for this variable, if possible: - if (watches[ mkLit(v)].size() == 0) watches[ mkLit(v)].clear(true); - if (watches[~mkLit(v)].size() == 0) watches[~mkLit(v)].clear(true); - - return backwardSubsumptionCheck(); -} - - -bool SimpSolver::substitute(Var v, Lit x) -{ - assert(!frozen[v]); - assert(!isEliminated(v)); - assert(value(v) == l_Undef); - - if (!ok) return false; - - eliminated[v] = true; - setDecisionVar(v, false); - const vec& cls = occurs.lookup(v); - - vec& subst_clause = add_tmp; - for (int i = 0; i < cls.size(); i++){ - Clause& c = ca[cls[i]]; - - subst_clause.clear(); - for (int j = 0; j < c.size(); j++){ - Lit p = c[j]; - subst_clause.push(var(p) == v ? x ^ sign(p) : p); - } - - removeClause(cls[i]); - - if (!addClause_(subst_clause)) - return ok = false; - } - - return true; -} - - -void SimpSolver::extendModel() -{ - int i, j; - Lit x; - - for (i = elimclauses.size()-1; i > 0; i -= j){ - for (j = elimclauses[i--]; j > 1; j--, i--) - if (modelValue(toLit(elimclauses[i])) != l_False) - goto next; - - x = toLit(elimclauses[i]); - model[var(x)] = lbool(!sign(x)); - next:; - } -} - - -bool SimpSolver::eliminate(bool turn_off_elim) -{ - if (!simplify()) - return false; - else if (!use_simplification) - return true; - - // Main simplification loop: - // - while (n_touched > 0 || bwdsub_assigns < trail.size() || elim_heap.size() > 0){ - - gatherTouchedClauses(); - // printf(" ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns); - if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()) && - !backwardSubsumptionCheck(true)){ - ok = false; goto cleanup; } - - // Empty elim_heap and return immediately on user-interrupt: - if (asynch_interrupt){ - assert(bwdsub_assigns == trail.size()); - assert(subsumption_queue.size() == 0); - assert(n_touched == 0); - elim_heap.clear(); - goto cleanup; } - - // printf(" ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size()); - for (int cnt = 0; !elim_heap.empty(); cnt++){ - Var elim = elim_heap.removeMin(); - - if (asynch_interrupt) break; - - if (isEliminated(elim) || value(elim) != l_Undef) continue; - - if (verbosity >= 2 && cnt % 100 == 0) - printf("elimination left: %10d\r", elim_heap.size()); - - if (use_asymm){ - // Temporarily freeze variable. Otherwise, it would immediately end up on the queue again: - bool was_frozen = frozen[elim]; - frozen[elim] = true; - if (!asymmVar(elim)){ - ok = false; goto cleanup; } - frozen[elim] = was_frozen; } - - // At this point, the variable may have been set by assymetric branching, so check it - // again. Also, don't eliminate frozen variables: - if (use_elim && value(elim) == l_Undef && !frozen[elim] && !eliminateVar(elim)){ - ok = false; goto cleanup; } - - checkGarbage(simp_garbage_frac); - } - - assert(subsumption_queue.size() == 0); - } - cleanup: - - // If no more simplification is needed, free all simplification-related data structures: - if (turn_off_elim){ - touched .clear(true); - occurs .clear(true); - n_occ .clear(true); - elim_heap.clear(true); - subsumption_queue.clear(true); - - use_simplification = false; - remove_satisfied = true; - ca.extra_clause_field = false; - - // Force full cleanup (this is safe and desirable since it only happens once): - rebuildOrderHeap(); - garbageCollect(); - }else{ - // Cheaper cleanup: - cleanUpClauses(); // TODO: can we make 'cleanUpClauses()' not be linear in the problem size somehow? - checkGarbage(); - } - - if (verbosity >= 1 && elimclauses.size() > 0) - printf("| Eliminated clauses: %10.2f Mb |\n", - double(elimclauses.size() * sizeof(uint32_t)) / (1024*1024)); - - return ok; -} - - -void SimpSolver::cleanUpClauses() -{ - occurs.cleanAll(); - int i,j; - for (i = j = 0; i < clauses.size(); i++) - if (ca[clauses[i]].mark() == 0) - clauses[j++] = clauses[i]; - clauses.shrink(i - j); -} - - -//================================================================================================= -// Garbage Collection methods: - - -void SimpSolver::relocAll(ClauseAllocator& to) -{ - if (!use_simplification) return; - - // All occurs lists: - // - for (int i = 0; i < nVars(); i++){ - vec& cs = occurs[i]; - for (int j = 0; j < cs.size(); j++) - ca.reloc(cs[j], to); - } - - // Subsumption queue: - // - for (int i = 0; i < subsumption_queue.size(); i++) - ca.reloc(subsumption_queue[i], to); - - // Temporary clause: - // - ca.reloc(bwdsub_tmpunit, to); -} - - -void SimpSolver::garbageCollect() -{ - // Initialize the next region to a size corresponding to the estimated utilization degree. This - // is not precise but should avoid some unnecessary reallocations for the new region: - ClauseAllocator to(ca.size() - ca.wasted()); - - cleanUpClauses(); - to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields. - relocAll(to); - Solver::relocAll(to); - if (verbosity >= 2) - printf("| Garbage collection: %12d bytes => %12d bytes |\n", - ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size); - to.moveTo(ca); -} diff --git a/src/sat/minisat/simp/SimpSolver.h b/src/sat/minisat/simp/SimpSolver.h deleted file mode 100644 index 49090181..00000000 --- a/src/sat/minisat/simp/SimpSolver.h +++ /dev/null @@ -1,197 +0,0 @@ -/************************************************************************************[SimpSolver.h] -Copyright (c) 2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_SimpSolver_h -#define Minisat_SimpSolver_h - -#include "mtl/Queue.h" -#include "core/Solver.h" - - -namespace Minisat { - -//================================================================================================= - - -class SimpSolver : public Solver { - public: - // Constructor/Destructor: - // - SimpSolver(); - ~SimpSolver(); - - // Problem specification: - // - Var newVar (bool polarity = true, bool dvar = true); - bool addClause (const vec& ps); - bool addEmptyClause(); // Add the empty clause to the solver. - bool addClause (Lit p); // Add a unit clause to the solver. - bool addClause (Lit p, Lit q); // Add a binary clause to the solver. - bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver. - bool addClause_( vec& ps); - bool substitute(Var v, Lit x); // Replace all occurences of v with x (may cause a contradiction). - - // Variable mode: - // - void setFrozen (Var v, bool b); // If a variable is frozen it will not be eliminated. - bool isEliminated(Var v) const; - - // Solving: - // - bool solve (const vec& assumps, bool do_simp = true, bool turn_off_simp = false); - lbool solveLimited(const vec& assumps, bool do_simp = true, bool turn_off_simp = false); - bool solve ( bool do_simp = true, bool turn_off_simp = false); - bool solve (Lit p , bool do_simp = true, bool turn_off_simp = false); - bool solve (Lit p, Lit q, bool do_simp = true, bool turn_off_simp = false); - bool solve (Lit p, Lit q, Lit r, bool do_simp = true, bool turn_off_simp = false); - bool eliminate (bool turn_off_elim = false); // Perform variable elimination based simplification. - - // Memory managment: - // - virtual void garbageCollect(); - - - // Generate a (possibly simplified) DIMACS file: - // -#if 0 - void toDimacs (const char* file, const vec& assumps); - void toDimacs (const char* file); - void toDimacs (const char* file, Lit p); - void toDimacs (const char* file, Lit p, Lit q); - void toDimacs (const char* file, Lit p, Lit q, Lit r); -#endif - - // Mode of operation: - // - int grow; // Allow a variable elimination step to grow by a number of clauses (default to zero). - int clause_lim; // Variables are not eliminated if it produces a resolvent with a length above this limit. - // -1 means no limit. - int subsumption_lim; // Do not check if subsumption against a clause larger than this. -1 means no limit. - double simp_garbage_frac; // A different limit for when to issue a GC during simplification (Also see 'garbage_frac'). - - bool use_asymm; // Shrink clauses by asymmetric branching. - bool use_rcheck; // Check if a clause is already implied. Prett costly, and subsumes subsumptions :) - bool use_elim; // Perform variable elimination. - - // Statistics: - // - int merges; - int asymm_lits; - int eliminated_vars; - - protected: - - // Helper structures: - // - struct ElimLt { - const vec& n_occ; - explicit ElimLt(const vec& no) : n_occ(no) {} - - // TODO: are 64-bit operations here noticably bad on 32-bit platforms? Could use a saturating - // 32-bit implementation instead then, but this will have to do for now. - uint64_t cost (Var x) const { return (uint64_t)n_occ[toInt(mkLit(x))] * (uint64_t)n_occ[toInt(~mkLit(x))]; } - bool operator()(Var x, Var y) const { return cost(x) < cost(y); } - - // TODO: investigate this order alternative more. - // bool operator()(Var x, Var y) const { - // int c_x = cost(x); - // int c_y = cost(y); - // return c_x < c_y || c_x == c_y && x < y; } - }; - - struct ClauseDeleted { - const ClauseAllocator& ca; - explicit ClauseDeleted(const ClauseAllocator& _ca) : ca(_ca) {} - bool operator()(const CRef& cr) const { return ca[cr].mark() == 1; } }; - - // Solver state: - // - int elimorder; - bool use_simplification; - vec elimclauses; - vec touched; - OccLists, ClauseDeleted> - occurs; - vec n_occ; - Heap elim_heap; - Queue subsumption_queue; - vec frozen; - vec eliminated; - int bwdsub_assigns; - int n_touched; - - // Temporaries: - // - CRef bwdsub_tmpunit; - - // Main internal methods: - // - lbool solve_ (bool do_simp = true, bool turn_off_simp = false); - bool asymm (Var v, CRef cr); - bool asymmVar (Var v); - void updateElimHeap (Var v); - void gatherTouchedClauses (); - bool merge (const Clause& _ps, const Clause& _qs, Var v, vec& out_clause); - bool merge (const Clause& _ps, const Clause& _qs, Var v, int& size); - bool backwardSubsumptionCheck (bool verbose = false); - bool eliminateVar (Var v); - void extendModel (); - - void removeClause (CRef cr); - bool strengthenClause (CRef cr, Lit l); - void cleanUpClauses (); - bool implied (const vec& c); - void relocAll (ClauseAllocator& to); -}; - - -//================================================================================================= -// Implementation of inline methods: - - -inline bool SimpSolver::isEliminated (Var v) const { return eliminated[v]; } -inline void SimpSolver::updateElimHeap(Var v) { - assert(use_simplification); - // if (!frozen[v] && !isEliminated(v) && value(v) == l_Undef) - if (elim_heap.inHeap(v) || (!frozen[v] && !isEliminated(v) && value(v) == l_Undef)) - elim_heap.update(v); } - - -inline bool SimpSolver::addClause (const vec& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); } -inline bool SimpSolver::addEmptyClause() { add_tmp.clear(); return addClause_(add_tmp); } -inline bool SimpSolver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); } -inline bool SimpSolver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); } -inline bool SimpSolver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); } -inline void SimpSolver::setFrozen (Var v, bool b) { frozen[v] = (char)b; if (use_simplification && !b) { updateElimHeap(v); } } - -inline bool SimpSolver::solve ( bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); return solve_(do_simp, turn_off_simp) == l_True; } -inline bool SimpSolver::solve (Lit p , bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_(do_simp, turn_off_simp) == l_True; } -inline bool SimpSolver::solve (Lit p, Lit q, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_(do_simp, turn_off_simp) == l_True; } -inline bool SimpSolver::solve (Lit p, Lit q, Lit r, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_(do_simp, turn_off_simp) == l_True; } -inline bool SimpSolver::solve (const vec& assumps, bool do_simp, bool turn_off_simp){ - budgetOff(); assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp) == l_True; } - -inline lbool SimpSolver::solveLimited (const vec& assumps, bool do_simp, bool turn_off_simp){ - assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp); } - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/utils/Makefile b/src/sat/minisat/utils/Makefile deleted file mode 100644 index 204cea54..00000000 --- a/src/sat/minisat/utils/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -EXEC = system_test -DEPDIR = mtl - -include $(MROOT)/mtl/template.mk diff --git a/src/sat/minisat/utils/Options.cc b/src/sat/minisat/utils/Options.cc deleted file mode 100644 index ec5a6e93..00000000 --- a/src/sat/minisat/utils/Options.cc +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************************[Options.cc] -Copyright (c) 2008-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#include "mtl/Sort.h" -#include "utils/Options.h" -#include "utils/ParseUtils.h" - -using namespace Minisat; - -void Minisat::parseOptions(int& argc, char** argv, bool strict) -{ - int i, j; - for (i = j = 1; i < argc; i++){ - const char* str = argv[i]; - if (match(str, "--") && match(str, Option::getHelpPrefixString()) && match(str, "help")){ - if (*str == '\0') - printUsageAndExit(argc, argv); - else if (match(str, "-verb")) - printUsageAndExit(argc, argv, true); - } else { - bool parsed_ok = false; - - for (int k = 0; !parsed_ok && k < Option::getOptionList().size(); k++){ - parsed_ok = Option::getOptionList()[k]->parse(argv[i]); - - // fprintf(stderr, "checking %d: %s against flag <%s> (%s)\n", i, argv[i], Option::getOptionList()[k]->name, parsed_ok ? "ok" : "skip"); - } - - if (!parsed_ok) - if (strict && match(argv[i], "-")) - fprintf(stderr, "ERROR! Unknown flag \"%s\". Use '--%shelp' for help.\n", argv[i], Option::getHelpPrefixString()), exit(1); - else - argv[j++] = argv[i]; - } - } - - argc -= (i - j); -} - - -void Minisat::setUsageHelp (const char* str){ Option::getUsageString() = str; } -void Minisat::setHelpPrefixStr (const char* str){ Option::getHelpPrefixString() = str; } -void Minisat::printUsageAndExit (int argc, char** argv, bool verbose) -{ - const char* usage = Option::getUsageString(); - if (usage != NULL) - fprintf(stderr, usage, argv[0]); - - sort(Option::getOptionList(), Option::OptionLt()); - - const char* prev_cat = NULL; - const char* prev_type = NULL; - - for (int i = 0; i < Option::getOptionList().size(); i++){ - const char* cat = Option::getOptionList()[i]->category; - const char* type = Option::getOptionList()[i]->type_name; - - if (cat != prev_cat) - fprintf(stderr, "\n%s OPTIONS:\n\n", cat); - else if (type != prev_type) - fprintf(stderr, "\n"); - - Option::getOptionList()[i]->help(verbose); - - prev_cat = Option::getOptionList()[i]->category; - prev_type = Option::getOptionList()[i]->type_name; - } - - fprintf(stderr, "\nHELP OPTIONS:\n\n"); - fprintf(stderr, " --%shelp Print help message.\n", Option::getHelpPrefixString()); - fprintf(stderr, " --%shelp-verb Print verbose help message.\n", Option::getHelpPrefixString()); - fprintf(stderr, "\n"); - exit(0); -} - diff --git a/src/sat/minisat/utils/Options.h b/src/sat/minisat/utils/Options.h deleted file mode 100644 index 9c1f4069..00000000 --- a/src/sat/minisat/utils/Options.h +++ /dev/null @@ -1,386 +0,0 @@ -/***************************************************************************************[Options.h] -Copyright (c) 2008-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_Options_h -#define Minisat_Options_h - -#include -#include -#include -#include - -#include "mtl/IntTypes.h" -#include "mtl/Vec.h" -#include "utils/ParseUtils.h" - -namespace Minisat { - -//================================================================================================== -// Top-level option parse/help functions: - - -extern void parseOptions (int& argc, char** argv, bool strict = false); -extern void printUsageAndExit(int argc, char** argv, bool verbose = false); -extern void setUsageHelp (const char* str); -extern void setHelpPrefixStr (const char* str); - - -//================================================================================================== -// Options is an abstract class that gives the interface for all types options: - - -class Option -{ - protected: - const char* name; - const char* description; - const char* category; - const char* type_name; - - static vec& getOptionList () { static vec options; return options; } - static const char*& getUsageString() { static const char* usage_str; return usage_str; } - static const char*& getHelpPrefixString() { static const char* help_prefix_str = ""; return help_prefix_str; } - - struct OptionLt { - bool operator()(const Option* x, const Option* y) { - int test1 = strcmp(x->category, y->category); - return test1 < 0 || test1 == 0 && strcmp(x->type_name, y->type_name) < 0; - } - }; - - Option(const char* name_, - const char* desc_, - const char* cate_, - const char* type_) : - name (name_) - , description(desc_) - , category (cate_) - , type_name (type_) - { - getOptionList().push(this); - } - - public: - virtual ~Option() {} - - virtual bool parse (const char* str) = 0; - virtual void help (bool verbose = false) = 0; - - friend void parseOptions (int& argc, char** argv, bool strict); - friend void printUsageAndExit (int argc, char** argv, bool verbose); - friend void setUsageHelp (const char* str); - friend void setHelpPrefixStr (const char* str); -}; - - -//================================================================================================== -// Range classes with specialization for floating types: - - -struct IntRange { - int begin; - int end; - IntRange(int b, int e) : begin(b), end(e) {} -}; - -struct Int64Range { - int64_t begin; - int64_t end; - Int64Range(int64_t b, int64_t e) : begin(b), end(e) {} -}; - -struct DoubleRange { - double begin; - double end; - bool begin_inclusive; - bool end_inclusive; - DoubleRange(double b, bool binc, double e, bool einc) : begin(b), end(e), begin_inclusive(binc), end_inclusive(einc) {} -}; - - -//================================================================================================== -// Double options: - - -class DoubleOption : public Option -{ - protected: - DoubleRange range; - double value; - - public: - DoubleOption(const char* c, const char* n, const char* d, double def = double(), DoubleRange r = DoubleRange(-HUGE_VAL, false, HUGE_VAL, false)) - : Option(n, d, c, ""), range(r), value(def) { - // FIXME: set LC_NUMERIC to "C" to make sure that strtof/strtod parses decimal point correctly. - } - - operator double (void) const { return value; } - operator double& (void) { return value; } - DoubleOption& operator=(double x) { value = x; return *this; } - - virtual bool parse(const char* str){ - const char* span = str; - - if (!match(span, "-") || !match(span, name) || !match(span, "=")) - return false; - - char* end; - double tmp = strtod(span, &end); - - if (end == NULL) - return false; - else if (tmp >= range.end && (!range.end_inclusive || tmp != range.end)){ - fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); - exit(1); - }else if (tmp <= range.begin && (!range.begin_inclusive || tmp != range.begin)){ - fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); - exit(1); } - - value = tmp; - // fprintf(stderr, "READ VALUE: %g\n", value); - - return true; - } - - virtual void help (bool verbose = false){ - fprintf(stderr, " -%-12s = %-8s %c%4.2g .. %4.2g%c (default: %g)\n", - name, type_name, - range.begin_inclusive ? '[' : '(', - range.begin, - range.end, - range.end_inclusive ? ']' : ')', - value); - if (verbose){ - fprintf(stderr, "\n %s\n", description); - fprintf(stderr, "\n"); - } - } -}; - - -//================================================================================================== -// Int options: - - -class IntOption : public Option -{ - protected: - IntRange range; - int32_t value; - - public: - IntOption(const char* c, const char* n, const char* d, int32_t def = int32_t(), IntRange r = IntRange(INT32_MIN, INT32_MAX)) - : Option(n, d, c, ""), range(r), value(def) {} - - operator int32_t (void) const { return value; } - operator int32_t& (void) { return value; } - IntOption& operator= (int32_t x) { value = x; return *this; } - - virtual bool parse(const char* str){ - const char* span = str; - - if (!match(span, "-") || !match(span, name) || !match(span, "=")) - return false; - - char* end; - int32_t tmp = strtol(span, &end, 10); - - if (end == NULL) - return false; - else if (tmp > range.end){ - fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); - exit(1); - }else if (tmp < range.begin){ - fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); - exit(1); } - - value = tmp; - - return true; - } - - virtual void help (bool verbose = false){ - fprintf(stderr, " -%-12s = %-8s [", name, type_name); - if (range.begin == INT32_MIN) - fprintf(stderr, "imin"); - else - fprintf(stderr, "%4d", range.begin); - - fprintf(stderr, " .. "); - if (range.end == INT32_MAX) - fprintf(stderr, "imax"); - else - fprintf(stderr, "%4d", range.end); - - fprintf(stderr, "] (default: %d)\n", value); - if (verbose){ - fprintf(stderr, "\n %s\n", description); - fprintf(stderr, "\n"); - } - } -}; - - -// Leave this out for visual C++ until Microsoft implements C99 and gets support for strtoll. -#ifndef _MSC_VER - -class Int64Option : public Option -{ - protected: - Int64Range range; - int64_t value; - - public: - Int64Option(const char* c, const char* n, const char* d, int64_t def = int64_t(), Int64Range r = Int64Range(INT64_MIN, INT64_MAX)) - : Option(n, d, c, ""), range(r), value(def) {} - - operator int64_t (void) const { return value; } - operator int64_t& (void) { return value; } - Int64Option& operator= (int64_t x) { value = x; return *this; } - - virtual bool parse(const char* str){ - const char* span = str; - - if (!match(span, "-") || !match(span, name) || !match(span, "=")) - return false; - - char* end; - int64_t tmp = strtoll(span, &end, 10); - - if (end == NULL) - return false; - else if (tmp > range.end){ - fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); - exit(1); - }else if (tmp < range.begin){ - fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); - exit(1); } - - value = tmp; - - return true; - } - - virtual void help (bool verbose = false){ - fprintf(stderr, " -%-12s = %-8s [", name, type_name); - if (range.begin == INT64_MIN) - fprintf(stderr, "imin"); - else - fprintf(stderr, "%4"PRIi64, range.begin); - - fprintf(stderr, " .. "); - if (range.end == INT64_MAX) - fprintf(stderr, "imax"); - else - fprintf(stderr, "%4"PRIi64, range.end); - - fprintf(stderr, "] (default: %"PRIi64")\n", value); - if (verbose){ - fprintf(stderr, "\n %s\n", description); - fprintf(stderr, "\n"); - } - } -}; -#endif - -//================================================================================================== -// String option: - - -class StringOption : public Option -{ - const char* value; - public: - StringOption(const char* c, const char* n, const char* d, const char* def = NULL) - : Option(n, d, c, ""), value(def) {} - - operator const char* (void) const { return value; } - operator const char*& (void) { return value; } - StringOption& operator= (const char* x) { value = x; return *this; } - - virtual bool parse(const char* str){ - const char* span = str; - - if (!match(span, "-") || !match(span, name) || !match(span, "=")) - return false; - - value = span; - return true; - } - - virtual void help (bool verbose = false){ - fprintf(stderr, " -%-10s = %8s\n", name, type_name); - if (verbose){ - fprintf(stderr, "\n %s\n", description); - fprintf(stderr, "\n"); - } - } -}; - - -//================================================================================================== -// Bool option: - - -class BoolOption : public Option -{ - bool value; - - public: - BoolOption(const char* c, const char* n, const char* d, bool v) - : Option(n, d, c, ""), value(v) {} - - operator bool (void) const { return value; } - operator bool& (void) { return value; } - BoolOption& operator=(bool b) { value = b; return *this; } - - virtual bool parse(const char* str){ - const char* span = str; - - if (match(span, "-")){ - bool b = !match(span, "no-"); - - if (strcmp(span, name) == 0){ - value = b; - return true; } - } - - return false; - } - - virtual void help (bool verbose = false){ - - fprintf(stderr, " -%s, -no-%s", name, name); - - for (uint32_t i = 0; i < 32 - strlen(name)*2; i++) - fprintf(stderr, " "); - - fprintf(stderr, " "); - fprintf(stderr, "(default: %s)\n", value ? "on" : "off"); - if (verbose){ - fprintf(stderr, "\n %s\n", description); - fprintf(stderr, "\n"); - } - } -}; - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/utils/Options.or b/src/sat/minisat/utils/Options.or deleted file mode 100644 index 7015117aaa5887fc063bc871bfe8136e0edec196..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45312 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 diff --git a/src/sat/minisat/utils/ParseUtils.h b/src/sat/minisat/utils/ParseUtils.h deleted file mode 100644 index d3071649..00000000 --- a/src/sat/minisat/utils/ParseUtils.h +++ /dev/null @@ -1,122 +0,0 @@ -/************************************************************************************[ParseUtils.h] -Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_ParseUtils_h -#define Minisat_ParseUtils_h - -#include -#include - -#include - -namespace Minisat { - -//------------------------------------------------------------------------------------------------- -// A simple buffered character stream class: - -static const int buffer_size = 1048576; - - -class StreamBuffer { - gzFile in; - unsigned char buf[buffer_size]; - int pos; - int size; - - void assureLookahead() { - if (pos >= size) { - pos = 0; - size = gzread(in, buf, sizeof(buf)); } } - -public: - explicit StreamBuffer(gzFile i) : in(i), pos(0), size(0) { assureLookahead(); } - - int operator * () const { return (pos >= size) ? EOF : buf[pos]; } - void operator ++ () { pos++; assureLookahead(); } - int position () const { return pos; } -}; - - -//------------------------------------------------------------------------------------------------- -// End-of-file detection functions for StreamBuffer and char*: - - -static inline bool isEof(StreamBuffer& in) { return *in == EOF; } -static inline bool isEof(const char* in) { return *in == '\0'; } - -//------------------------------------------------------------------------------------------------- -// Generic parse functions parametrized over the input-stream type. - - -template -static void skipWhitespace(B& in) { - while ((*in >= 9 && *in <= 13) || *in == 32) - ++in; } - - -template -static void skipLine(B& in) { - for (;;){ - if (isEof(in)) return; - if (*in == '\n') { ++in; return; } - ++in; } } - - -template -static int parseInt(B& in) { - int val = 0; - bool neg = false; - skipWhitespace(in); - if (*in == '-') neg = true, ++in; - else if (*in == '+') ++in; - if (*in < '0' || *in > '9') fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", *in), exit(3); - while (*in >= '0' && *in <= '9') - val = val*10 + (*in - '0'), - ++in; - return neg ? -val : val; } - - -// String matching: in case of a match the input iterator will be advanced the corresponding -// number of characters. -template -static bool match(B& in, const char* str) { - int i; - for (i = 0; str[i] != '\0'; i++) - if (in[i] != str[i]) - return false; - - in += i; - - return true; -} - -// String matching: consumes characters eagerly, but does not require random access iterator. -template -static bool eagerMatch(B& in, const char* str) { - for (; *str != '\0'; ++str, ++in) - if (*str != *in) - return false; - return true; } - - -//================================================================================================= -} - -#endif diff --git a/src/sat/minisat/utils/System.cc b/src/sat/minisat/utils/System.cc deleted file mode 100644 index a7cf53f5..00000000 --- a/src/sat/minisat/utils/System.cc +++ /dev/null @@ -1,95 +0,0 @@ -/***************************************************************************************[System.cc] -Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#include "utils/System.h" - -#if defined(__linux__) - -#include -#include - -using namespace Minisat; - -// TODO: split the memory reading functions into two: one for reading high-watermark of RSS, and -// one for reading the current virtual memory size. - -static inline int memReadStat(int field) -{ - char name[256]; - pid_t pid = getpid(); - int value; - - sprintf(name, "/proc/%d/statm", pid); - FILE* in = fopen(name, "rb"); - if (in == NULL) return 0; - - for (; field >= 0; field--) - if (fscanf(in, "%d", &value) != 1) - printf("ERROR! Failed to parse memory statistics from \"/proc\".\n"), exit(1); - fclose(in); - return value; -} - - -static inline int memReadPeak(void) -{ - char name[256]; - pid_t pid = getpid(); - - sprintf(name, "/proc/%d/status", pid); - FILE* in = fopen(name, "rb"); - if (in == NULL) return 0; - - // Find the correct line, beginning with "VmPeak:": - int peak_kb = 0; - while (!feof(in) && fscanf(in, "VmPeak: %d kB", &peak_kb) != 1) - while (!feof(in) && fgetc(in) != '\n') - ; - fclose(in); - - return peak_kb; -} - -double Minisat::memUsed() { return (double)memReadStat(0) * (double)getpagesize() / (1024*1024); } -double Minisat::memUsedPeak() { - double peak = memReadPeak() / 1024; - return peak == 0 ? memUsed() : peak; } - -#elif defined(__FreeBSD__) - -double Minisat::memUsed(void) { - struct rusage ru; - getrusage(RUSAGE_SELF, &ru); - return (double)ru.ru_maxrss / 1024; } -double MiniSat::memUsedPeak(void) { return memUsed(); } - - -#elif defined(__APPLE__) -#include - -double Minisat::memUsed(void) { - malloc_statistics_t t; - malloc_zone_statistics(NULL, &t); - return (double)t.max_size_in_use / (1024*1024); } - -#else -double Minisat::memUsed() { - return 0; } -#endif diff --git a/src/sat/minisat/utils/System.h b/src/sat/minisat/utils/System.h deleted file mode 100644 index 17581927..00000000 --- a/src/sat/minisat/utils/System.h +++ /dev/null @@ -1,60 +0,0 @@ -/****************************************************************************************[System.h] -Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson -Copyright (c) 2007-2010, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Minisat_System_h -#define Minisat_System_h - -#if defined(__linux__) -#include -#endif - -#include "mtl/IntTypes.h" - -//------------------------------------------------------------------------------------------------- - -namespace Minisat { - -static inline double cpuTime(void); // CPU-time in seconds. -extern double memUsed(); // Memory in mega bytes (returns 0 for unsupported architectures). -extern double memUsedPeak(); // Peak-memory in mega bytes (returns 0 for unsupported architectures). - -} - -//------------------------------------------------------------------------------------------------- -// Implementation of inline functions: - -#if defined(_MSC_VER) || defined(__MINGW32__) -#include - -static inline double Minisat::cpuTime(void) { return (double)clock() / CLOCKS_PER_SEC; } - -#else -#include -#include -#include - -static inline double Minisat::cpuTime(void) { - struct rusage ru; - getrusage(RUSAGE_SELF, &ru); - return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; } - -#endif - -#endif diff --git a/src/sat/minisat/utils/System.or b/src/sat/minisat/utils/System.or deleted file mode 100644 index 9e266370c164cc2a9713cb7eb5bf3e7cae209ea1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10488 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 F{2P2 -#include -// #include "Solver.h" -#include -#include "sat/bsat/satSolver.h" - -using namespace std; - -/********** MiniSAT_Solver **********/ -enum SatResult -{ - UNSAT = 0, - SAT, - UNDECIDED -}; - -typedef int Var; - -class SatSolver -{ - public : - SatSolver():_solver(0) { } - ~SatSolver() { if (_solver) delete _solver; } - - // Solver initialization and reset - void initialize() { - reset(); - if (_curVar == 0) { sat_solver_addvar(_solver); ++_curVar; } - } - void reset() { - if (_solver) delete _solver; - _solver = new sat_solver(); - _assump.clear(); //_curVar = 0; - } - - // // Constructing proof model - // Return the Var ID of the new Var - inline Var newVar() { sat_solver_addvar(_solver); return ++_curVar;; } - // fa/fb = true if it is inverted - void addAigCNF(Var vf, Var va, bool fa, Var vb, bool fb) { - sat_solver_add_and( _solver, vf, va, vb, va, vb, 0 ); - // vec lits; - // Lit lf = Lit(vf); - // Lit la = fa? ~Lit(va): Lit(va); - // Lit lb = fb? ~Lit(vb): Lit(vb); - // lits.push(la); lits.push(~lf); - // _solver->addClause(lits); lits.clear(); - // lits.push(lb); lits.push(~lf); - // _solver->addClause(lits); lits.clear(); - // lits.push(~la); lits.push(~lb); lits.push(lf); - // _solver->addClause(lits); lits.clear(); - } - // // fa/fb = true if it is inverted - void addXorCNF(Var vf, Var va, bool fa, Var vb, bool fb) { - sat_solver_add_xor( _solver, vf, va, vb, (fa ^ fb) ? 1 : 0 ); - // vec lits; - // Lit lf = Lit(vf); - // Lit la = fa? ~Lit(va): Lit(va); - // Lit lb = fb? ~Lit(vb): Lit(vb); - // lits.push(~la); lits.push( lb); lits.push( lf); - // _solver->addClause(lits); lits.clear(); - // lits.push( la); lits.push(~lb); lits.push( lf); - // _solver->addClause(lits); lits.clear(); - // lits.push( la); lits.push( lb); lits.push(~lf); - // _solver->addClause(lits); lits.clear(); - // lits.push(~la); lits.push(~lb); lits.push(~lf); - // _solver->addClause(lits); lits.clear(); - } - - // For incremental proof, use "assumeSolve()" - void assumeRelease() { _assump.clear(); } - void assumeProperty(Var prop, bool val) { - _assump.push_back(toLitCond(prop, val)); - } - SatResult assumpSolve() { - return lbool2SatResult(sat_solver_solve(_solver, &_assump.front(), &_assump.back(), 0, 0, 0, 0)); - } - - // For one time proof, use "solve" - void assertProperty(Var prop, bool val) { - lit Lits[1]; - Lits[0] = Abc_Var2Lit(prop, val); - sat_solver_addclause(_solver, Lits, Lits+1); - // _solver->addUnit(val? Lit(prop): ~Lit(prop)); - } - bool solve() { return lbool2bool(sat_solver_solve(_solver, 0, 0, 0, 0, 0, 0)); } - - // Functions about Reporting - // Return 1/0/-1; -1 means unknown value - int getValue(Var v) const { - return sat_solver_get_var_value(_solver, v); } - void printStats() const { Sat_SolverPrintStats( stdout, _solver ); } - - private : - sat_solver *_solver; // Pointer to a Minisat solver - Var _curVar; // Variable currently - vector _assump; // Assumption List for assumption solve - - static SatResult lbool2SatResult(lbool b) { - if (b == l_False) return UNSAT; - if (b == l_True) return SAT; - return UNDECIDED; - } - static bool lbool2bool(lbool b) { - if (b == l_False) return false; - if (b == l_True) return true; - } -}; - -#endif // SAT_H - diff --git a/src/sat/test/File.cpp b/src/sat/test/File.cpp deleted file mode 100644 index eb113245..00000000 --- a/src/sat/test/File.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include "File.h" - -void File::open(int file_descr, FileMode m, bool own) -{ - if (fd != -1) ::close(fd); - fd = file_descr; - mode = m; - own_fd = own; - pos = 0; - buf = xmalloc(File_BufSize); - if (mode == READ) size = read(fd, buf, File_BufSize); - else size = -1; -} - -void File::open(cchar* name, cchar* mode_) -{ - if (fd != -1) ::close(fd); - bool has_r = strchr(mode_, 'r') != NULL; - bool has_w = strchr(mode_, 'w') != NULL; - bool has_a = strchr(mode_, 'a') != NULL; - bool has_p = strchr(mode_, '+') != NULL; - bool has_x = strchr(mode_, 'x') != NULL; - assert(!(has_r && has_w)); - assert(has_r || has_w || has_a); - - int mask = 0; - if (has_p) mask |= O_RDWR; - else if (has_r) mask |= O_RDONLY; - else mask |= O_WRONLY; - - if (!has_r) mask |= O_CREAT; - if (has_w) mask |= O_TRUNC; - if (has_x) mask |= O_EXCL; - - fd = open64(name, mask, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); - - if (fd != -1){ - mode = has_r ? READ : WRITE; - own_fd = true; - pos = 0; - if (has_a) lseek64(fd, 0, SEEK_END); - buf = xmalloc(File_BufSize); - if (mode == READ) size = read(fd, buf, File_BufSize); - else size = -1; - } -} - - -void File::close(void) -{ - if (fd == -1) return; - if (mode == WRITE) - flush(); - xfree(buf); buf = NULL; - if (own_fd) - ::close(fd); - fd = -1; -} - -void File::seek(int64 file_pos, int whence) -{ - if (mode == WRITE){ - flush(); - pos = 0; - lseek64(fd, file_pos, whence); - }else{ - if (whence == SEEK_CUR) lseek64(fd, file_pos - (size - pos), SEEK_CUR); - else lseek64(fd, file_pos, whence); - size = read(fd, buf, File_BufSize); - pos = 0; - } -} - -int64 File::tell(void) -{ - if (mode == WRITE) - return lseek64(fd, 0, SEEK_CUR); - else - return lseek64(fd, 0, SEEK_CUR) - (size - pos); -} - - -//================================================================================================= -// Marshaling: - - -void putUInt(File& out, uint64 val) -{ - if (val < 0x20000000){ - uint v = (uint)val; - if (v < 0x80) - out.putChar(v); - else{ - if (v < 0x2000) - out.putChar(0x80 | (v >> 8)), - out.putChar((uchar)v); - else if (v < 0x200000) - out.putChar(0xA0 | (v >> 16)), - out.putChar((uchar)(v >> 8)), - out.putChar((uchar)v); - else - out.putChar((v >> 24) | 0xC0), - out.putChar((uchar)(v >> 16)), - out.putChar((uchar)(v >> 8)), - out.putChar((uchar)v); - } - }else - out.putChar(0xE0), - out.putChar((uchar)(val >> 56)), - out.putChar((uchar)(val >> 48)), - out.putChar((uchar)(val >> 40)), - out.putChar((uchar)(val >> 32)), - out.putChar((uchar)(val >> 24)), - out.putChar((uchar)(val >> 16)), - out.putChar((uchar)(val >> 8)), - out.putChar((uchar)val); -} - - -uint64 getUInt(File& in) -// throw(Exception_EOF) -//warning: dynamic exception specifications are deprecated in C++11 [-Wdeprecated] -{ - uint byte0, byte1, byte2, byte3, byte4, byte5, byte6, byte7; - byte0 = in.getChar(); - if (byte0 == (uint)EOF) - throw Exception_EOF(); - if (!(byte0 & 0x80)) - return byte0; - else{ - switch ((byte0 & 0x60) >> 5){ - case 0: - byte1 = in.getChar(); - return ((byte0 & 0x1F) << 8) | byte1; - case 1: - byte1 = in.getChar(); - byte2 = in.getChar(); - return ((byte0 & 0x1F) << 16) | (byte1 << 8) | byte2; - case 2: - byte1 = in.getChar(); - byte2 = in.getChar(); - byte3 = in.getChar(); - return ((byte0 & 0x1F) << 24) | (byte1 << 16) | (byte2 << 8) | byte3; - default: - byte0 = in.getChar(); - byte1 = in.getChar(); - byte2 = in.getChar(); - byte3 = in.getChar(); - byte4 = in.getChar(); - byte5 = in.getChar(); - byte6 = in.getChar(); - byte7 = in.getChar(); - return ((uint64)((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3) << 32) - | (uint64)((byte4 << 24) | (byte5 << 16) | (byte6 << 8) | byte7); - } - } -} diff --git a/src/sat/test/File.h b/src/sat/test/File.h deleted file mode 100644 index 931a9542..00000000 --- a/src/sat/test/File.h +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef File_h -#define File_h - -#ifndef Global_h -#include "Global.h" -#endif - -#include -#include -#include - -#ifndef _LARGEFILE64_SOURCE -#define lseek64 ::lseek -#define open64 ::open -#endif - - -//================================================================================================= -// A buffered file abstraction with only 'putChar()' and 'getChar()'. - - -#define File_BufSize 1024 // A small buffer seem to work just as fine as a big one (at least under Linux) - -enum FileMode { READ, WRITE }; - -class Exception_EOF {}; - - -// WARNING! This code is not thoroughly tested. May contain bugs! - -class File { - int fd; // Underlying file descriptor. - FileMode mode; // Reading or writing. - uchar* buf; // Read or write buffer. - int size; // Size of buffer (at end of file, less than 'File_BufSize'). - int pos; // Current position in buffer - bool own_fd; // Do we own the file descriptor? If so, will close file in destructor. - -public: - #define DEFAULTS fd(-1), mode(READ), buf(NULL), size(-1), pos(0), own_fd(true) - File(void) : DEFAULTS {} - - File(int fd, FileMode mode, bool own_fd = true) : DEFAULTS { - open(fd, mode, own_fd); } - - File(cchar* name, cchar* mode) : DEFAULTS { - open(name, mode); } - #undef DEFAULTS - - ~File(void) { - close(); } - - void open(int fd, FileMode mode, bool own_fd = true); // Low-level open. If 'own_fd' is FALSE, descriptor will not be closed by destructor. - void open(cchar* name, cchar* mode); // FILE* compatible interface. - void close(void); - - bool null(void) { // TRUE if no file is opened. - return fd == -1; } - - int releaseDescriptor(void) { // Don't run UNIX function 'close()' on descriptor in 'File's 'close()'. - if (mode == READ) - lseek64(fd, pos - size, SEEK_CUR); - own_fd = false; - return fd; } - - FileMode getMode(void) { - return mode; } - - void setMode(FileMode m) { - if (m == mode) return; - if (m == READ){ - flush(); - size = read(fd, buf, File_BufSize); - }else{ - lseek64(fd, pos - size, SEEK_CUR); - size = -1; } - mode = m; - pos = 0; } - - int getCharQ(void) { // Quick version with minimal overhead -- don't call this in the wrong mode! - #ifdef PARANOID - assert(mode == READ); - #endif - if (pos < size) return (uchar)buf[pos++]; - if (size < File_BufSize) return EOF; - size = read(fd, buf, File_BufSize); - pos = 0; - if (size == 0) return EOF; - return (uchar)buf[pos++]; } - - int putCharQ(int chr) { // Quick version with minimal overhead -- don't call this in the wrong mode! - #ifdef PARANOID - assert(mode == WRITE); - #endif - if (pos == File_BufSize) - write(fd, buf, File_BufSize), - pos = 0; - return buf[pos++] = (uchar)chr; } - - int getChar(void) { - if (mode == WRITE) setMode(READ); - return getCharQ(); } - - int putChar(int chr) { - if (mode == READ) setMode(WRITE); - return putCharQ(chr); } - - bool eof(void) { - assert(mode == READ); - if (pos < size) return false; - if (size < File_BufSize) return true; - size = read(fd, buf, File_BufSize); - pos = 0; - if (size == 0) return true; - return false; } - - void flush(void) { - assert(mode == WRITE); - write(fd, buf, pos); - pos = 0; } - - void seek(int64 pos, int whence = SEEK_SET); - int64 tell(void); -}; - - -//================================================================================================= -// Some nice helper functions: - - -void putUInt (File& out, uint64 val); -//uint64 getUInt (File& in) throw(Exception_EOF); -//warning: dynamic exception specifications are deprecated in C++11 [-Wdeprecated] -uint64 getUInt (File& in); -static inline uint64 encode64(int64 val) { return (val >= 0) ? (uint64)val << 1 : (((uint64)(~val) << 1) | 1); } -static inline int64 decode64(uint64 val) { return ((val & 1) == 0) ? (int64)(val >> 1) : ~(int64)(val >> 1); } -static inline void putInt (File& out, int64 val) { putUInt(out, encode64(val)); } -static inline uint64 getInt (File& in) { return decode64(getUInt(in)); } - - -//================================================================================================= -#endif diff --git a/src/sat/test/Global.h b/src/sat/test/Global.h deleted file mode 100644 index 14dbfe85..00000000 --- a/src/sat/test/Global.h +++ /dev/null @@ -1,278 +0,0 @@ -/****************************************************************************************[Global.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Global_h -#define Global_h - -#include -#include -#include -#include -#include -#include -#include - - -//================================================================================================= -// Basic Types & Minor Things: - - -#ifdef _MSC_VER -typedef INT64 int64; -typedef UINT64 uint64; -typedef INT_PTR intp; -typedef UINT_PTR uintp; -#define I64_fmt "I64d" -#else -typedef long long int64; -typedef unsigned long long uint64; -typedef __PTRDIFF_TYPE__ intp; -typedef unsigned __PTRDIFF_TYPE__ uintp; -#define I64_fmt "lld" -#endif -typedef unsigned char uchar; -typedef const char cchar; - -// FIXED BY RIC -#ifndef uint -typedef unsigned int uint; -#endif - -template static inline T min(T x, T y) { return (x < y) ? x : y; } -template static inline T max(T x, T y) { return (x > y) ? x : y; } - -template struct STATIC_ASSERTION_FAILURE {}; -//template <> struct STATIC_ASSERTION_FAILURE{}; -#define TEMPLATE_FAIL STATIC_ASSERTION_FAILURE() - - -//================================================================================================= -// 'malloc()'-style memory allocation -- never returns NULL; aborts instead: - - -template static inline T* xmalloc(size_t size) { - T* tmp = (T*)malloc(size * sizeof(T)); - assert(size == 0 || tmp != NULL); - return tmp; } - -template static inline T* xrealloc(T* ptr, size_t size) { - T* tmp = (T*)realloc((void*)ptr, size * sizeof(T)); - assert(size == 0 || tmp != NULL); - return tmp; } - -template static inline void xfree(T *ptr) { - if (ptr != NULL) free((void*)ptr); } - - -//================================================================================================= -// Random numbers: - - -// Returns a random float 0 <= x < 1. Seed must never be 0. -static inline double drand(double& seed) { - seed *= 1389796; - int 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); } - - -//================================================================================================= -// Time and Memory: - - -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#ifdef _MSC_VER - -#include - -static inline double cpuTime(void) { - return (double)clock() / CLOCKS_PER_SEC; } - -static inline int64 memUsed() { - return 0; } - -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#else - -#include -#include -#include - -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; } - -static inline int memReadStat(int field) -{ - char name[256]; - pid_t pid = getpid(); - sprintf(name, "/proc/%d/statm", pid); - FILE* in = fopen(name, "rb"); - if (in == NULL) return 0; - int value; - for (; field >= 0; field--) - fscanf(in, "%d", &value); - fclose(in); - return value; -} - -static inline int64 memUsed() { return (int64)memReadStat(0) * (int64)getpagesize(); } - -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#endif - - - -//================================================================================================= -// 'vec' -- automatically resizable arrays (via 'push()' method): - - -// NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc) - -template -class vec { - T* data; - int sz; - int cap; - - void init(int size, const T& pad); - void grow(int min_cap); - -public: - // Types: - typedef int Key; - typedef T Datum; - - // Constructors: - vec(void) : data(NULL) , sz(0) , cap(0) { } - vec(int size) : data(NULL) , sz(0) , cap(0) { growTo(size); } - vec(int size, const T& pad) : data(NULL) , sz(0) , cap(0) { growTo(size, pad); } - vec(T* array, int size) : data(array), sz(size), cap(size) { } // (takes ownership of array -- will be deallocated with 'xfree()') - ~vec(void) { clear(true); } - - // Ownership of underlying array: - T* release (void) { T* ret = data; data = NULL; sz = 0; cap = 0; return ret; } - operator T* (void) { return data; } // (unsafe but convenient) - operator const T* (void) const { return data; } - - // Size operations: - int size (void) const { return sz; } - void shrink (int nelems) { assert(nelems <= sz); for (int i = 0; i < nelems; i++) sz--, data[sz].~T(); } - void pop (void) { sz--, data[sz].~T(); } - void growTo (int size); - void growTo (int size, const T& pad); - void clear (bool dealloc = false); - void capacity (int size) { grow(size); } - - // Stack interface: - void push (void) { if (sz == cap) grow(sz+1); new (&data[sz]) T() ; sz++; } - void push (const T& elem) { if (sz == cap) grow(sz+1); new (&data[sz]) T(elem); sz++; } - const T& last (void) const { return data[sz-1]; } - T& last (void) { return data[sz-1]; } - - // Vector interface: - const T& operator [] (int index) const { return data[index]; } - T& operator [] (int index) { return data[index]; } - - // Don't allow copying (error prone): - vec& operator = (vec& other) { TEMPLATE_FAIL; } - vec (vec& other) { TEMPLATE_FAIL; } - - // Duplicatation (preferred instead): - void copyTo(vec& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) new (©[i]) T(data[i]); } - void moveTo(vec& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; } -}; - -template -void vec::grow(int min_cap) { - if (min_cap <= cap) return; - if (cap == 0) cap = (min_cap >= 2) ? min_cap : 2; - else do cap = (cap*3+1) >> 1; while (cap < min_cap); - data = xrealloc(data, cap); } - -template -void vec::growTo(int size, const T& pad) { - if (sz >= size) return; - grow(size); - for (int i = sz; i < size; i++) new (&data[i]) T(pad); - sz = size; } - -template -void vec::growTo(int size) { - if (sz >= size) return; - grow(size); - for (int i = sz; i < size; i++) new (&data[i]) T(); - sz = size; } - -template -void vec::clear(bool dealloc) { - if (data != NULL){ - for (int i = 0; i < sz; i++) data[i].~T(); - sz = 0; - if (dealloc) xfree(data), data = NULL, cap = 0; } } - - -//================================================================================================= -// Lifted booleans: - - -class lbool { - int value; - explicit lbool(int v) : value(v) { } - -public: - lbool() : value(0) { } - lbool(bool x) : value((int)x*2-1) { } - int toInt(void) const { return value; } - - bool operator == (const lbool& other) const { return value == other.value; } - bool operator != (const lbool& other) const { return value != other.value; } - lbool operator ~ (void) const { return lbool(-value); } - - friend int toInt (lbool l); - friend lbool toLbool(int v); -}; -inline int toInt (lbool l) { return l.toInt(); } -inline lbool toLbool(int v) { return lbool(v); } - -const lbool l_True = toLbool( 1); -const lbool l_False = toLbool(-1); -const lbool l_Undef = toLbool( 0); - - -//================================================================================================= -// Relation operators -- extend definitions from '==' and '<' - - -#ifndef __SGI_STL_INTERNAL_RELOPS // (be aware of SGI's STL implementation...) -#define __SGI_STL_INTERNAL_RELOPS -template static inline bool operator != (const T& x, const T& y) { return !(x == y); } -template static inline bool operator > (const T& x, const T& y) { return y < x; } -template static inline bool operator <= (const T& x, const T& y) { return !(y < x); } -template static inline bool operator >= (const T& x, const T& y) { return !(x < y); } -#endif - - -//================================================================================================= -#endif diff --git a/src/sat/test/Heap.h b/src/sat/test/Heap.h deleted file mode 100644 index cddf6693..00000000 --- a/src/sat/test/Heap.h +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************************[Heap.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Heap_h -#define Heap_h - - -//================================================================================================= - - -static inline int left (int i) { return i+i; } -static inline int right (int i) { return i+i + 1; } -static inline int parent(int i) { return i >> 1; } - -template -class Heap { - public: - C comp; - vec heap; // heap of ints - vec indices; // int -> index in heap - - inline void percolateUp(int i) - { - int x = heap[i]; - while (parent(i) != 0 && comp(x,heap[parent(i)])){ - heap[i] = heap[parent(i)]; - indices[heap[i]] = i; - i = parent(i); - } - heap [i] = x; - indices[x] = i; - } - - inline void percolateDown(int i) - { - int x = heap[i]; - while (left(i) < heap.size()){ - int child = right(i) < heap.size() && comp(heap[right(i)],heap[left(i)]) ? right(i) : left(i); - if (!comp(heap[child],x)) break; - heap[i] = heap[child]; - indices[heap[i]] = i; - i = child; - } - heap [i] = x; - indices[x] = i; - } - - bool ok(int n) { return n >= 0 && n < (int)indices.size(); } - - public: - Heap(C c) : comp(c) { heap.push(-1); } - - void setBounds (int size) { assert(size >= 0); indices.growTo(size,0); } - bool inHeap (int n) { assert(ok(n)); return indices[n] != 0; } - void increase (int n) { assert(ok(n)); assert(inHeap(n)); percolateUp(indices[n]); } - bool empty () { return heap.size() == 1; } - - void insert(int n) { - assert(ok(n)); - indices[n] = heap.size(); - heap.push(n); - percolateUp(indices[n]); } - - int getmin() { - int r = heap[1]; - heap[1] = heap.last(); - indices[heap[1]] = 1; - indices[r] = 0; - heap.pop(); - if (heap.size() > 1) - percolateDown(1); - return r; } - - bool heapProperty() { - return heapProperty(1); } - - bool heapProperty(int i) { - return (size_t)i >= heap.size() - || ((parent(i) == 0 || !comp(heap[i],heap[parent(i)])) && heapProperty(left(i)) && heapProperty(right(i))); } -}; - - -//================================================================================================= -#endif diff --git a/src/sat/test/Makefile b/src/sat/test/Makefile deleted file mode 100644 index 190aee12..00000000 --- a/src/sat/test/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -andTest: clean File.o Proof.o Solver.o andTest.o - g++ -o $@ -std=c++11 -g File.o Proof.o Solver.o andTest.o - -File.o: File.cpp - g++ -c -std=c++11 -g File.cpp - -Proof.o: Proof.cpp - g++ -c -std=c++11 -g Proof.cpp - -Solve.o: Solver.cpp - g++ -c -std=c++11 -g Solver.cpp - -andTest.o: andTest.cpp - g++ -c -std=c++11 -g andTest.cpp - -clean: - rm -f *.o diff --git a/src/sat/test/Makefile2 b/src/sat/test/Makefile2 deleted file mode 100644 index cc6b13ec..00000000 --- a/src/sat/test/Makefile2 +++ /dev/null @@ -1,17 +0,0 @@ -satTest2: clean File.o Proof.o Solver.o satTest2.o - g++ -o $@ -g File.o Proof.o Solver.o satTest2.o - -File.o: File.cpp - g++ -c -g File.cpp - -Proof.o: Proof.cpp - g++ -c -g Proof.cpp - -Solve.o: Solver.cpp - g++ -c -g Solver.cpp - -satTest2.o: satTest2.cpp - g++ -c -g satTest2.cpp - -clean: - rm -f *.o diff --git a/src/sat/test/Makefile3 b/src/sat/test/Makefile3 deleted file mode 100644 index ad33223f..00000000 --- a/src/sat/test/Makefile3 +++ /dev/null @@ -1,17 +0,0 @@ -satTest3: clean File.o Proof.o Solver.o satTest.o - g++ -o $@ -g File.o Proof.o Solver.o satTest.o - -File.o: File.cpp - g++ -c -g File.cpp - -Proof.o: Proof.cpp - g++ -c -g Proof.cpp - -Solve.o: Solver.cpp - g++ -c -g Solver.cpp - -satTest.o: satTest.cpp - g++ -c -g satTest.cpp - -clean: - rm -f *.o diff --git a/src/sat/test/NO_USE/itp.h b/src/sat/test/NO_USE/itp.h deleted file mode 100644 index d38b492e..00000000 --- a/src/sat/test/NO_USE/itp.h +++ /dev/null @@ -1,228 +0,0 @@ -#ifndef ITP_H -#define ITP_H - -#include "Proof.h" -#include "Solver.h" -#include "strash.h" -//#include - -//==== ITP ====== [ Abstract class ] ========================================== -// is a ProofTraverser -// has setType to set the vartype label -//============================================================================= - -class ITP : virtual public ProofTraverser -{ - -public: - static const int VarA = -1 ; - static const int VarB = -2 ; - static const int VarUnknow = -3 ; - -protected: - - vector _subITP; - bool _inv; - -public: - vector base; - - void set( bool i ){_inv = i; } - ITP(){} -}; - -//==== Boolean AigPtr Calculator ============================================== -// Boolean interface -//============================================================================= - -class AigCal -{ -public: - virtual ~AigCal(){}; - virtual AigPtr AND( const AigPtr & a , const AigPtr & b)= 0 ; - virtual AigPtr OR( const AigPtr & a , const AigPtr & b){ return ~( AND ( (~a) , (~b)) );} - virtual AigPtr ITE(const AigPtr & c , const AigPtr & t , const AigPtr & f){ return OR( AND(c,t),AND(~c,f)) ; } -}; - - -//==== PITP ======== [ Abstract class ] ======================================= - -class PITP : virtual public ITP , virtual public AigCal , virtual public ProofTraverser -{ -public: - /// constructor - PITP():ITP(){} - virtual ~PITP(){} - - /// interpolation usage - virtual void root(const vec & c , bool A); - virtual void chain(const vec & cs , const vec & xs ); -private: - AigPtr resolve(AigPtr a ,Lit v, AigPtr b); - -}; - -//==== MITP ===== [ Abstract class ] ========================================== - -class MITP : virtual public ITP , virtual public AigCal , virtual public ProofTraverser -{ -public: - MITP( ) :ITP(){} - virtual ~MITP(){} - - virtual void root( const vec & c , bool A); - virtual void chain( const vec & cs , const vec & xs); -private: - AigPtr resolve( AigPtr a, Lit v , AigPtr b ); -}; - -//==== InterpolantITP ========================================================= -// a interface to wrapping SITP and MutiSITP -//============================================================================= -class InterpolantITP : virtual public ProofTraverser -{ -public : - virtual AigPtr interpolant() =0 ; -}; - - - -//==== SITP ====== [] ========================================================= -// is a ITP , AigCal , InterpolantITP -// have StrashMgr reference , and a final construct interpolant -//============================================================================= -class SITP : virtual public ITP , virtual public AigCal , virtual public InterpolantITP -{ - StrashCkt & _ref; - AigPtr _interpolant; - -public: - - //--- construct & destruct --- - SITP( StrashCkt & k ,bool p); - virtual ~SITP(){} - - //--- concrete func of AigCal --- - virtual AigPtr AND( const AigPtr & a , const AigPtr & b){return _ref.createAND( a, b);} - - //--- concreate func of ITP --- - virtual void done(); - - //--- concrete func of InterpolantITP --- - virtual AigPtr interpolant(){return _interpolant;} - - //--- utilization func --- - virtual unsigned size(); -}; - -//==== MultiITP ====== [] ====================================================== -// Wrap multi ITP container as to perform online interpolant construction -//============================================================================= -class MultiSITP : virtual public ProofTraverser -{ - - vector _sitp; - -public : - //--- construct & destruct - MultiSITP( unsigned a ); - virtual ~MultiSITP(); - void set( unsigned i , SITP * s ){ _sitp[i] = s ;} - -// SITP * itp(unsigned i){ return _sitp[i] ;} - SITP & operator[]( unsigned i ){ return * (_sitp[i] ); } - - //--- concrete func of ProofTraverser --- - virtual void root (const vec& c , bool A); - virtual void chain (const vec& cs, const vec& xs); - virtual void deleted(ClauseId c); - virtual void done (); -}; - - -//==== SMITP ====== [ Concrete class ] ======================================== -// is a McMillan construction structure hash circuit -// -// applying the [McMillan] method to construct the [interpolation] to -// the complete structure hash circuit -// -//============================================================================= - - -class SMITP : virtual public SITP , virtual public MITP -{ -public: - virtual ~SMITP(){} - SMITP( StrashCkt & k , bool p ):SITP(k,p){} -}; - -//==== SPITP ====== [ Concrete class ] ======================================== -// is a Pudlark construction structure hash circuit -// -// applying the [Pudlark] method to construct the [interpolation] to -// the complete structure hash circuit -// -//============================================================================= - -class SPITP: virtual public SITP , virtual public PITP -{ -public: - virtual ~SPITP(){} - SPITP( StrashCkt & k , bool p):SITP(k,p){} -}; - -//==== Checker ================================================================ -// -//============================================================================= -struct Checker : virtual public ProofTraverser -{ - vec< vec > clauses; - vec< vec< ClauseId > > vcs; - vec< vec > vxs; - vector< bool > phase; - - int TRA_INT; - Checker():TRA_INT(0){} - void root (const vec& c ,bool A); - void chain (const vec& cs, const vec& xs) ; - void deleted(ClauseId c) ; - void resolve(vec& main, vec& other, Lit x); - void traverse( ProofTraverser & ); - void done(); -}; - -/****************************************************************************** - * [Synopsis] help for saving the proof traverser information -******************************************************************************/ -class ITPMgr -{ - protected: - ProofTraverser * _pft; // internal - SITP * _itp; // construction - Proof * _pf; // proof - AigPtr _interpolant; // constructed - - public: - - enum CONST_MODE{ ON_THE_FLY , NONE , POST }; - - int CC_MIN;// - int ITP_CONTAINER; - int PFT_CONTAINER; - int ITP_PHASE; - int MODE; - - - ITPMgr( ): - _pft( NULL ), _itp( NULL ),_pf( NULL ), - - CC_MIN(1), ITP_CONTAINER(3), PFT_CONTAINER(4), - ITP_PHASE(0), MODE( ON_THE_FLY ) - {} - ~ITPMgr(); - - ProofTraverser * pfGen( Solver & S, StrashCkt & ckt ); // parameter for _itp - AigPtr itpGen(); -}; - -#endif diff --git a/src/sat/test/NO_USE/mitp.h b/src/sat/test/NO_USE/mitp.h deleted file mode 100644 index c88a6803..00000000 --- a/src/sat/test/NO_USE/mitp.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef MITP_H -#define MITP_H - -#include "Proof.h" -#include "Solver.h" - -class MVITP : virtual public ProofTraverser -{ - public: - protected: -}; - -#endif diff --git a/src/sat/test/Proof.cpp b/src/sat/test/Proof.cpp deleted file mode 100644 index 9f5fedfe..00000000 --- a/src/sat/test/Proof.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/*****************************************************************************************[Proof.C] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#include "Proof.h" -#include "Sort.h" -#include - -//================================================================================================= -// Temporary files handling: - - -class TempFiles { - vec files; // For clean-up purposed on abnormal exit. - -public: - ~TempFiles() - { - for (int i = 0; i < files.size(); i++) - remove(files[i]); - //printf("Didn't delete:\n %s\n", files[i]); - } - - // Returns a read-only string with the filename of the temporary file. The pointer can be used to - // remove the file (which is otherwise done automatically upon program exit). - // - char* open(File& fp) - { -// char * name; -// char* name = "/tmp/fileXXXXXX"; - char* name = new char[64]; - strcpy(name, "/tmp/fileXXXXXX"); - for(;;){ -// name = tempnam(NULL, NULL); // (gcc complains about this... stupid gcc...) -// fp.open(name, "wx+"); - fp.open( mkstemp(name) , WRITE , true ); - assert(name != NULL); - if (fp.null()) - xfree(name); - else{ - files.push(name); - return name; - } - } - } -}; -static TempFiles temp_files; // (should be singleton) - - -//================================================================================================= -// Proof logging: - - -Proof::Proof() -{ - fp_name = temp_files.open(fp); - id_counter = 0; - trav = NULL; - TRA_INT = 0; - fpos =0 ; -} - - -Proof::Proof(ProofTraverser& t) -{ - id_counter = 0; - trav = &t; - TRA_INT = 0; - fpos = 0; -} - - -ClauseId Proof::addRoot(vec& cl, bool A) -{ - cl.copyTo(clause); - sortUnique(clause); - - if (trav != NULL) - trav->root(clause, A); - if (!fp.null()){ - putUInt(fp, index(clause[0]) << 1); - for (int i = 1; i < clause.size(); i++) - putUInt(fp, index(clause[i]) - index(clause[i-1])); - putUInt(fp, 0); // (0 is safe terminator since we removed duplicates) - if(A) putUInt(fp , 1); - else putUInt(fp , 2 ); - } - - return id_counter++; -} - - -void Proof::beginChain(ClauseId start) -{ - assert(start != ClauseId_NULL); - chain_id .clear(); - chain_lit.clear(); - chain_id.push(start); -} - - -void Proof::resolve(ClauseId next, Lit x) -{ - assert(next != ClauseId_NULL); - chain_id .push(next); - chain_lit.push(x); -} - - -ClauseId Proof::endChain() -{ - assert(chain_id.size() == chain_lit.size() + 1); - if (chain_id.size() == 1) - return chain_id[0]; - else{ - if (trav != NULL) - trav->chain(chain_id, chain_lit); - if (!fp.null()){ - putUInt(fp, ((id_counter - chain_id[0]) << 1) | 1); - for (int i = 0; i < chain_lit.size(); i++) - putUInt(fp, index(chain_lit[i])+1 ), - putUInt(fp, id_counter - chain_id[i+1]); - putUInt(fp, 0); - } - - return id_counter++; - } -} - - -void Proof::deleted(ClauseId gone) -{ - if (trav != NULL) - trav->deleted(gone); - if (!fp.null()){ - putUInt(fp, ((id_counter - gone) << 1) | 1); - putUInt(fp, 0); - } -} - - -//================================================================================================= -// Read-back methods: - - -void Proof::compress(Proof& dst, ClauseId goal) -{ - assert(!fp.null()); - assert(false); // Not yet! -} - - -bool Proof::save(cchar* filename) -{ - assert(!fp.null()); - - // Switch to read mode: - fp.setMode(READ); - fp.seek(0); - - // Copy file: - File out(filename, "wox"); - if (out.null()) - return false; - - while (!fp.eof()) - out.putChar(fp.getChar()); - - // Restore write (proof-logging) mode: - fp.seek(0, SEEK_END); - fp.setMode(WRITE); - return true; -} - - -void Proof::traverse(ProofTraverser& trav, ClauseId goal) -{ - assert(!fp.null()); - - // Switch to read mode: - fp.setMode(READ); - fp.seek( fpos ); - - // Traverse proof: - if (goal == ClauseId_NULL) - goal = last(); - - uint64 tmp; - int idx; - bool A; - - for(ClauseId id = TRA_INT ; id <= goal; id++){ - tmp = getUInt(fp); - if ((tmp & 1) == 0){ - // Root clause: - clause.clear(); - idx = tmp >> 1; - clause.push(toLit(idx)); - for(;;){ - tmp = getUInt(fp); - if (tmp == 0) break; - idx += tmp; - clause.push(toLit(idx)); - } - if( getUInt(fp) == 1 ) A = true; - else A = false; - //assert( false); - trav.root(clause ,A); - - - }else{ - // Derivation or Deletion: - - chain_id .clear(); - chain_lit.clear(); - chain_id.push(id - (tmp >> 1)); - for(;;){ - tmp = getUInt(fp); - if (tmp == 0) break; - chain_lit.push(toLit( tmp - 1)); - tmp = getUInt(fp); - chain_id.push(id - tmp); - } - - if (chain_lit.size() == 0) - id--, // (no new clause introduced) - trav.deleted(chain_id[0]); - else - trav.chain(chain_id, chain_lit); - } - } - TRA_INT = goal+1; - fpos = fp.tell(); - fp.seek(0, SEEK_END); - fp.setMode(WRITE); -} diff --git a/src/sat/test/Proof.h b/src/sat/test/Proof.h deleted file mode 100644 index b1dbe039..00000000 --- a/src/sat/test/Proof.h +++ /dev/null @@ -1,74 +0,0 @@ -/*****************************************************************************************[Proof.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Proof_h -#define Proof_h - -#include "SolverTypes.h" -#include "File.h" - - -//================================================================================================= - - -// A "listner" for the proof. Proof events will be passed onto (online mode) or replayed to -// (offline mode) this class. Each call to 'root()' or 'chain()' produces a new clause. The first -// clause has ID 0, the next 1 and so on. These are the IDs passed to 'chain()'s 'cs' parameter. -// -struct ProofTraverser { - virtual void root (const vec& c , bool A)=0;// {assert(false);}; - virtual void chain (const vec& cs, const vec& xs)=0;// {assert(false);}; - virtual void deleted(ClauseId c){} - virtual void done ()=0;//{assert(false);} - virtual ~ProofTraverser(){} -}; - - -class Proof { - File fp; - cchar* fp_name; - ClauseId id_counter; - ProofTraverser* trav; - - int TRA_INT; - int64 fpos; - - vec clause; - vec chain_id; - vec chain_lit; - -public: - Proof(); // Offline mode -- proof stored to a file, which can be saved, compressed, and/or traversed. - Proof(ProofTraverser& t); // Online mode -- proof will not be stored. - - ClauseId addRoot (vec& clause , bool A ); - void beginChain(ClauseId start); - void resolve (ClauseId next, Lit x); - ClauseId endChain (); - void deleted (ClauseId gone); - ClauseId last () { assert(id_counter != ClauseId_NULL); return id_counter - 1; } - - void compress (Proof& dst, ClauseId goal = ClauseId_NULL); // 'dst' should be a newly constructed, empty proof. - bool save (cchar* filename); - void traverse (ProofTraverser& trav, ClauseId goal = ClauseId_NULL) ; -}; - - -//================================================================================================= -#endif diff --git a/src/sat/test/Solver.cpp b/src/sat/test/Solver.cpp deleted file mode 100644 index 7e6b34ba..00000000 --- a/src/sat/test/Solver.cpp +++ /dev/null @@ -1,854 +0,0 @@ -/****************************************************************************************[Solver.C] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#include "Solver.h" -#include "Sort.h" -#include - -int effLimit = INT_MAX; // 100000; // INT_MAX; - -//================================================================================================= -// Helper functions: - - -void removeWatch(vec& ws, Clause* elem) -{ - if (ws.size() == 0) return; // (skip lists that are already cleared) - int j = 0; - for (; ws[j] != elem ; j++) assert(j < ws.size()); - for (; j < ws.size()-1; j++) ws[j] = ws[j+1]; - ws.pop(); -} - - -//================================================================================================= -// Operations on clauses: - - -/*_________________________________________________________________________________________________ -| -| newClause : (ps : const vec&) (learnt : bool) (id : ClauseId) -> [void] -| -| Description: -| Allocate and add a new clause to the SAT solvers clause database. If a conflict is detected, -| the 'ok' flag is cleared and the solver is in an unusable state (must be disposed). -| -| Input: -| ps - The new clause as a vector of literals. -| learnt - Is the clause a learnt clause? For learnt clauses, 'ps[0]' is assumed to be the -| asserting literal. An appropriate 'enqueue()' operation will be performed on this -| literal. One of the watches will always be on this literal, the other will be set to -| the literal with the highest decision level. -| id - If logging proof, learnt clauses should be given an ID by caller. -| -| Effect: -| Activity heuristics are updated. -|________________________________________________________________________________________________@*/ -void Solver::newClause(const vec& ps_, bool learnt, ClauseId id , bool A) -{ - assert(learnt || id == ClauseId_NULL); - if (!ok) return; - - vec qs; - if (!learnt){ - assert(decisionLevel() == 0); - ps_.copyTo(qs); // Make a copy of the input vector. - - // Remove duplicates: - sortUnique(qs); - - // Check if clause is satisfied: - for (int i = 0; i < qs.size()-1; i++){ - if (qs[i] == ~qs[i+1]) - return; } - for (int i = 0; i < qs.size(); i++){ - if (value(qs[i]) == l_True) - return; } - - // Remove false literals: - int i, j; - if (proof != NULL) proof->beginChain(proof->addRoot(qs,A)); - for (i = j = 0; i < qs.size(); i++) - if (value(qs[i]) != l_False) - qs[j++] = qs[i]; - else - if (proof != NULL) proof->resolve(unit_id[var(qs[i])], qs[i]); - qs.shrink(i - j); - if (proof != NULL) id = proof->endChain(); - } - const vec& ps = learnt ? ps_ : qs; // 'ps' is now the (possibly) reduced vector of literals. - - if (ps.size() == 0){ - ok = false; - - }else if (ps.size() == 1){ - // NOTE: If enqueue takes place at root level, the assignment will be lost in incremental use (it doesn't seem to hurt much though). - if (id != ClauseId_NULL) - unit_id[var(ps[0])] = id; - if (!enqueue(ps[0])) - ok = false; - - }else{ - // Allocate clause: - Clause* c = Clause_new(learnt, ps, id); - - if (learnt){ - // Put the second watch on the literal with highest decision level: - int max_i = 1; - int max = level[var(ps[1])]; - for (int i = 2; i < ps.size(); i++) - if (level[var(ps[i])] > max) - max = level[var(ps[i])], - max_i = i; - (*c)[1] = ps[max_i]; - (*c)[max_i] = ps[1]; - - // Bumping: - claBumpActivity(c); // (newly learnt clauses should be considered active) - - // Enqueue asserting literal: - check(enqueue((*c)[0], c)); - - // Store clause: - watches[index(~(*c)[0])].push(c); - watches[index(~(*c)[1])].push(c); - learnts.push(c); - stats.learnts_literals += c->size(); - - }else{ - // Store clause: - watches[index(~(*c)[0])].push(c); - watches[index(~(*c)[1])].push(c); - clauses.push(c); - stats.clauses_literals += c->size(); - } - } -} - - -// Disposes a clauses and removes it from watcher lists. NOTE! Low-level; does NOT change the 'clauses' and 'learnts' vector. -// -void Solver::remove(Clause* c, bool just_dealloc) -{ - if (!just_dealloc){ - removeWatch(watches[index(~(*c)[0])], c), - removeWatch(watches[index(~(*c)[1])], c); - - if (c->learnt()) stats.learnts_literals -= c->size(); - else stats.clauses_literals -= c->size(); - - if (proof != NULL) proof->deleted(c->id()); - } - - xfree(c); -} - - -// Can assume everything has been propagated! (esp. the first two literals are != l_False, unless -// the clause is binary and satisfied, in which case the first literal is true) -// Returns True if clause is satisfied (will be removed), False otherwise. -// -bool Solver::simplify(Clause* c) const -{ - assert(decisionLevel() == 0); - for (int i = 0; i < c->size(); i++){ - if (value((*c)[i]) == l_True) - return true; - } - return false; -} - - -//================================================================================================= -// Minor methods: - - -// Creates a new SAT variable in the solver. If 'decision_var' is cleared, variable will not be -// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result). -// -Var Solver::newVar() { - int index; - index = nVars(); - watches .push(); // (list for positive literal) - watches .push(); // (list for negative literal) - reason .push(NULL); - assigns .push(toInt(l_Undef)); - level .push(-1); - trail_pos .push(-1); - activity .push(0); - order .newVar(); - analyze_seen.push(0); - if (proof != NULL) unit_id.push(ClauseId_NULL); - return index; } - - -// Returns FALSE if immediate conflict. -bool Solver::assume(Lit p) { - trail_lim.push(trail.size()); - return enqueue(p); } - - -// Revert to the state at given level. -void Solver::cancelUntil(int level) { - if (decisionLevel() > level){ - for (int c = trail.size()-1; c >= trail_lim[level]; c--){ - Var x = var(trail[c]); - assigns[x] = toInt(l_Undef); - reason [x] = NULL; - order.undo(x); } - trail.shrink(trail.size() - trail_lim[level]); - trail_lim.shrink(trail_lim.size() - level); - qhead = trail.size(); } } - - -//================================================================================================= -// Major methods: - - -/*_________________________________________________________________________________________________ -| -| analyze : (confl : Clause*) (out_learnt : vec&) (out_btlevel : int&) -> [void] -| -| Description: -| Analyze conflict and produce a reason clause ('out_learnt') and a backtracking level -| ('out_btlevel'). -| -| Pre-conditions: -| * 'out_learnt' is assumed to be cleared. -| * Current decision level must be greater than root level. -| -| Post-conditions: -| * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'. -| * If performing proof-logging, the last derived clause in the proof is the reason clause. -|________________________________________________________________________________________________@*/ - -class lastToFirst_lt { // Helper class to 'analyze' -- order literals from last to first occurance in 'trail[]'. - const vec& trail_pos; -public: - lastToFirst_lt(const vec& t) : trail_pos(t) {} - bool operator () (Lit p, Lit q) { return trail_pos[var(p)] > trail_pos[var(q)]; } -}; -void Solver::analyze(Clause* confl, vec& out_learnt, int& out_btlevel) -{ - vec& seen = analyze_seen; - int pathC = 0; - Lit p = lit_Undef; - - // Generate conflict clause: - // - if (proof != NULL) proof->beginChain(confl->id()); - out_learnt.push(); // (leave room for the asserting literal) - out_btlevel = 0; - int index = trail.size()-1; - for(;;){ - assert(confl != NULL); // (otherwise should be UIP) - - Clause& c = *confl; - if (c.learnt()) - claBumpActivity(&c); - - for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){ - Lit q = c[j]; - if (!seen[var(q)]){ - if (level[var(q)] > 0){ - varBumpActivity(q); - seen[var(q)] = 1; - if (level[var(q)] == decisionLevel()) - pathC++; - else{ - out_learnt.push(q); - out_btlevel = max(out_btlevel, level[var(q)]); - } - }else - if (proof != NULL) proof->resolve(unit_id[var(q)], q); - } - } - - // Select next clause to look at: - while (!seen[var(trail[index--])]); - p = trail[index+1]; - confl = reason[var(p)]; - seen[var(p)] = 0; - pathC--; - if (pathC == 0) break; - - if (proof != NULL) proof->resolve(confl->id(), ~p); - } - out_learnt[0] = ~p; - - // Conflict clause minimization: - // - int i=0 , j=0 ; - if (expensive_ccmin == 2){ - // Simplify conflict clause (a lot): - // - uint min_level = 0; - for (i = 1; i < out_learnt.size(); i++) - min_level |= 1 << (level[var(out_learnt[i])] & 31); // (maintain an abstraction of levels involved in conflict) - - analyze_toclear.clear(); - for (i = j = 1; i < out_learnt.size(); i++) - if (reason[var(out_learnt[i])] == NULL || !analyze_removable(out_learnt[i], min_level)) - out_learnt[j++] = out_learnt[i]; - }else if(expensive_ccmin == 1){ - // Simplify conflict clause (a little): - // - analyze_toclear.clear(); - for (i = j = 1; i < out_learnt.size(); i++){ - Clause* r = reason[var(out_learnt[i])]; - if (r == NULL) - out_learnt[j++] = out_learnt[i]; - else{ - Clause& c = *r; - for (int k = 1; k < c.size(); k++) - if (!seen[var(c[k])] && level[var(c[k])] != 0){ - out_learnt[j++] = out_learnt[i]; - goto Keep; - } - analyze_toclear.push(out_learnt[i]); - Keep:; - } - } - } - - // Finilize proof logging with conflict clause minimization steps: - // - if (proof != NULL){ - sort(analyze_toclear, lastToFirst_lt(trail_pos)); - for (int k = 0; k < analyze_toclear.size(); k++){ - Var v = var(analyze_toclear[k]); assert(level[v] > 0); - Lit l = analyze_toclear[k]; - Clause& c = *reason[v]; - proof->resolve(c.id(), l); - for (int k = 1; k < c.size(); k++) - if (level[var(c[k])] == 0) - proof->resolve(unit_id[var(c[k])], c[k]); - } - proof->endChain(); - } - // Clean up: - // - for (int j = 0; j < out_learnt.size() ; j++) seen[var(out_learnt [j])] = 0; - for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared) - - stats.max_literals += out_learnt.size(); - out_learnt.shrink(i - j); - stats.tot_literals += out_learnt.size(); -} - - -// Check if 'p' can be removed. 'min_level' is used to abort early if visiting literals at a level that cannot be removed. -// -bool Solver::analyze_removable(Lit p, uint min_level) -{ - assert(reason[var(p)] != NULL); - analyze_stack.clear(); analyze_stack.push(p); - int top = analyze_toclear.size(); - while (analyze_stack.size() > 0){ - assert(reason[var(analyze_stack.last())] != NULL); - Clause& c = *reason[var(analyze_stack.last())]; - analyze_stack.pop(); - for (int i = 1; i < c.size(); i++){ - Lit p = c[i]; - if (!analyze_seen[var(p)] && level[var(p)] != 0){ - if (reason[var(p)] != NULL && ((1 << (level[var(p)] & 31)) & min_level) != 0){ - analyze_seen[var(p)] = 1; - analyze_stack.push(p); - analyze_toclear.push(p); - }else{ - for (int j = top; j < analyze_toclear.size(); j++) - analyze_seen[var(analyze_toclear[j])] = 0; - analyze_toclear.shrink(analyze_toclear.size() - top); - return false; - } - } - } - } - analyze_toclear.push(p); - - return true; -} - - -/*_________________________________________________________________________________________________ -| -| analyzeFinal : (confl : Clause*) (skip_first : bool) -> [void] -| -| Description: -| Specialized analysis procedure to express the final conflict in terms of assumptions. -| 'root_level' is allowed to point beyond end of trace (useful if called after conflict while -| making assumptions). If 'skip_first' is TRUE, the first literal of 'confl' is ignored (needed -| if conflict arose before search even started). -|________________________________________________________________________________________________@*/ -void Solver::analyzeFinal(Clause* confl, bool skip_first) -{ - // -- NOTE! This code is relatively untested. Please report bugs! - conflict.clear(); - if (root_level == 0){ - if (proof != NULL) conflict_id = proof->last(); - return; } - //assert(false); - vec& seen = analyze_seen; - if (proof != NULL) proof->beginChain(confl->id()); - for (int i = skip_first ? 1 : 0; i < confl->size(); i++){ - Var x = var((*confl)[i]); - Lit l = (*confl)[i]; - if (level[x] > 0) - seen[x] = 1; - else - if (proof != NULL) proof->resolve(unit_id[x], l); - } - - int start = (root_level >= trail_lim.size()) ? trail.size()-1 : trail_lim[root_level]; - for (int i = start; i >= trail_lim[0]; i--){ - Var x = var(trail[i]); - Lit l = trail[i]; - if (seen[x]){ - Clause* r = reason[x]; - if (r == NULL){ - assert(level[x] > 0); - conflict.push(~trail[i]); - }else{ - Clause& c = *r; - if (proof != NULL) proof->resolve(c.id(), l); - for (int j = 1; j < c.size(); j++) - if (level[var(c[j])] > 0) - seen[var(c[j])] = 1; - else - if (proof != NULL) proof->resolve(unit_id[var(c[j])], c[j]); - } - seen[x] = 0; - } - } - if (proof != NULL) conflict_id = proof->endChain(); -} - - -/*_________________________________________________________________________________________________ -| -| enqueue : (p : Lit) (from : Clause*) -> [bool] -| -| Description: -| Puts a new fact on the propagation queue as well as immediately updating the variable's value. -| Should a conflict arise, FALSE is returned. -| -| Input: -| p - The fact to enqueue -| from - [Optional] Fact propagated from this (currently) unit clause. Stored in 'reason[]'. -| Default value is NULL (no reason). -| -| Output: -| TRUE if fact was enqueued without conflict, FALSE otherwise. -|________________________________________________________________________________________________@*/ -bool Solver::enqueue(Lit p, Clause* from) -{ - if (value(p) != l_Undef) - return value(p) != l_False; - else{ - Var x = var(p); - assigns [x] = toInt(lbool(!sign(p))); - level [x] = decisionLevel(); - trail_pos[x] = trail.size(); - reason [x] = from; - trail.push(p); - return true; - } -} - - - -/*_________________________________________________________________________________________________ -| -| propagate : [void] -> [Clause*] -| -| Description: -| Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned, -| otherwise NULL. NOTE! This method has been optimized for speed rather than readability. -| -| Post-conditions: -| * The propagation queue is empty, even if there was a conflict. -|________________________________________________________________________________________________@*/ -Clause* Solver::propagate() -{ - Clause* confl = NULL; - while (qhead < trail.size()){ - stats.propagations++; - simpDB_props--; - - Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. - vec& ws = watches[index(p)]; - Clause** i,** j,** end; - - for (i = j = (Clause**)ws, end = i + ws.size(); i != end;){ - Clause& c = **i; i++; - // Make sure the false literal is data[1]: - Lit false_lit = ~p; - if (c[0] == false_lit) - c[0] = c[1], c[1] = false_lit; - - assert(c[1] == false_lit); - - // If 0th watch is true, then clause is already satisfied. - Lit first = c[0]; - lbool val = value(first); - if (val == l_True){ - *j++ = &c; - }else{ - // Look for new watch: - for (int k = 2; k < c.size(); k++) - if (value(c[k]) != l_False){ - c[1] = c[k]; c[k] = false_lit; - watches[index(~c[1])].push(&c); - goto FoundWatch; } - - // Did not find watch -- clause is unit under assignment: - if (decisionLevel() == 0 && proof != NULL){ - // Log the production of this unit clause: - proof->beginChain(c.id()); - for (int k = 1; k < c.size(); k++) - proof->resolve(unit_id[var(c[k])], c[k]); - ClauseId id = proof->endChain(); - assert(unit_id[var(first)] == ClauseId_NULL || value(first) == l_False); // (if variable already has 'id', it must be with the other polarity and we should have derived the empty clause here) - if (value(first) != l_False) - unit_id[var(first)] = id; - else{ - // Empty clause derived: - proof->beginChain(unit_id[var(first)]); - proof->resolve(id, ~first); - proof->endChain(); - } - } - - *j++ = &c; - if (!enqueue(first, &c)){ - if (decisionLevel() == 0) - ok = false; - confl = &c; - qhead = trail.size(); - // Copy the remaining watches: - while (i < end) - *j++ = *i++; - } - FoundWatch:; - } - } - ws.shrink(i - j); - } - - return confl; -} - - -/*_________________________________________________________________________________________________ -| -| reduceDB : () -> [void] -| -| Description: -| Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked -| clauses are clauses that are reason to some assignment. Binary clauses are never removed. -|________________________________________________________________________________________________@*/ -struct reduceDB_lt { bool operator () (Clause* x, Clause* y) { return x->size() > 2 && (y->size() == 2 || x->activity() < y->activity()); } }; -void Solver::reduceDB() -{ - int i, j; - double extra_lim = cla_inc / learnts.size(); // Remove any clause below this activity - - sort(learnts, reduceDB_lt()); - for (i = j = 0; i < learnts.size() / 2; i++){ - if (learnts[i]->size() > 2 && !locked(learnts[i])) - remove(learnts[i]); - else - learnts[j++] = learnts[i]; - } - for (; i < learnts.size(); i++){ - if (learnts[i]->size() > 2 && !locked(learnts[i]) && learnts[i]->activity() < extra_lim) - remove(learnts[i]); - else - learnts[j++] = learnts[i]; - } - learnts.shrink(i - j); -} - - -/*_________________________________________________________________________________________________ -| -| simplifyDB : [void] -> [bool] -| -| Description: -| Simplify the clause database according to the current top-level assigment. Currently, the only -| thing done here is the removal of satisfied clauses, but more things can be put here. -|________________________________________________________________________________________________@*/ -void Solver::simplifyDB() -{ - if (!ok) return; // GUARD (public method) - assert(decisionLevel() == 0); - - if (propagate() != NULL){ - ok = false; - return; } - - if (nAssigns() == simpDB_assigns || simpDB_props > 0) // (nothing has changed or preformed a simplification too recently) - return; - - // Clear watcher lists: - for (int i = simpDB_assigns; i < nAssigns(); i++){ - Lit p = trail[i]; - watches[index( p)].clear(true); - watches[index(~p)].clear(true); - } - - // Remove satisfied clauses: - for (int type = 0; type < 2; type++){ - vec& cs = type ? learnts : clauses; - int j = 0; - for (int i = 0; i < cs.size(); i++){ - if (!locked(cs[i]) && simplify(cs[i])) - remove(cs[i]); - else - cs[j++] = cs[i]; - } - cs.shrink(cs.size()-j); - } - - simpDB_assigns = nAssigns(); - simpDB_props = stats.clauses_literals + stats.learnts_literals; // (shouldn't depend on 'stats' really, but it will do for now) -} - - -/*_________________________________________________________________________________________________ -| -| search : (nof_conflicts : int) (nof_learnts : int) (params : const SearchParams&) -> [lbool] -| -| Description: -| Search for a model the specified number of conflicts, keeping the number of learnt clauses -| below the provided limit. NOTE! Use negative value for 'nof_conflicts' or 'nof_learnts' to -| indicate infinity. -| -| Output: -| 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If -| all variables are decision variables, this means that the clause set is satisfiable. 'l_False' -| if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached. -|________________________________________________________________________________________________@*/ -lbool Solver::search(int nof_conflicts, int nof_learnts, const SearchParams& params) -{ - if (!ok) return l_False; // GUARD (public method) - assert(root_level == decisionLevel()); - - stats.starts++; - int conflictC = 0; - var_decay = 1 / params.var_decay; - cla_decay = 1 / params.clause_decay; - model.clear(); - - for (;;){ - Clause* confl = propagate(); - if (confl != NULL){ - // CONFLICT - - stats.conflicts++; conflictC++; - vec learnt_clause; - int backtrack_level; - if (decisionLevel() == root_level){ - // Contradiction found: - analyzeFinal(confl); - return l_False; } - analyze(confl, learnt_clause, backtrack_level); - cancelUntil(max(backtrack_level, root_level)); - newClause(learnt_clause, true, (proof != NULL) ? proof->last() : ClauseId_NULL); - if (learnt_clause.size() == 1) level[var(learnt_clause[0])] = 0; // (this is ugly (but needed for 'analyzeFinal()') -- in future versions, we will backtrack past the 'root_level' and redo the assumptions) - varDecayActivity(); - claDecayActivity(); - - }else{ - // NO CONFLICT - - if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ - // Reached bound on number of conflicts: - progress_estimate = progressEstimate(); - cancelUntil(root_level); - return l_Undef; } - - if (decisionLevel() == 0) - // Simplify the set of problem clauses: - simplifyDB(), assert(ok); - - if (nof_learnts >= 0 && learnts.size()-nAssigns() >= nof_learnts) - // Reduce the set of learnt clauses: - reduceDB(); - - // New variable decision: - stats.decisions++; - Var next = order.select(params.random_var_freq); - - if (next == var_Undef){ - // Model found: - model.growTo(nVars()); - for (int i = 0; i < nVars(); i++) model[i] = value(i); - cancelUntil(root_level); - return l_True; - } - - check(assume(~Lit(next))); - } - } -} - - -// Return search-space coverage. Not extremely reliable. -// -double Solver::progressEstimate() -{ - double progress = 0; - double F = 1.0 / nVars(); - for (int i = 0; i < nVars(); i++) - if (value(i) != l_Undef) - progress += pow(F, level[i]); - return progress / nVars(); -} - - -// Divide all variable activities by 1e100. -// -void Solver::varRescaleActivity() -{ - for (int i = 0; i < nVars(); i++) - activity[i] *= 1e-100; - var_inc *= 1e-100; -} - - -// Divide all constraint activities by 1e100. -// -void Solver::claRescaleActivity() -{ - for (int i = 0; i < learnts.size(); i++) - learnts[i]->activity() *= 1e-20; - cla_inc *= 1e-20; -} - - -/*_________________________________________________________________________________________________ -| -| solve : (assumps : const vec&) -> [bool] -| -| Description: -| Top-level solve. If using assumptions (non-empty 'assumps' vector), you must call -| 'simplifyDB()' first to see that no top-level conflict is present (which would put the solver -| in an undefined state). -| -| Input: -| A list of assumptions (unit clauses coded as literals). Pre-condition: The assumptions must -| not contain both 'x' and '~x' for any variable 'x'. -|________________________________________________________________________________________________@*/ -lbool Solver::solve(const vec& assumps) -{ - simplifyDB(); - if (!ok) return l_False; // false; - - SearchParams params(default_params); - double nof_conflicts = 100; - double nof_learnts = nClauses() / 3; - lbool status = l_Undef; - - // Perform assumptions: - root_level = assumps.size(); - for (int i = 0; i < assumps.size(); i++){ - Lit p = assumps[i]; - assert(var(p) < nVars()); - if (!assume(p)){ - if (reason[var(p)] != NULL){ - analyzeFinal(reason[var(p)], true); - conflict.push(~p); - }else{ - assert(proof == NULL || unit_id[var(p)] != ClauseId_NULL); // (this is the pre-condition above) - conflict.clear(); - conflict.push(~p); - if (proof != NULL) conflict_id = unit_id[var(p)]; - } - cancelUntil(0); - return l_False; } // false; } - Clause* confl = propagate(); - if (confl != NULL){ - analyzeFinal(confl), assert(conflict.size() > 0); - cancelUntil(0); - return l_False; } // false; } - } - assert(root_level == decisionLevel()); - - // Search: - if (verbosity >= 1){ - reportf("==================================[MINISAT]"); - reportf("===================================\n"); - reportf("| Conflicts | ORIGINAL | "); - reportf("LEARNT | Progress |\n"); - reportf("| | Clauses Literals | Limit Clauses "); - reportf("Literals Lit/Cl | |\n"); - reportf("==========================================="); - reportf("===================================\n"); - } - - while (status == l_Undef){ - if (verbosity >= 1){ - printStats(); - reportf("| %9d | %7d %8d | %7d %7d %8d %7.1f | %6.3f %% |\n", - (int)stats.conflicts, nClauses(), - (int)stats.clauses_literals, - (int)nof_learnts, nLearnts(), - (int)stats.learnts_literals, - (double)stats.learnts_literals/nLearnts(), - progress_estimate*100); - fflush(stdout); - } - status = search((int)nof_conflicts, (int)nof_learnts, params); - nof_conflicts *= 1.5; - nof_learnts *= 1.1; - -if ((int)stats.conflicts >= effLimit) { - cancelUntil(0); - return l_Undef; // status == l_True; -// return status == l_True; -} - } - if (verbosity >= 1) { - reportf("==========================================="); - reportf("===================================\n"); - } - - cancelUntil(0); - return status; -// return status == l_True; -} - -void Solver::printStats() -{ - reportf("==============================[MINISAT]"); - reportf("===============================\n"); - reportf("| Conflicts | ORIGINAL | "); - reportf("LEARNT | Progress |\n"); - reportf("| | Clauses Literals | Clauses "); - reportf("Literals Lit/Cl | |\n"); - reportf("======================================="); - reportf("===============================\n"); - reportf("| %9d | %7d %8d | %7d %8d %7.1f | %6.3f %% |\n", - (int)stats.conflicts, nClauses(), (int)stats.clauses_literals, - nLearnts(), (int)stats.learnts_literals, - (double)stats.learnts_literals/nLearnts(), progress_estimate*100); - reportf("======================================="); - reportf("===============================\n"); -} diff --git a/src/sat/test/Solver.h b/src/sat/test/Solver.h deleted file mode 100644 index b5343760..00000000 --- a/src/sat/test/Solver.h +++ /dev/null @@ -1,219 +0,0 @@ -/****************************************************************************************[Solver.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Solver_h -#define Solver_h - -#include "SolverTypes.h" -#include "VarOrder.h" -#include "Proof.h" - -// Redfine if you want output to go somewhere else: -#define reportf(format, args...) ( printf(format , ## args), fflush(stdout) ) - - -//================================================================================================= -// Solver -- the main class: - - -struct SolverStats { - int64 starts, decisions, propagations, conflicts; - int64 clauses_literals, learnts_literals, max_literals, tot_literals; - SolverStats() : starts(0), decisions(0), propagations(0), conflicts(0) - , clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0) { } -}; - - -struct SearchParams { - double var_decay, clause_decay, random_var_freq; // (reasonable values are: 0.95, 0.999, 0.02) - SearchParams(double v = 1, double c = 1, double r = 0) : var_decay(v), clause_decay(c), random_var_freq(r) { } -}; - - -class Solver { -protected: - // Solver state: - // - bool ok; // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used! - vec clauses; // List of problem clauses. - vec learnts; // List of learnt clauses. - vec unit_id; // 'unit_id[var]' is the clause ID for the unit literal 'var' or '~var' (if set at toplevel). - double cla_inc; // Amount to bump next clause with. - double cla_decay; // INVERSE decay factor for clause activity: stores 1/decay. - - vec activity; // A heuristic measurement of the activity of a variable. - double var_inc; // Amount to bump next variable with. - double var_decay; // INVERSE decay factor for variable activity: stores 1/decay. Use negative value for static variable order. - VarOrder order; // Keeps track of the decision variable order. - - vec > watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true). - vec assigns; // The current assignments (lbool:s stored as char:s). - vec trail; // Assignment stack; stores all assigments made in the order they were made. - vec trail_lim; // Separator indices for different decision levels in 'trail[]'. - vec reason; // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none. - vec level; // 'level[var]' is the decision level at which assignment was made. - vec trail_pos; // 'trail_pos[var]' is the variable's position in 'trail[]'. This supersedes 'level[]' in some sense, and 'level[]' will probably be removed in future releases. - int root_level; // Level of first proper decision. - int qhead; // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat). - int simpDB_assigns; // Number of top-level assignments since last execution of 'simplifyDB()'. - int64 simpDB_props; // Remaining number of propagations that must be made before next execution of 'simplifyDB()'. - - // Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which is used: - // - vec analyze_seen; - vec analyze_stack; - vec analyze_toclear; - Clause* propagate_tmpbin; - Clause* analyze_tmpbin; - vec addUnit_tmp; - vec addBinary_tmp; - vec addTernary_tmp; - - // Main internal methods: - // - bool assume (Lit p); - void cancelUntil (int level); - void record (const vec& clause); - - void analyze (Clause* confl, vec& out_learnt, int& out_btlevel); // (bt = backtrack) - bool analyze_removable(Lit p, uint min_level); // (helper method for 'analyze()') - void analyzeFinal (Clause* confl, bool skip_first = false); - bool enqueue (Lit fact, Clause* from = NULL); - Clause* propagate (); - void reduceDB (); - Lit pickBranchLit (const SearchParams& params); - lbool search (int nof_conflicts, int nof_learnts, const SearchParams& params); - double progressEstimate (); - - // Activity: - // - void varBumpActivity(Lit p) { - if (var_decay < 0) return; // (negative decay means static variable order -- don't bump) - if ( (activity[var(p)] += var_inc) > 1e100 ) varRescaleActivity(); - order.update(var(p)); } - void varDecayActivity () { if (var_decay >= 0) var_inc *= var_decay; } - void varRescaleActivity(); - void claDecayActivity () { cla_inc *= cla_decay; } - void claRescaleActivity(); - - // Operations on clauses: - // - void newClause(const vec& ps, bool learnt = false, ClauseId id = ClauseId_NULL, bool A = true); - void claBumpActivity (Clause* c) { if ( (c->activity() += cla_inc) > 1e20 ) claRescaleActivity(); } - void remove (Clause* c, bool just_dealloc = false); - bool locked (const Clause* c) const { return reason[var((*c)[0])] == c; } - bool simplify (Clause* c) const; - - int decisionLevel() const { return trail_lim.size(); } - -public: - Solver() : ok (true) - , cla_inc (1) - , cla_decay (1) - , var_inc (1) - , var_decay (1) - , order (assigns, activity) - , qhead (0) - , simpDB_assigns (0) - , simpDB_props (0) - , default_params (SearchParams(0.95, 0.999, 0.02)) - , expensive_ccmin (2) - , proof (NULL) - , verbosity (0) - , progress_estimate(0) - , conflict_id (ClauseId_NULL) - { - vec dummy(2,lit_Undef); - propagate_tmpbin = Clause_new(false, dummy); - analyze_tmpbin = Clause_new(false, dummy); - addUnit_tmp .growTo(1); - addBinary_tmp .growTo(2); - addTernary_tmp.growTo(3); - } - - ~Solver() { - for (int i = 0; i < learnts.size(); i++) remove(learnts[i], true); - for (int i = 0; i < clauses.size(); i++) if (clauses[i] != NULL) remove(clauses[i], true); - remove(propagate_tmpbin, true); - remove(analyze_tmpbin, true); - } - - // Helpers: (semi-internal) - // - lbool value(Var x) const { return toLbool(assigns[x]); } - lbool value(Lit p) const { return sign(p) ? ~toLbool(assigns[var(p)]) : toLbool(assigns[var(p)]); } - lbool modelValue(Var x) const { return model[x]; } -// lbool modelValue(Lit p) const { return model[var(p)] ^ sign(p); } - - int nAssigns() { return trail.size(); } - int nClauses() { return clauses.size(); } - int nLearnts() { return learnts.size(); } - - // Statistics: (read-only member variable) - // - SolverStats stats; - - // Mode of operation: - // - SearchParams default_params; // Restart frequency etc. - int expensive_ccmin; // Controls conflict clause minimization. TRUE by default. - Proof* proof; // Set this directly after constructing 'Solver' to enable proof logging. Initialized to NULL. - int verbosity; // Verbosity level. 0=silent, 1=some progress report, 2=everything - - // Problem specification: - // - Var newVar (); - int nVars () { return assigns.size(); } - void addUnit (Lit p) { addUnit_tmp [0] = p; addClause(addUnit_tmp); } - void addBinary (Lit p, Lit q) { addBinary_tmp [0] = p; addBinary_tmp [1] = q; addClause(addBinary_tmp); } - void addTernary(Lit p, Lit q, Lit r) { addTernary_tmp[0] = p; addTernary_tmp[1] = q; addTernary_tmp[2] = r; addClause(addTernary_tmp); } - void addClause (const vec& ps , bool A = true) { newClause(ps , false , ClauseId_NULL , A); } - // (used to be a difference between internal and external method...) - - // Solving: - // - bool okay() { return ok; } // FALSE means solver is in an conflicting state (must never be used again!) - void simplifyDB(); - lbool solve(const vec& assumps); - lbool solve() { vec tmp; return solve(tmp); } - - double progress_estimate; // Set by 'search()'. - vec model; // If problem is satisfiable, this vector contains the model (if any). - vec conflict; // If problem is unsatisfiable under assumptions, this vector represent the conflict clause expressed in the assumptions. - ClauseId conflict_id; // (In proof logging mode only.) ID for the clause 'conflict' (for proof traverseral). NOTE! The empty clause is always the last clause derived, but for conflicts under assumption, this is not necessarly true. - - // Printing: - // - void printStats(); -}; - - -//================================================================================================= -// Debug: - - -#define L_LIT "%s%d" -#define L_lit(p) sign(p)?"-":"", var(p)+1 - -// Just like 'assert()' but expression will be evaluated in the release version as well. -inline void check(bool expr) { assert(expr); } - - -//================================================================================================= -#endif diff --git a/src/sat/test/SolverTypes.h b/src/sat/test/SolverTypes.h deleted file mode 100644 index 74df73a8..00000000 --- a/src/sat/test/SolverTypes.h +++ /dev/null @@ -1,141 +0,0 @@ -/***********************************************************************************[SolverTypes.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - - -#ifndef SolverTypes_h -#define SolverTypes_h - -#ifndef Global_h -#include "Global.h" -#endif - - -//================================================================================================= -// Variables, literals, clause IDs: - - -// NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N, -// so that they can be used as array indices. - -typedef int Var; -#define var_Undef (-1) - - -class Lit { - int x; -public: - Lit() : x(2*var_Undef) {} // (lit_Undef) - explicit Lit(Var var, bool sgn = false) : x((var+var) + (int)sgn) {} - friend Lit operator ~ (Lit p); - - friend bool sign (Lit p); - friend int var (Lit p); - friend int index (Lit p); - friend Lit toLit (int i); - friend Lit unsign(Lit p); - friend Lit id (Lit p, bool sgn); - - friend bool operator == (Lit p, Lit q); - friend bool operator < (Lit p, Lit q); - - uint hash() const { return (uint)x; } -}; -inline Lit operator ~ (Lit p) { Lit q; q.x = p.x ^ 1; return q; } -inline bool sign (Lit p) { return p.x & 1; } -inline int var (Lit p) { return p.x >> 1; } -inline int index (Lit p) { return p.x; } // A "toInt" method that guarantees small, positive integers suitable for array indexing. -inline Lit toLit (int i) { Lit p; p.x = i; return p; } // Inverse of 'index()'. -inline Lit unsign(Lit p) { Lit q; q.x = p.x & ~1; return q; } -inline Lit id (Lit p, bool sgn) { Lit q; q.x = p.x ^ (int)sgn; return q; } -inline bool operator == (Lit p, Lit q) { return index(p) == index(q); } -inline bool operator < (Lit p, Lit q) { return index(p) < index(q); } // '<' guarantees that p, ~p are adjacent in the ordering. - -const Lit lit_Undef(var_Undef, false); // }- Useful special constants. -const Lit lit_Error(var_Undef, true ); // } - -inline int toDimacs(Lit p) { return sign(p) ? -var(p) - 1 : var(p) + 1; } - - -//================================================================================================= -// Clause -- a simple class for representing a clause: - - -typedef int ClauseId; // (might have to use uint64 one day...) -const int ClauseId_NULL = INT_MIN; - -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -class Clause { - uint size_learnt; - Lit data[1]; -public: - // NOTE: This constructor cannot be used directly (doesn't allocate enough memory). - Clause(bool learnt, const vec& ps, ClauseId id_ = ClauseId_NULL) { - size_learnt = (ps.size() << 1) | (int)learnt; - for (int i = 0; i < ps.size(); i++) data[i] = ps[i]; - if (learnt) activity() = 0; - if (id_ != ClauseId_NULL) id() = id_; } - - // -- use this function instead: - friend Clause* Clause_new(bool, const vec&, ClauseId); - - int size () const { return size_learnt >> 1; } - bool learnt () const { return size_learnt & 1; } - Lit operator [] (int i) const { return data[i]; } - Lit& operator [] (int i) { return data[i]; } - float& activity () const { - void *p = const_cast(&data[size()]); return *((float *)p); - } // return *((float*)&data[size()]); } - ClauseId& id () const { return *((ClauseId*)&data[size() + (int)learnt()]); } -}; - -inline Clause* Clause_new(bool learnt, const vec& ps, ClauseId id = ClauseId_NULL) { - assert(sizeof(Lit) == sizeof(uint)); - assert(sizeof(float) == sizeof(uint)); - assert(sizeof(ClauseId) == sizeof(uint)); - void* mem = xmalloc(sizeof(Clause) + sizeof(uint)*(ps.size() + (int)learnt + (int)(id != ClauseId_NULL))); - return new (mem) Clause(learnt, ps, id); } - - -//================================================================================================= -// GClause -- Generalize clause: - - -// Either a pointer to a clause or a literal. -class GClause { - void* data; - GClause(void* d) : data(d) {} -public: - friend GClause GClause_new(Lit p); - friend GClause GClause_new(Clause* c); - - bool isLit () const { return ((uintp)data & 1) == 1; } - Lit lit () const { return toLit(((intp)data) >> 1); } - Clause* clause () const { return (Clause*)data; } - bool operator == (GClause c) const { return data == c.data; } - bool operator != (GClause c) const { return data != c.data; } -}; -inline GClause GClause_new(Lit p) { return GClause((void*)(((intp)index(p) << 1) + 1)); } -inline GClause GClause_new(Clause* c) { assert(((uintp)c & 1) == 0); return GClause((void*)c); } - -#define GClause_NULL GClause_new((Clause*)NULL) - - -//================================================================================================= -#endif diff --git a/src/sat/test/Sort.h b/src/sat/test/Sort.h deleted file mode 100644 index e4191cc7..00000000 --- a/src/sat/test/Sort.h +++ /dev/null @@ -1,131 +0,0 @@ -/******************************************************************************************[Sort.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef Sort_h -#define Sort_h - - -//================================================================================================= - - -template -struct LessThan_default { - bool operator () (T x, T y) { return x < y; } -}; - - -//================================================================================================= - - -template -void selectionSort(T* array, int size, LessThan lt) -{ - int i, j, best_i; - T tmp; - - for (i = 0; i < size-1; i++){ - best_i = i; - for (j = i+1; j < size; j++){ - if (lt(array[j], array[best_i])) - best_i = j; - } - tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; - } -} -template static inline void selectionSort(T* array, int size) { - selectionSort(array, size, LessThan_default()); } - - -template -void sort(T* array, int size, LessThan lt, double& seed) -{ - if (size <= 15) - selectionSort(array, size, lt); - - else{ - T pivot = array[irand(seed, size)]; - T tmp; - int i = -1; - int j = size; - - for(;;){ - do i++; while(lt(array[i], pivot)); - do j--; while(lt(pivot, array[j])); - - if (i >= j) break; - - tmp = array[i]; array[i] = array[j]; array[j] = tmp; - } - - sort(array , i , lt, seed); - sort(&array[i], size-i, lt, seed); - } -} -template void sort(T* array, int size, LessThan lt) { - double seed = 91648253; sort(array, size, lt, seed); } -template static inline void sort(T* array, int size) { - sort(array, size, LessThan_default()); } - - -template -void sortUnique(T* array, int& size, LessThan lt) -{ - int i, j; - T last; - - if (size == 0) return; - - sort(array, size, lt); - - i = 1; - last = array[0]; - for (j = 1; j < size; j++){ - if (lt(last, array[j])){ - last = array[i] = array[j]; - i++; } - } - - size = i; -} -template static inline void sortUnique(T* array, int& size) { - sortUnique(array, size, LessThan_default()); } - - -//================================================================================================= -// For 'vec's: - - -template void sort(vec& v, LessThan lt) { - sort((T*)v, v.size(), lt); } -template void sort(vec& v) { - sort(v, LessThan_default()); } - - -template void sortUnique(vec& v, LessThan lt) { - int size = v.size(); - T* data = v.release(); - sortUnique(data, size, lt); - v.~vec(); - new (&v) vec(data, size); } -template void sortUnique(vec& v) { - sortUnique(v, LessThan_default()); } - - -//================================================================================================= -#endif diff --git a/src/sat/test/VarOrder.h b/src/sat/test/VarOrder.h deleted file mode 100644 index ad6c77ce..00000000 --- a/src/sat/test/VarOrder.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************************[VarOrder.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -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. -**************************************************************************************************/ - -#ifndef VarOrder_h -#define VarOrder_h - -#include "SolverTypes.h" -#include "Heap.h" - - -//================================================================================================= - - -struct VarOrder_lt { - const vec& activity; - bool operator () (Var x, Var y) { return activity[x] > activity[y]; } - VarOrder_lt(const vec& act) : activity(act) { } -}; - -class VarOrder { - const vec& assigns; // var->val. Pointer to external assignment table. -// const vec& activity; // var->act. Pointer to external activity table. - Heap heap; - double random_seed; // For the internal random number generator - -public: - VarOrder(const vec& ass, const vec& act) : -// assigns(ass), activity(act), heap(VarOrder_lt(act)), random_seed(91648253) - assigns(ass), heap(VarOrder_lt(act)), random_seed(91648253) - { } - - inline void newVar(void); - inline void update(Var x); // Called when variable increased in activity. - inline void undo(Var x); // Called when variable is unassigned and may be selected again. - inline Var select(double random_freq =.0); // Selects a new, unassigned variable (or 'var_Undef' if none exists). -}; - - -void VarOrder::newVar(void) -{ - heap.setBounds(assigns.size()); - heap.insert(assigns.size()-1); -} - - -void VarOrder::update(Var x) -{ - if (heap.inHeap(x)) - heap.increase(x); -} - - -void VarOrder::undo(Var x) -{ - if (!heap.inHeap(x)) - heap.insert(x); -} - - -Var VarOrder::select(double random_var_freq) -{ - // Random decision: - if (drand(random_seed) < random_var_freq && !heap.empty()){ - Var next = irand(random_seed,assigns.size()); - if (toLbool(assigns[next]) == l_Undef) - return next; - } - - // Activity based decision: - while (!heap.empty()){ - Var next = heap.getmin(); - if (toLbool(assigns[next]) == l_Undef) - return next; - } - - return var_Undef; -} - - -//================================================================================================= -#endif diff --git a/src/sat/test/andTest b/src/sat/test/andTest deleted file mode 100644 index a9d470863a4af40f23fbccae6105e9bacf8be492..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 193160 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

vY2Ou?UR})C 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 z zQBx~*4`tTPYV6<^oy}-U@-eziHNFb;jREF%b*F1gM0CzDKcEL|Mt635?Ujss$+>FgUUJ*!G%tFm@W(Q29W4$?Eu!aZ* zp&jYG!}eDNGpL&QB9_%4ALt8o72ap;Dp+n7Dbt_{o>K>@zL)GJ-856Zhrf{Lp{C+jS~iLE zE3?<6kVowpeqmT%`Cl ztFnZDdRh#rnw8a6bE7^(+LbY^YFV~1Jt-wJtxAzhr^dHa4p@Kw=ZYvh?rn8Kko_(EW$=O~ zA3;PoOmI^>ah!&m!{q1pUoPE0KM<&Y^4sI?=G)``@5wD_W_J@1jVFiw=gHyfX#!%= z)8vhZsvlpMtLl+@xkwV*oY4zrcV-zM0!lP+11_TC*o|fT?ZOz~FL6?CNDiS8vzS%j zy4RF-!bsi2ZP5!*|M$!?D0BWuDOg!oijNY4#8lpb2WB!Rx{j#;_5<~^F z=|CMksSZx4SU!FfswkMvp|lT2xkvW_Vd<*(Z>4Q*&3C29EkUbK5?0XBJx@Imy{^xW z!EkCfn4Dl;oly3$C^KA^sg0F1N&=H6%!=|m1%_}CMhw~IAsQJ#L{M@e#*~pzMfo_- zgToagBNX<+B+W;tL=)#Io{~Sw^L$toZt0vKoHS-78mY}Ea+ahrQ8f!&ActNyMaL7CM3n1vXzt?1uP^ow-olxkZ7mI%)3f_YtBXDNa7EiTq>(q(| z@UrM6OsyrN_r4c?zLO+cG>VY-EJD{)BbP3|%TW(rsu~X0R#8fi4zk@Ac^RD*k$Wjy>L?(c0Lh;rog9$e4Fox_+QeNL6HE?MxLi zh&)we{?%bLpTI~+Gt_h)si*&N-W9|LDDR5qbPKhcd2Xy^E$JtD?whJPL+wSBdc;Uf z!h<>{hlPeE^4ll6k;-zDtX3tCkZzkXMt%S% zzJjC56o+swBjHZ+!HtAFPwmsteP!H!459W$#fbj0vg z+0`*&)W=A;BS?v)C9s+K#`Lt`^#D?DQpiTaon;g1q%{)ma!yeP&4a&pe1_IO2zP%H z7MG&Ek9GXA&bwX>Uxwp6yaR$JM`W*&5jZjeiAOmy0wqy|^2Nvn>$A!MNOhz$fnCUT zMi1Ueaek0045X`Y-c350OO!J*0$l?1kr4>Wn~{U1r%EM9Qn4N*BQRvqr)^?n1o|Hp zkXQmc8+wh>VjHYwytOl)KJcPA#wK|DjA4f|CrnY!Wbzb~AwLQLtmOu8U- eOCI51=Ay;BEZKJ>nX#Cc*C8{$0DF;t%j{qA*3?%3 diff --git a/src/sat/test/andTest.cpp b/src/sat/test/andTest.cpp deleted file mode 100644 index 118e56aa..00000000 --- a/src/sat/test/andTest.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include "sat.h" - -using namespace std; - -class Gate -{ -public: - Gate(unsigned i = 0): _gid(i) {} - ~Gate() {} - - Var getVar() const { return _var; } - void setVar(const Var& v) { _var = v; } - -private: - unsigned _gid; // for debugging purpose... - Var _var; -}; - -// -// -vector gates; - -void -initCircuit() -{ - // Init gates - for (size_t i = 0; i < 301; ++i) - gates.push_back(new Gate(i)); // gates[i] - - // POs are not needed in this demo example -} - -void -genProofModel(SatSolver& s) -{ - // Allocate and record variables; No Var ID for POs - for (size_t i = 0, n = gates.size(); i < n; ++i) { - Var v = s.newVar(); - gates[i]->setVar(v); - } - - s.addAigCNF(gates[101]->getVar(), gates[0]->getVar(), false, - gates[1]->getVar(), false); - for (size_t i = 2; i < 100; ++i) { - // AIG(100+i, i, 100+i-1) - s.addAigCNF(gates[100+i]->getVar(), gates[100+i-1]->getVar(), false, - gates[i]->getVar(), false); - } // final output = 199 - - s.addAigCNF(gates[200]->getVar(), gates[99]->getVar(), false, - gates[100]->getVar(), false); - for (int i = 98; i >= 0; --i) { - s.addAigCNF(gates[103+i]->getVar(), gates[103+i-1]->getVar(), false, - gates[i]->getVar(), false); - } // final output = 299 - - s.addXorCNF(gates[300]->getVar(), gates[199]->getVar(), false, - gates[299]->getVar(), false); -} - -void reportResult(const SatSolver& solver, bool result) -{ - solver.printStats(); - cout << (result? "SAT" : "UNSAT") << endl; - if (result) { -// for (size_t i = 0, n = gates.size(); i < n; ++i) - for (size_t i = 0, n = 101; i < n; ++i) - cout << solver.getValue(gates[i]->getVar()) << endl; - } - cout << "output = " << solver.getValue(gates[300]->getVar()) << endl; -} - -int main() -{ - initCircuit(); - - SatSolver solver; - solver.initialize(); - - // - genProofModel(solver); - - bool result; - solver.assumeRelease(); // Clear assumptions - solver.assumeProperty(gates[300]->getVar(), true); // Gate(300) = 1 - result = solver.assumpSolve(); - reportResult(solver, result); -} diff --git a/src/sat/test/andTest.dSYM/Contents/Info.plist b/src/sat/test/andTest.dSYM/Contents/Info.plist deleted file mode 100644 index 1e83c145..00000000 --- a/src/sat/test/andTest.dSYM/Contents/Info.plist +++ /dev/null @@ -1,20 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleIdentifier - com.apple.xcode.dsym.andTest - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - dSYM - CFBundleSignature - ???? - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/src/sat/test/andTest.dSYM/Contents/Resources/DWARF/andTest b/src/sat/test/andTest.dSYM/Contents/Resources/DWARF/andTest deleted file mode 100644 index af6ef5d10bab053466b624b81395c936e1cc4e3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 203461 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 Q_)RIu)#HocpccsgANfLCGynhq diff --git a/src/sat/test/sat.h b/src/sat/test/sat.h deleted file mode 100644 index 7a78d392..00000000 --- a/src/sat/test/sat.h +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** - FileName [ sat.h ] - PackageName [ sat ] - Synopsis [ Define miniSat solver interface functions ] - Author [ Chung-Yang (Ric) Huang, Cheng-Yin Wu ] - Copyright [ Copyleft(c) 2010-present LaDs(III), GIEE, NTU, Taiwan ] -****************************************************************************/ - -#ifndef SAT_H -#define SAT_H - -#include -#include -#include "Solver.h" - -using namespace std; - -/********** MiniSAT_Solver **********/ -enum SatResult -{ - UNSAT = 0, - SAT, - UNDECIDED -}; - -class SatSolver -{ - public : - SatSolver():_solver(0) { } - ~SatSolver() { if (_solver) delete _solver; } - - // Solver initialization and reset - void initialize() { - reset(); - if (_curVar == 0) { _solver->newVar(); ++_curVar; } - } - void reset() { - if (_solver) delete _solver; - _solver = new Solver(); - _assump.clear(); _curVar = 0; - } - - // Constructing proof model - // Return the Var ID of the new Var - inline Var newVar() { _solver->newVar(); return _curVar++; } - // fa/fb = true if it is inverted - void addAigCNF(Var vf, Var va, bool fa, Var vb, bool fb) { - vec lits; - Lit lf = Lit(vf); - Lit la = fa? ~Lit(va): Lit(va); - Lit lb = fb? ~Lit(vb): Lit(vb); - lits.push(la); lits.push(~lf); - _solver->addClause(lits); lits.clear(); - lits.push(lb); lits.push(~lf); - _solver->addClause(lits); lits.clear(); - lits.push(~la); lits.push(~lb); lits.push(lf); - _solver->addClause(lits); lits.clear(); - } - // fa/fb = true if it is inverted - void addXorCNF(Var vf, Var va, bool fa, Var vb, bool fb) { - vec lits; - Lit lf = Lit(vf); - Lit la = fa? ~Lit(va): Lit(va); - Lit lb = fb? ~Lit(vb): Lit(vb); - lits.push(~la); lits.push( lb); lits.push( lf); - _solver->addClause(lits); lits.clear(); - lits.push( la); lits.push(~lb); lits.push( lf); - _solver->addClause(lits); lits.clear(); - lits.push( la); lits.push( lb); lits.push(~lf); - _solver->addClause(lits); lits.clear(); - lits.push(~la); lits.push(~lb); lits.push(~lf); - _solver->addClause(lits); lits.clear(); - } - - // For incremental proof, use "assumeSolve()" - void assumeRelease() { _assump.clear(); } - void assumeProperty(Var prop, bool val) { - _assump.push(val? Lit(prop): ~Lit(prop)); - } - SatResult assumpSolve() { - return lbool2SatResult(_solver->solve(_assump)); - } - - // For one time proof, use "solve" - void assertProperty(Var prop, bool val) { - _solver->addUnit(val? Lit(prop): ~Lit(prop)); - } - bool solve() { _solver->solve(); return _solver->okay(); } - - // Functions about Reporting - // Return 1/0/-1; -1 means unknown value - int getValue(Var v) const { - return (_solver->modelValue(v)==l_True?1: - (_solver->modelValue(v)==l_False?0:-1)); } - void printStats() const { const_cast(_solver)->printStats(); } - - private : - Solver *_solver; // Pointer to a Minisat solver - Var _curVar; // Variable currently - vec _assump; // Assumption List for assumption solve - - static SatResult lbool2SatResult(lbool b) { - if (b == l_False) return UNSAT; - if (b == l_True) return SAT; - return UNDECIDED; - } -}; - -#endif // SAT_H - diff --git a/src/sat/test/satTest b/src/sat/test/satTest deleted file mode 100644 index 6a2c90848150e5d4e2ef817fc3470184c3d5bf2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 242861 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

F9a-_Y3m zh{k{GB*?((6>bg8VyYL;iJ~6T{WjJ5?X2XF~oK5TyJ^ zIN@j9Dt}%|?q@J1iEEM6$q;QI2m)Vk-rmHkmpLEEwAI8 z7#Hh&@72dT%HINlDnCy6IixN>t{~4ZlD3R~9p%Thk$X$a-%t5>wR~qOxENpK2wl6A z^ihm8&6^ymKk$3)&hv0te=Rm#){N)t<04OBGAjYfnf|cH^oP!;Aj|K}-qxyotB==u zvg8QLdVML2pJjD^3o=*Til3^sI94D3B-w=XJvW(D8 zS~xe$6qOtho)5o~P^N_Eh%By;y1=RejoV2%*~--N?)-zHuHIQ&Z22)5it+DhUC%G+ z<5__3SPTN|>jLX`oN*5=`$L5zM=wE~--3Zy*;`Z@r|9Ez#JO7IYtk{DTn0xLFtP4t-3?hWsCl{8(`P1?)-*UO}GAK(?HOb7B~|UuyZ)ls_B<+3uQf z!sSs)UgjSx#MK}Z=xHtdl2L{rudRUXvI?of5pM}W;6)m&N*}R%iRgF}1Xg8dEx5SWs#;TT(#JjE zQiCyBz2KFjd3Wu07QJgVt~TIPA$KhS?5>p}i_e;!*Wik?!8dD|`}A?h1OrD7_EC|= z`I*g+;qq0KB~TJ+&BT*Q(boJsPH(`!`!(7Z`nVFP9lJoFHSd;3RM7CZG5mYfK=R5` zkY}Xe9AoxwgF6q`#5Q=T+m!ux5cg}1>wt+vh|Ozp@*rfDs=U&;&)4HzWbu82s{L)a zCibBkFJB)&ChkcfP~UQS1n!eK;k3HK<(2hgs{+yBk}kBL!IjA3jCvL)wYGeXYoZru z#HIQ;b0Uy`1_F`qlgHJf^O*mF%^nlNaGj~SF95fyTv-ZMUuPwFIV;+%dG6B3mpxux zb1N@|at+*Vk|G=tW{tzsQ|HaN%G!hRk{0|#AJZnqWHw&`;4S;(D4g9@BsyP$EElbO zs%28Q7lDL(O{^>w{RX^TGjXWq8Ly8Id%WaOO^okFJ16WHVhwtPVVtf7;wBr#WE)|d z>^ud$obfa~b2aZ0kJoFzo#%j;uOJLht>(SK9Un7sG-Di_RZHcKiq-jLevui&&qc-Iu*TEUPbl ztuMAd2S`N)KSGXH;Z1dr9o%tnG@cZnxl=){0iA5t`wJ874sIISW>*GqGCbCTCAdM5rftprSYcf z=E!*T>U9?ClPCx;BlT7C2l!s+@$B3Eb7U{0(Gg)vV#W_3<-g({V2d($fri5A7QMAaIuo zf=mIKK#ytR!M79%{uSi`mx9?BT7KcOdVv#UT9FaYV;<^wIdp- zuorUTk8+(0-p97wH{(;p3suQ}uaA#;d3>}_dV-Y~S@Y0C?LYEy-0oU_o>i||Z`8-F zco?_eRqd=EgOxf!*KIepl`uiuUJ5dEKUSCOWPNlCVB2LNsB--ZXR2HXUW(lg?1iQ{ z+jX&)LqHd+Wt0-@O#3q`=>j1P=pGHe9lWZUPVTE%&6@QheT*&E@qp&O1ggnMm|(GL zKxXbH$2T?1hb-235LB^t;!G6_tGt4d-Ry;?Tu&gu=($p7Zqks4xBA)_^0lNUVM(fMz&CrJsZe>Q@IcbDyil*XU!)anNrP2+Hy| z;!L%4L{p&EjkOD|Qkt#?zqUHxY{*i54Wa8=;Wc$Tdt4vy0IzQ8`}%0vHTQu%R69UUdC$C+m$uu%tSu(LBK=QW!A57(yZu=a4`(C5tov{VY0+~vjp)>xGK3+xzK9neMIm^Js?^Dmy)Lr`c zCb+aCRTWVux~yMIa;<=5uYd6}BNSl4*=EK}o>EWNM{D>hdRdzNgq7~sa9 zr#;{0*0C;zIsbr_2RqweR7Dk?)<>A4*eJxqc`D`je06LEe8?TvwIgOt1y-30`$cc+ zaVDg>IcSlVdQuFMxpW!P-FMc9^0KrO~U zW3SJ(-G&sxx(g-H%8nKCh_@#XjS5RTy0fs*5$_~OQSX!{JdRVf>xg=%^cAj| z%@-Pa*&V9*E1AVLAi%C2H_79YjyvRWJ}Rm1?}18EU2-n_ovEC6u2L{N0HeC4B==oO zy3?vkxF< zI>r?`R0%>5Zk^V8b--t7!x!|S$3u{rA*eDh{^E!t|WN8fiE^oj%Z`fYO+I2n^9 z;Qs03tJ~JEM=XX*8M6vaWGA?0;h!<*Id>}smOz1yc_5%qooD^&E|vO2O+DXQCP}OD z82VeBF{r?~nr7Xjcy9ng$orxa{{>z~D6ln8u|9qf%L}hQ?f`B+_X$y=dDiM2^&Pzma1N-$|@;LGzh!Ze6a zb;EcOsO|ELetgYcLOk>%+*34|sxQ31c^Z^L`DJ?N@XuiDyD{0N6?;G*N6j{ck@sif zFsR$3D5CUIJ>Gy8I0< zAw6AP?&%Pl)_x9qudQi77=^}KZWB~522F;+@tJBMZK)p}Ko~p!_*zx8yHT`uOoL1& z6bgoy!`3y5v{)bMXa+^RJ9C3~fyO&p^BnK-;syH@&5Wfteghf zL_}xK7ia<_@XkcTZqmp3b3FLFwYY&d*9P8P&%eq#jM+V4k2>Atc53iN+K*Yh;$f9vDZKKkkyW1DMZY;~=SecD%e zJcP0aX7q!~*dyk8MQ@KWwz)RSnrmrn#6KK~Y9+qt=1>CZ8L1IR(C@YouvNgr?XA?w4C`qDt^ON>Fvz7}Hk zp_t^>5ZCMDXFk+F!%+ItKpwwO<@Kf>kwdBx;R2^OHAq1vNF+tj)5k%*M-=G$sLBrM(9gix>eV(LzpXGEt z*TI=qMyAA!vKaX_%jk6NVQM=ri9^qRnKc(@i#6J?hZP#TR6F+RYT6`53X9*jVl;#Y zFhg(ExstE3zPf_pki|&XimW2%5+>KzAlKpg{nkpRU;xAU@8(u9GFdi2`g}vE#mqJ~ zG#i}YdU z8v+~-IvRJ328+8p@#BrygI@c?%$H28!h2z1^ zdkLMs({*>}R(^sj#{wtwzGrt;h$$S`jRnNiKOcstD3L|zDSUSD632?HD{w7;1|RoN zOa&Y(lEv8iisj7+k!F8;HExmCwN`z_TWalH7A+FalHpL!IvaoO|6%Dj1xN97D9aMpTMt38!OoDu zm4biQThGYr5#IGad7a{2|F^szaZ?J};crvf+t?@V=?0oDh=%1qgs#_W> z>hL}U`!#Y9YFSp+BAD@*2CO@6Zp6~t;s+8ibq_hqN@&C@lbXu)BKyJ-N#Mc0a;;+M z@!yZbYaYpPz4bHs^%bSR`xB| zznay33-+ewcB_H$mUEJ<6{rh(HOuN;7D2W}g zn_-Hmvc6Q@l*OW*Qq{VtsYXQ3C__Pr&|>Ppx$z@2`{ct6pIy2drNM*(7}n_{eA0r>H%X zbPMb7b8F)uKWQ1jBVSn81d_f$aUx$@%W*J*hf?q>s~#EuRpppTdI^Ma!ioo> z99|O+U0Mxi) z*7F|Xh#gjaO>HYiqE@rVn6|@e#2V~zsn#klo1z_7b98MTQb$|w!8Qu=?48!1VS;f- zSm%4v!rEya28)eLv+6v3guTGV6F!?ikGD?bJgsCd);RA7l?a3)AhEoi=$%0p| zY;9cMQo+VhFnW*{!JxNoy{ulu?h3G!s?FoAfFK%H!I8bl(cvrTXoC@}Zbn-xxNc|! zeRk;?Y%kSUp`{k=82T;_hs%4>ZPrRq3oOP6q?OlWGtN!2gbS(`t%=|sgi632Kn+*= z=gu8C_r`w<8{Ba2y3J@V$d;ea+2d7 z4mV=Yu&iXqJvQk$xCZA~!IM#Vf{vRZOlo{4PLq-t-)_*MDm7^VSQ3yvOr^UX3YZ4F zL`fn_;&73Klq4P~G9+2%mXxIO8#+{HvLJan+}<#a9#7Wc0aieaILw#CA)uCdx0cq#-zh1 z3nQx%j_?w+(2;2P;;2-u$e6LXN=wDh(E+fe^NU<1o<7;qcz#+29;1?JU)mD0qroyx zLBcT_X&C8KlBm{LmLU%(SwR{p*&}oXjEf^GYEz+(&qf6tF;s{NGB+=MVo*&2ObRAI zZ>CLV+Pvg6D3cS9rl9i9#VMPUteFT|BFQ7IL*#BmQ{qJ=*+vyjje%R>vE=#UWXva{ zI24mg`J5oS?!dV+gCJKV>>j2V_b?USNAl58)BEIwJQg#^5BlpP z;cW}(vB*!4BztMV$1O@KOFUBg(&;|Zq9m1sZcFV|!Hg#u324F#NVlK~p~Wo~%X8S!m_S#vYYoN9)dd8TP`+!8ZF z#JI({Kc(a}ju3t4=UZlmMv?j)Yle`=ar8Ko4bY6;W>M97$!08FXoh&lC!-G;rXn^M z|FT#cOV*xj6ReApm{g|0-5Gs#JuFe3 zVAV_)1nQ9KD%JQw)2vnMLTN~owjf!hE(#Puw&Aj1f>%=M61CdQh?<`mlR49*V+@qv zWOI^NXurOeqLk7Msz<|Js>?tVrsp)?+%)SIUOD{ce{v7LBVaYpnRTE>)7Dr>qZUrt&~pWwo8=HA}xhrw2`^XdUdjXxT!8MePOJe7T$uM5I> z1*!Kc+PJax(ldDKGz1+5hdYhb&kT2(0tF|4KioOfSHTQ-nzh#P>`T}JE=E?_tyMmn z%ZKVVAHvgjLyV9=3fX8zN$vh&(qr#`wSXKhtgPW$wNih{gJ*y6CRvUO5@w4tp%CvS3O@|2v( zll}j(Lu`FpbxlsygbAA3n;c#U;Jx4f0=fdxnT9TM{+&E}1!&pSg0HLV8`o6UPp*SS z#N23o&E%>kyzbZMG8HAo&eyfkwP1qLX0B1ua$vjiZ1|F|^ zFpp`Qh*i$tEb9(C3AK(y6FbWJClXzx#o0)0A5laZ;oM+Zuf|!Fi9>83s3?QXYcCOhM{KHk07-QE3|eN0NXTi4y~e%9UHZI4UAFaI8MR@xJZ$zEvLKev*R<%*fz$gtK; zdu(@imwQh4?rm{aUiV&bB6(4*Tj-wZt~LMJ$0XawrnGgRv*^9O&%4jR=e~E&Zg-oz z(4L%pCy?Al?x|hdcJG!6yKOA;u;LsP(*(?Nel4sg?4o4A9oX&8vL_pc-0x{Se1<^w z$i(fo*;}OW#fJ8@u-@xl+hu2@K)K!9e2(rRZ`)ctcnp?6WhH{T!b% zq(1}IJ;xq~>=-4^7IYgZkW9H&W&ErzKG6^v;XDJtq^;3ZkgO?=QgqO zoVSGas6B{{lpXmi)0}>f2vP2CHZ^pW+|>8t;+-b<(NFE%l-=FCyPeIGz0+OR+M~D}@o2X@hW{h!cfw6`bM3M0 zqdPm@tq0J8vy!XS0rYXTZaQ>u@t@N?^L?HkjsM7g%1n>zfI#=Q$ELpKmUr!WZ|`UB z(c9cR_qM&~-j?TfEpor2jGdXXx6MvZ-s}FYz+GiePI1cZOv}msbgw(h&3O$zs?|-A z7!mjAy;r!$eSuVaYO-_k*7x_iuN`o=?Q^OoKMxm%PJicKdtx&B{gmX(?d2ofn_hS8 zoCRCqVv?WVYiE*@mE2{Qj&!%b=AQbxyU;mp>vOQ2dycf-CcD=1FYQ`m`=0(*R!L8f zOII{xy!I92t*!PDLNL_?(Q_tPuiA&2R1;FqnPs)w@g{YNK`4ZGPcf-YCiN*{{mDL> z$#DSQZj!T+U9n01Z<9J5jfIJ9LU9wcW_MZO9c+>h?L9f$B>#dp8L2WsOsp#B7J^_u zDTQr9c*P{&+!KV>c-kaq0Yf@*LYr_%PFTPFhB>T=JyDnD=Tu~hQDmk`-enmx4FYz( zNj}1I)9exCX7Z&bIn(;{<=ty{<2F{agL?C1&5yg$dv=yd-e;0u71rmM?{inRb#=LH%JcqP-BDzjjMY$U1Rtplcz{IID$wyg_b-Bm6Q6J2F zMC|kgGhg{SJ{Wa1A7d&Bbh<$P=5xt_2u*3eo^-y%owOTWyvv?Il}VdFMXUTT-lGp; zasrZTP4XT(#Hpr$=KC?{1q*j=)<#ycoo=Y+qbKJP%lgzl(=)NP-Tthy*m zGdWLZ{|rSo84>d_Vek2vj|F4$c`9FH^{U(n1)3_AYhh08%KZ*v$ncVp`zs9ucec%p zbEKakOJCz0()u6gkfYae4hemXb4coKoFj{K)-+wpNtQd)K0et_HU)jhP$DRXY|Lz$ z-+|#6z3zK^oz0gOxC_f;KLe?B5ws{og#ng$85a zaqQ;ns?l-=JetE6ohLR|*YKGLe`>I&&RZ&5mm}PZ8QD5hwmUMG#Q+5DQyCY2c(E9=+dA+n{$2g8y* z6Pu={S|#iJTC1v>V0{e-xatf_Gg&T4MIw(nNlKB?JfBM4_@wGFFiUc5lne88a#K?U)Ab@= zB*F}^Y3;^pvf@mx@KWhqs)gm`8ylNxJs8Lo!VQhy{gJ*}cupWx1SC;a-ji`CMcZE$ zvZAV*g2M*V3HHJVrId)~L3GnL-MRvo9z&m*#16>oJ z*LlJl(b60yWUjMMSZ=GGn~Vp1JWQOU#@NLBc(cyiACob;k1?-_MjJB}HbG`%l1=Q` znB-oD*&GX*NUu&R%KJT2UK77H2EznwjTujyu&hpaJZ&Pb2CTzMGI3O$?Ho_bHbg~C zgjDB6VZCqHQGF&*>> zJZNI6yA_uNb`#~&xjG)LUp8H$m@t*jE6g)DS!qLx2{h^a1(dyhx(O8N?8Rtbr!xZ+ z=F$0aJoJ%6eZrV{j?N15Lx}? zHenT=s~nU`jy{=ef+r#xCXxpk3z#^G&hxZ@mppg7?p8O(TjydTz$4TeLbyOCc%kz$ zbveqYXyOz)?=yLf$<%}-jLGzUgMI5D%S~2}i>jOOfzD+PP-Nw?!I(&aY>c{~Ly&CZ z0XpYf;Fj%($tK{RbA@GntsFU%O)Nj>KCFf>RPBrDCO%&biV46MgJNRq1ySe&O&mNn zmsjJ4I&0io%);DU`A$1wqroU7pG?9ya=4Q|G`9p5P12rJPSr=#6qxSx|6gS5` zfd3ZaKYg1ax`{dB9BJ+4C}}s|p(GH6L=$Ah8EtiU+1Wa4QcOq@CmYowhmTA(!9)1M z=211+q%tOC2d7hDj5Gsp0&qA}EjvHC3zKbglKKCHWK2=(Uz9f|`4dcy%XTsxXeO|P zv(tgkKogpjtQrQ1CM<+=7l?Dp)D4mZ6Vbu>FA(bNGU~u|6Pm&K(y^RGcjm%HzKjW? z;QY*HP6yPTl2Rrhf^#n@a{?kJmVxtMAOx~8K?$5MDPS@g0VoqazGUHM+1scGp$g<*@vsr+*|UcZGIaC2WUgcB z=3VHCeaJtj-<5Jn8~g%_){Kgo1={a}+#h=m3%+Zy{@EN+9r@Oij zx|yYm^g%y)WRax&UE43V9CMQueUIeoSxz(A*U$&u%=i`bK_8S-Bq=-l$p4O1ML((! z`R6rVP6~l1R{tr7D*3s6$hT|ya7+&IFIN77QAIL+hy3;F{k6Zdfn}cb4~dauy^(HS z(cRDo{mLVXBxOP$bTd29Tl*${f9;#}A^N2c%fY{3xk)$gpiFy>rJJ`=SeGOJV(I3+ z)R-7L@rZBUQ02zZgYBPu=9Sfg7(Qc1^YUtRA9VA0Ke7+Hd7;%8-Mra4x(|8t?A=#A zndkn#=zDZM%e5x|r@1eWldG!oe@O>;KnNFPUz-qi(sZSlbP%vYQVpH8?d~8%ps22{ z?yk^XRa8}XrP(GBR#^raL>(1ESmX!lsG!3DvV+K?$he@gsSN(yW?%*#Mn{-)?mgdo ztKQPVkNiP>AbsBVo_p@O=kCipkJ1R*v31|1PB|`o^ARRIPCuNU(e*6-3(ChiT3r5d zpcW?|Cu`(XB2qq%*n;JZ^21r%+?e<{bbCG~9LH_PNAw?De{j4O)&Fof&e@)bk&h#` zxbnkU+wL*(H%a+@Dki*hzoZU{8b?^a6%roR|8Y1@_14A6$I%|!n}5Ob#~I&p6C4U( zC+YJ|Z~g`2U$_PRuq=tw52uB3`fb{Re5@HZ8udc@;b<{VKF%1&W8&kSG0y%EY(YO9 zNRo?2{R`UfMTy@R6W+3aQiq%r6OP5ir7__++q@tq94m+OV#0CId3j9uMO)AhOR6~i za3&h3-%myUDKY7{Hz##SJ|_GI36HZM4qxN+!|`ie{fe9Caed?ViDTHW#OOEO{Ep+t z&F?Udz9sp4f_V9d`V|~Ur<(_II@8VLIDEQ!9Ealoci5<5^?)64j2rAHk&k;1OzN2L z2I2?vaqm3CHyPlAoYsR(_>F<_0CK?h+`)!#O$;CO#zAwi{zJ~ehZ;G*3Fs3{PaQTr z-*ofI=V+2O-F%Y6afmc0pa5}sayX8a=ElUIZa&HJr<+f5_;mA04#(+JT>3bN zikeSzd>lya7NbAD-g!_UoXe5pm-S znG^9mogdPd6Xt_&E1EAP^sR!U5O|f$*T6a10hTZ{l>On-_C94#wi* zDC3De;mVY7ZV@nadF`|m<#sz$RAGV;^O0|E-pUK?Bc?4co)|n;uLTHnEc^5FD@MC zdU5IFfbZBC`8eo{s~oG%_86CVeSas2~M9E19y zpT*H*G9W+L&*CVuBfy7p#F=EA9dS4r)C2KxN*UMB;J7lb9C2(JCm-jRaq@AH87ChH zn%|GfKR(bEwZ7(hgd@bbdXA&SM2!6M=A;hki3!Ki;>wtCdsN8%IHNo& zMn1l86}5h4`8dstTHkOuPBdfN!F5TUa-4h|eXfhq59gn8^6{akIQjUVQ(QO>QsdIc zX=+^h__9)*{OR^L*nZRPZ*VvcVGoV54~}Ew=5zQ8QJj7_xQ)v{PH*G#k7L}p`hla| zxcK;9Pn>?!?ccC{;`VRQPvQW0o2`ujF^-*BcaFkxa10!0M;r(@$CLxULUU3~_;mXm zoc?tC92|~QJ11xd+O}9_P@^S2ZQH*??Ja@;0Pq&Z6@~7K};&2>C zlW$o4LpgH2;&6NeBrbg%T3;CxA1Bw_H#N#fJ;H(Yd4c%B@fK&-9|`b5Pn=)}*O>^% zS@vEr@$pHEr((i!=-n0wM?P@)eK_sO@DFxGdjQ{mUZ2$ApPr%rSiTcB&bpFK1buNV zUNCHy58*f&56*Lt4i3nN0`Y_C;J`d?9K)gcihvyGfur*{J#d1)B|UJW9;XM+)eni$ z1Lx~4G2u9859*10;JiI#X0F?D3~id>~KKyJ**OSit1&FFE>$9bg*@^L?q8!z$w?+SfhG@Mp8 zLylDWL#{<~6wBB8kJWP56!K?HYh$N-Y&(Z758p(+K43ka0j)A?U-yLk z=zQqQ{Q*6?pr4ppJi_W%7rH1>?PE4r44uYxverGQm6u+bF6V~H=|0(CDja91(jMWc zywPll*5R>YrYeSO3~Of}*FilJt(9y(SE%NP^I5G7RUQ3;hpA?PthSLm?Ubpww&c79 zXZsEBTIg0ucF3OTnO9wc;>f2jCCb&-%M7iXs2IgPdI5tv04`QIWM`ThcXf&kQ}SFM zJ=>_$Yx}G1`a1=>t>|upB1t!qE@i4*iP*Fw^jUy`l6xIUnlZOd@BD@rh47A04sDkG zvo{)b0s9V4FXk^5rbqMiPLk*BX;`JfN-b<7oyf%E?46>r4`E^HVvoG^8ILJ}ZJS*v z?!HqV-h66^*P&}=Fj5;i$qr%*#nE_*%soV3)1Z#Bv0kAWQN)vSS?VKoEjFoHbrOlX z!jdE;3kl9&efydu7yaa|o%*$ zsoe5?gOuq-^`O85LVd*`BVmYxenz0JWQ*(&L`I7k%`@~K+GPD`KL1#2g!#u|B<-gn z$&U7B%9-(s*Vwi(K-yTx22Iy#yxyn0QF^tH97NExfo2b!4;rRve9n}~KDs&Miw?HC z$`;2`h|b?Lspq&ey_yfY)nN)WPC#dRlS(GV_7B3AxOhJ3Zigw*xHS+Z z3pY=vl+z3JxeimHziqLwUbvJU?-eworq2`0$&S47lox6fB ztQT$|f7$ZXe9&KYm;#L($x(VC>}eOz2mM`#DbTpR93=~3ZM#ADnh(0uVG1;EI!DPu z*p!RsgFe?`3iPFND>_ORZcJZpd1^lBD;=glqaTivg(MLE?O*HjwJ~@ z%ktEG&{c;i(74$ir5D0(a`Al7w>V6J{yXC3*p!af^0)2?Z!m@Bn|1ir_^Fbf!Fa^5DVqsah8MNH; z)O^sZ9Hu}|SS&0Hx14I0r{;q`+hGdyO%@Bw!kYpQ+rFgcgMQ3m3N+pvh^k)*OYDoX zra6<)?G96*af>}l7T!R(+3H^NLEq*u1^Q8oh4YA8Nsn8enh*L(hbho_dm&0MgniG& z^FcrFFa`P*i-q;VTM$3DJT)KmYYtPOXB-K;hGpT6i6+Za^FeRzFa;WKP(EQH-CKH7M!1-;o}3iNj@ z7Or1-Bjst!Q}aQ8*I^3u&n*^~g?4|F>l1v?w>V6J?${4@4a>rtE(o5fxZ?Qz#9&gb6(%PZsgMQs%3N+rRiIRn|m94M?=_Pcp!xU(| zeG?@MVR;wN2R-I61^OpXqGlgDyBsfyP@sQF|yZe9-qeOo7I2nkZQa+dtuK4|=Y{6lmN$iIN4KZ*uwZLEqvq1sZPwMae=sA9gzU zppSEy0{tzEh0E~)3474;)O^s7I81@Y+f7k=A?#-^o)7wEhbhn}EP!3Zdf_dp9?Mhn zL9cL_0*$w#qV$3-A9Qy1K|kU!1sZQqMae=sBTfe&^g4$r(6?GFoJXYdlGDKl{i?$h zXuP=hw^V^VSIFGocbCl&Fy@X!i zFa`RbEEbl98$n;QJT)Km-40Wr=eJLzmxLW7$O^FiP5Fa`P}9r1a@4Y9?Rr{;rR>M#ZRVT*Ydr=YxLTVG8vB zSS(!cQ7-o#==1{pfWs8%f0+lq2w4(#pXI6fpdWCU0*$vmqwkq^FhDkFa>&JSG+8|g?flhujYe3++hkd z-bRhG7s7UO`|CdFT^y!BV~;*c7Q(P+&$b7RJ$u65)BZi)aQ#LVcA&L_(Dyh@fqukd z;rjJ{?z!X5*{vp=UZ8!4DbNR7EUef2d5-)+-M`11z8kF_YCh;o9Hv0uVzIEj@K*32 zEKkh`{kFptXuKsHRaX(V&7>@Wp-%3@(zcr*DN z%Tx0~pYJdQ`kNLD%fj2sTYb*u5w!0x1$tkLg=OJQ=lv~D%?CZ#VG8u677NS5ThW(W z9y&7=`bvi>(0EHasvHsaxQpk5e$rtIG~TF=l7+CJxp+S4mmQ`+|JGvRJmSsl-&>xV z5Bd#$dQ}aR3c9;U)X0fndc#FNm^3d8! z=q`sT&}oZ>W#NtYjOC$ya-oMDra)g|v9PT7^9&4c(qCoMqdPT1U*j+Z8gJG|wMT^A z<>L9Ezv(aq`X!5n^N2U}_qFw==7Vl_m;ycDVqsZ$n}5Xe)O^tE9Hu~DYO$~^y!ro% z)t&A}3H=L)DbVj)EG!FN0%m*xZKLLcp5-tF8eRjUY>%)*Ts$B2;SN)vZ?afeulMtu z51tARJJ012^pOrzpchyytQWi*+-!BHvrM6HbC?1RF9%WfLfDsGJRkH|9i~7(YO%0h zk4f0$mWR$og?`du3N*YYMCpaF@40wB=;s}#K>wS?!g{?fVZX9GH6QeE9Hv13#bRMu z@YwLK<*E6WzQLBQnkh6qI7H?uiQB>M#X*xy8b= z;5A~U<)QN-p?e*sKxZu$mNg_{Im=V?L6162fxgLNVOj7-akJ&2dN1^C4pX4-vRGIa zJXd_f^3Xa>=zAQdK*N(oR5>E-zg;{Z^q(B2K<|1Z>Pc8Hc*NM<^3Z(~q4#o_0^MP; zuq=4bSZI0ZEK}&C9i~9Tn?_U~5!UbG`Jhj7m;!y4#lm{QD@Voh)O^sB4pX52$zowy z@Zj+^%R~G3Lf`E$1^P{kg=N9p$A4L#nh*Mq4pX3a-84-(O4#m}hssgty&R@M!&69< z?Gbi_i|2!GahL)PuOd;h5Vpw0^FbfuFa^5XVqtqB>;%h0cXWkb<}d|%*kWN>2ph3H zG&d1?ox>Dpcs7a3Bf>Vics}S$9Hv0S3rdtMgnik?^Fe>rVG8t*Ef&rrys7-e^3;6L zFFH(te%)eWSqS@;<)JZ6=-)U@frbZ`s5~O~7XgZ`<*6li#@iIRn|zqoilXm7KvCkpib z77OPQ-fvd^gN^5d?sb>~z3+A43(JD1oc%2i?dJ$R*I^2Do5jMinnmXWtnM`*^gM?t z&>yi_SXNTP7F!-V7ZrM`!xZSVEEbkkmavNDq481ZNrx%W_gO3~>wXFQmgTAWpdWIW z0=@0cNsoU~bpl?1I;>4;A3*3XhbhqT3KS&^VJlrcA9Sz76liz|ijoEILfc#2Yd+{X z4pX2PSuAWXq?2H&Ks@nw6`tvB@R=d;oT@o7Sj2c)4>P5)?o@XJSj!VLfFGDo)7vlhbhqT zniM4qI^X2-@DbVo76eSBfzvS}cgMQUv3N$=FMae?g z3AecV1$vpo6li#HijoDLUvl~JLBHxS1sWcmqGWwg@5>?oS!Wv`^svJeXn3`X$|J(A zaPfT5S369BzSUykwhdeU+1c3#{f@&FXn3oN((4D(hy2j?B{d)P3l3ADkGleOC#=_P zqVpH6?sR8M=sO&yK*I}HlwJsX)W!2bKjAP1I(2KjUhw91g5{xghtSI$ra;5{R+L__ z<({8HdNm*PJ`Pi$;bALE)(7%=+N zEG!G&%r3P&H6QdR9Hv0S`&g9iQ7#KznfaiPc9;SUPh?TDKB)KQkpC|_+xVdGaF_!9 z2aAPm4^M6XZFy=w=s!73f$slOe4T(TuX1+wL0{uA1sYz`qHO zGRm6PRzlBpm;w!Nby0al8UNCizYqF#hbhqTC>JFQUh^Kj*69WM5r-+z%j}vmT#nFr z%H_ugeXhe4=#5`RnqgV+#&@yhsrjHUbC?1><7@G<;IXgC^3eNMLT~Lb1$wc?!g|5G z-xAAH^FenzOo1M;SXdT30p=}F%?CZ^Fa;W(|DwtfWqjE6umipSDD;sIQ=tFTVqv|I z&PJz$5Bd^^DbU}rSXdUk5&pB~srjJqb(jJTZ-Y^JgwFqEb*DXKq5tSG1^V*Oz!qV> zkj~HV0uS9&5c)NTDbVn87^N4&R^RPpf$npd0zGB1uwL+%c#h?vyFNmn?=S`WWs8Mn zA?y{)L+8js|H5Gk^bX&E{$W{jBy2~^Q}aRZ>@Woy-Wa3og|Lsics}UU9i~8EY_YIj z@alM}<)L|w(4TOa0uAquQFb(jMEIg5q$f~U$aSe}{>dXvKx=zp_VSQflm z{>t*up1aV$ahL+V!#~H{9v(1vv^-Q-h2Gg=3N$=nM%fEte|Im^tNEZWbeIDDJBx+$ z2#=aq*nX+zgTC5f3N$=xM(KsH+Gm|!pwD)g0^RgE@P+mAS}IfH)yyFMt(MK-QBc~+ zVaaPDUtqbG#mD!|uVzNPmXX3l3pukI^;(9e3KZG=t(Hy5WUgGv7Yhv!X$m7RlNpX6 zRB5d0wP;6gE!Et5qRAIlp2CXSqf|?7G(AlIyK?E#A&QG95}M7XbL+FY61i~743Y!6 z7Is)yAr;J@by;GkR5IiFEO8e}F#Xe_Q!|nW$pKyqx#}8c4^%BfxxtB%G`R{ZklRc= zmL>+-qn3Tn7lw-n%M1>dbCY-)%NIxmBSh-{vHPQme5~jLHw?*lRBhpYyHRj z3IfcdmLa76vz-2=&&68(U-y$5e_ayl)lW`;h{NBLDg2$f_+8tY_+8tYh}TGb)}L(v z{RQ?$1c$sQCH|8V{|sRa+7J0ZD-i$C?UFjiq1%~=tztip&vr)oh<^@YY*#Utck&KN zdh+P6{^NnqJUKhyd6J0w_$7&7lK8F2m_$H6lssP$h`(vaqz>7%qhUDoOXe^BMLaxT zN<@A7Pu`c*K~LUiIOdo?_FtqA;3^_GKGb|w;=d~Kvpa#){B3T0^gcz;_3@WJo75aj zpEZp4OF5XQu>EePfcp5}3rWNJg84J=2=f>JqWtjuWg_b1&udz&gXT3c>UlTmf89U9 z{69!R%qi8xd$K8`nV*#StuCsjg6Tg&Xnp**CH~tIKUiMD_-v;7`2H-DzCVjmS6}r* z#PjonaovUfO5!Vt|Bw-*`wy0Z^r6?!2&+&3xvfn4&uuk*`jGQ#ApQ#y{{@MEsH9J9 z`iFS<`)fk$)AzP9>3iFlh{5s-KK}>BXIVD?5`UJ&SE$%Jb>JKavyqbd8;n1jfFQ=4$M0&;_4`d9f1jB6_qLh%OU4?dH$Kt#tYYH- zQtz19Wvv{M+9&@&7T<{{+)o z8x#Nd|26Ub9;9Uc2IF)0h`LwLxh!SSTp&W=QRm&HR3F>(T6;}=pC=gfJBa@OI{lCQ zV_f24GAjM93k*8ZMhtboVET1IA+m|Jo0*KjXVUyA3U8u$PZU0j<}*?FRvzXnUfr*W zdNj;K>R`&}HXh~|jkxb&-q46|>tR07h;L`d`9^$u594H?a)oji#%2 ze0LB1dm~P@5&d>uK$Ewpry}va>bM-)Zm3!IEy!dP2RqBT#jt=0-cToHF<%~ z#Ny2^avjy=9Z>h=$R=;Ddk~7-)l6@;_sovThA{3QW_fSE+W^u7=V(SmIUcU@a5;8q zJY0?`jqmAQ=4Xg<{X@Ut*9gw~@o$j+XFcBt=(%3-UX>)u{o?e$h*((vH=0bki1A5{ zE3aARVZd+Hcv$~C31@w-k$EThA0{HoZchn6JoxS^5qKWJa^NL+wcz_x#%EAHyiV+Z z`NP42e$s1ZpOJeUg`d%mW*NXbmHf9;SCivuOK+Qk#>td8?=1tA4JZPg8x6k zHwEw?5*}rTS42L%N5Kwn3l6WIpBMQ}G{~@?@X(2AHSD%&-=yZ``8@w%w@m>%z;3q$ zaMU6C6GM{YY2z+1DiN{hsis`u{fJoUb__ zPHN6z{lBQo;GY*csQ=B2437GL5N%AboE3uaDEuvgpDOsyf_DjC5FG34C4!fZHu4XG z9BPkT|6d5ybF{nbg})~JXm`&A_|fiu5WvyCUJT%9U#|vm)aQquFnXdsuOa=p+|{=Y zj&h$A{0za-U)?VFh9?dGp`!nf1oysU@Py!VXpzeDlY(PfdZOUoQ;l*e;D6fS2Z@~9 z!T*fG4-*{iy6-rHqy7Gz__=&b0sN1GUmd`A*v9aGDS)G0KP5QY5!!W9?1^@LAj#4B z75nhG&cD+|{^?7S`WbSjg#T5MgM8g7{C5ZVpA`Owq+C#+(VuL$v{63#lZV9qhv?Kj z?|((khCq3>(?Wywe@M!uUHFTHvpv0TBY%zH*9w19_|XqMBm5@`Kl1wv;ol(qu+NUP zpkeu668=>p{~*FyAMa_C?xBMB34W-^nI-rcf?p%{*+=lJAxFyPFu{4hQRi3iqXhT2 zGkB}W!OXRbaMp8fHmNzgg@2jwKlHT0(LYxN-yryL!v9aepD_He^KS+B1fM7T&D%%! zhes05`s{a|k%Rsa{mJZYGg<=dgZ@MXaP&*KLH~V8_gIq8{g^NOGX%%DjN8>1moXpM zB_JRD)gA#H{nb7Je7WQcH^Ctv?HaeI(cUqRDy}>(iYGZ{}V3z`AlD z!sk-`hqrO`KZghoZ>H-c!^a2?4+uvHzMSx#Ne;aA-y(QU`0>UuHBbG!T5!CjOFfkS z-KXWq1O0hL$k&Dc{>@2^tQ36f9XwiX&heVRWpE|g5yTwYLWj0a7f8*YyMkHD9S0V>DmN2iF zwWHA=Z)C!52Mhi{!pOlm(j_=Np;XnH3MmfWpU#qD98543!_;Gt5 z_4Z1^2QD>o76||Kf_HB+c(dR?5gZ+I6(OK5FBrsbo zUicW{%^GR^XE+8wTjb!jCHl`#5)NCjq$_6_c{d9`yj#tcWWJ&KXM6a9PfhU0g&#M3 zFBSa90r^Plx5AINK+!MFAqKV&JXfHd9!fakvgiXu&n3dY*9A$P;(mgkqWNcgR~~Ed z$91UZog@5sy9V{`YRwZePtGG5m*%{L=)-S9~54{({JX2iFS(zf}0om42fn z`0c_EFFUaR1A^mb`!-vf2+sYt;V>19Ij`2Y0>jW%c_a{|>?T`1_ zCMpQl2VZG}p1TQ-8~d0S9Vz%@pEK$1Ch0B`9B&q*KkOC!nX?W5JmD`9egLh|`rGXU|BB%FI>!@&|5EVY!;>08dHr5+c(BKOZ#H#+oL{_+NM_N$eFca2Y4igL z!S|B+>LTGkO>lS;A0a>jlez|1pm@C28aA>1#jMH@MEQ1?iGBu8x4+py(~Cx z{GxpOD1)3Yc(0`Dr+ z-qt!z9R1{Z5zsHfwyghc`B!5|-l# z=lsG8De6PN;P5(#avT&n_$oo4$T?f%@<4yy5b|omccOMwlKliF_2*W?IbFO7bfxe= zBKS|&CpEH4@D~J!7qtTf|DE8=&Pi$n?PVr0u>7w`yQb=)fBO?&Z=Zh?d@z1IZ)%=w1@V2O3P;NO(?HAnF41c!HEn*QnEX2Q9C;w_U;&oKCd zgzq$yCb@FoOxV3=g#X@oNexX(z^jCFerJ8o;Cl-G7vc9LUsnje!(79UFXW-$+e>iV zKu5pPE%>2QpE1uoMR0hP#yq4VIJ^$iqyAkiINnk|TkwAr{DCWz8bSYam*78=c0t{X z{yi)>Ji+ZQ_`eDcFN@Ig_k^>ZXP=hToJY+t5w@icgzbhe-}Q)`-2_jbYxv2G`ggG4 z@P2-@{6g2T%i_+Jtno|?h`Yr^a6 zb5-*7j_@b1HS*7wba$qLuIJw@{09@xcEFoJL&ATn;PC2=2mTAe@pkw| zk;50PSUx;yqCeS%aJC!19C3>9A1VBI$h;c$p-1@P_5EGpKUMH!PB;2|M(jT!IKF^7 zD*TrS-rj8Z(VyQyxT5od+?@?ad1@l=ShDE{+i%;(+cy| z#{}Q)Jd-Z;e_7{hi=R!a2Wqdvp6H6R=uvc$`=# z{DWG~Y!6=}ED63r_>MJ!SU6i zalt=C2V|^2JZ*IdzEE&@EIVBAQw4ATWKtt&7bU@edcMKWk@omm!ns}G?H$nbc_pspjn#%=(|4?vv{6)L_55eJ;6aD9m!%V(Ty)3CEd`#rbC7kuydKZIZf1_Ra zJ8v{N`lWM(|E*&T{%Mi(S>eZ9Ts?w6BRD+lz&@`De%;kZ&PBriXTkSN7#!(tM+WC| z8Q#>0_X&Qb)MvgI%)cqY@%1{`;R?Y=rM+|;cJFq<@zuh)fW+2j7RGPf9Pf-AN6EP@S|luv!BShQp=z1y^uHji)WdD zuL(aqprb$hw&s_}^k;#PzZZT_^oQNHnQ!uiw<}wOe_U{Ub&~IG^Y8P5cU_p|N198U z-`54dy>{X2pb;CeE6i@~W|(7zK1uebAr*x^*+ zZ#l>CqkPMP5B;Zfu7Q^JooTv0!l(87w_(Ow0U z?mtQc$Pmu?x?ARrb0pn$n&0z!#SS+}zOEpg*C}tveV#pp|C1u;#0evRp5U7V#}}NS z|2=}k8}0GJ|EA#h3I+O&KM`JU=MBQY15G6A@qZA!Ie^cSdeTKW=Xb$1NzI9Q^%}w9 zrJb6a{tan4v%TH=llu9O+Zy~T;fIHO)Y~rz|FWdv-=)d$KP>$4DzKM`{F9Yf3%d>wZi}0MF#(_@INa2^FD0w?}>e0 z6#jdzF!-gy|6hW`oA-8t&sbp69nBj4qSUK{31>awAsF+tj|%>l%+t`mN`m97(>sa$ ziwWoYwn6HfFZgGL{~nnqK+ih`hj-k?!v8ekY#+RtdzIw(IpK$gQq=!F+L%9lKYu^M zIbYut{f`s*#|nOn)c>6Y@6mGPf&RQB3JaIChogn>^uNKsuAIr65 zOC>LT!iv?$FJ6&O_oUNnSG6Z@YqCUG&Pw@EJ~+) z`%(h~r=+{rtXeYAvw9V0W^Kp%;c_n5LoB@m{Je1eI2pW{C4_)+mK1 zVaaGFPZc;;y3>RUf>mq_s#q5gD@JNoTdp|#UP_@_&hSh9xl~`GUDv1q0m|{3B4h0p ziko7kwq$~?Tw%!Mf4YjXXn<-bx9^H+?0vf7#|ZD|5-5ioMj}zpjTa|#AIns;qkV0Y zxol5w=aR9^1m%$movM5LSZ=tQ=XzhxkBn-nvy>^5%K!%3#xv`C@+mTZEB{Bx+K%jK zE_>!+j3Qj68rWz#j!wF zWK)&yS$I+Sg05X9>LwOu3YoE~vvX-(Vc6kBiVI|2Y~rqkO8Sw#QDfM95N7p`Zu8Jz zLSqF|!;h{dm0Yro^o z>ZpxldNkc}^i9`(k#Z{<<WJ6QyZF!_mp-OgS?plkhanw+eZIXdJYY+tuCO{WQ)DEIxik zipH5hWX)M0)lBJ0LzjTzsRM*(=_#uguk2aku~Qsqv39J=<`gft$oqGb`OPBTZlXmeV{( zTYo_-S$(uztfj|tg^}uLI>%F1nqDN6C#>i>e#yxvr`uZES=0V%Cynba!TwASPoPsv zjp_saiMEvXBg9LA)aq`Iv#38)HRDvGl`WVM!yspk+Y|t#fo`Sjr2C z;#5zs$rdLusi$R>-auBxsXhv(Z zkWaO8alOGG|*M&s}4a#HG zQ>A!UVGHwht9AW|qMg2>C~b+fmw1yUSSb>TY^IRSjjf?Y*qEsS)RE?k72Qj=_fUt; z{YuCPPT7ePjdnVBYZGlobL##3i{)w$SEEGd3fgNJ7|j%@CmqgAj8%K6gs3y5X?31j z0OtU6u3X`)i5yvq<3Vo@H|12x<<3m44^&c{s|HDluE|U}qC>*~jHx}kOi{q~`!v#W z8z&=V&#Yz2L%R3Ja76usX}ay)&{#n;?Sjgt_R>;sC{)H#Gk#i6nw0`eq6RbVIJJoS z0_rT&10^^5Q{^@LVd3QT23}#pRB+Rs>kc+OPJ1FD_J)ll)@F+njzsH_*(KsC&?`Gc zbrgo#zCm6EI~-y+B=upJ;2S4exu`k3nWZ-VBrjJrNTr)0b*R z%*3N-#b6@E|ED?)`q%5#p$EJUJwMTgG!=VEnoO)Kwwt|m=`mV5vcNc@dr!w|2ls~F zT;k+YZKa|fTxlYkNmIpHpRb0hqMIqurXNj}rF06l@m|+e^9~rAuxxJ9R73W=Sbg1b zu;PT3KWfT1stMLFx^=vW1%2K24YQc^me4#pxPQl?(xG&fb3+r^94`SGb(wNQjPxCP z#MQ+}196`W+>YN4(Pn&WoF><`x2Sd$uJ{qNQdTe6@pCas!MG)WHt9mzq~NoFlsy%o z`0bUys?Rs`2r9n8`V}O1@BP)WN)OfcM3zd8=E|9TwbGMKky&UqK@F8o9g4I-$YsWR zvIFTZ^v|-E>(HC#Tw&7<%UF{+ zJI2*5U`@dzq`_kK!+c%+&}S6`#qNB$QsphxNwd2`g=uC4krRnfBsYV2FB<4W8k32- z?Nzb_)hb#5>mHQXcxW!+QQkE9g=G4^VzHX4+Y!=*X<7zNJ-M?nHg*NpK}Q!k$|zf2 zFL|i2*EN=DL*6xY^SZu2Rv9N?I%o7gNb3E!@ey za5~Y_#tCs#kcydT<)*r(kf-U^7AI+aGE3{I7D)nEolx|;^5c~3+z{geNKWlOY~ zj-#(`3A| zoGVl++=iy>OI)`=HZ)PmW_IFYYo{(?T{W{@(yeK#Kb)Sd6HN`P8@T(^?m!DWUUfsd zJ+bjh#aeJalUPvBm8i|pnuJzBeal^0>8=B1-N~DR1?eWVYD2*ZPQ&S~$7l1M?ZMRa z4#fl}Rd(!7w3;zDO`~9F&?Pft{b@!zI=CleXeDG9CQuW*3PzmlC&1Q;wxL`$&)&*c zt^!N8=W-oax*HLtDCcL zirPl40}aBcEj1?5Hj*pogI1onjPDEOsWs z;9S>1uCnIQRnX0bu;Cb3)Yj>Q>4`b;wMQgw6cn4w+}6#eblavt8Vh8Ks}XbR?7+We zC080FbByUy&_~cT>R=e!Vy#+~Ef&nx6}^^4_rH)vK0fx$d*iurKH?6xH`7X}*kp?( z>yeb~XgS1Z29k!gq--L)wH)2g;EjiL;jbTCwzQh#s$q*}i`M9(1NpS8h`Mq$^nrC# zz=nPTNyvPOWk_s-MRu~6+NiNBN}!WYUq`4sE2&B~KhAqTx{C?UuxOp6P0D+6W|7agwTNB5GC^ZQ zWA|^%7*$8BlCR&@$AX)z7q#Hl5yWzKvCNgn_4AM&)Ru5rf#&u2uWOaL#zO)^lik=2 z&ETvxcAvPeCynKCt1!E&MDLsLwv&Ato^wMIDt~{~&2_BS|7!rb8B&`@E+y3s=Bd{GM7n=+)xLYls>p((q$TSWI28%FuRcE3)S z88%;~c80IP1QLm!N_5F7YA!Y2yWEYKQkOz~9IYL3T++APSt%bi%0%S~yP=WWkS1I0 zx-~`_G?B0+yoN3y>HOJqP?QZOVx83H&ZPNEFG`%*BWkbi3#rM{44BVOh)Fjl4P&dW zZc*1xcT>z+(L&l-b44mmT^}Sjwr+h|P8$wU)9N&Ev}`&b8m-Z_>1N1D z=;gF77+R@MyE&eq&2d+noDa1wFX2ufgoy{R6Ezo&$NQ%`?kF=S$lr*2wHEe~O zD=&4X#2l5bz~;^j&)HYSb_G%6u$$CKM|1-DE@9oz%s5sqFhp)HFp69Gj!^~ z{dRZ{P?uFhzaWK1@w>vyDOPPERJCk&JK`GJ58mj404O^!n7j8qf6a5=4sCacKrEJ%+4f{sI zo1lIx)38f`>@>D-*S+QRhn)0YM|<>M$KQJYA#mg!I{HOTHnYY0O<~fRPhxqBmL6HZ zK24oqrAQaL=$b-$vbCYJ!JQ(kjW(fSmm5RO#i^ZjAv?%s69vgWJwT(}cWXsWN z(@70^X)c?Yvip77va&em3N1@CI*BOSJs*3W%2Y7ovUeI{H~y&)AE$%le8E(Q>95XA nJB_iYsn`%fadpz}OgJ-?gOP%+Q^WdAkYIZ%O diff --git a/src/sat/test/satTest.cpp b/src/sat/test/satTest.cpp deleted file mode 100644 index 06489ce4..00000000 --- a/src/sat/test/satTest.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include -#include "sat.h" - -using namespace std; - -class Gate -{ -public: - Gate(unsigned i = 0): _gid(i) {} - ~Gate() {} - - Var getVar() const { return _var; } - void setVar(const Var& v) { _var = v; } - -private: - unsigned _gid; // for debugging purpose... - Var _var; -}; - -// -//[0] PI 1 (a) -//[1] PI 2 (b) -//[2] AIG 4 1 2 -//[3] PI 3 (c) -//[4] AIG 5 1 3 -//[5] AIG 6 !4 !5 -//[6] PO 9 !6 -//[7] AIG 7 !2 !3 -//[8] AIG 8 !7 1 -//[9] PO 10 8 -// -vector gates; - -void -initCircuit() -{ - // Init gates - gates.push_back(new Gate(1)); // gates[0] - gates.push_back(new Gate(2)); // gates[1] - gates.push_back(new Gate(4)); // gates[2] - gates.push_back(new Gate(3)); // gates[3] - gates.push_back(new Gate(5)); // gates[4] - gates.push_back(new Gate(6)); // gates[5] - gates.push_back(new Gate(9)); // gates[6] - gates.push_back(new Gate(7)); // gates[7] - gates.push_back(new Gate(8)); // gates[8] - gates.push_back(new Gate(10)); // gates[9] - - // POs are not needed in this demo example -} - -void -genProofModel(SatSolver& s) -{ - // Allocate and record variables; No Var ID for POs - for (size_t i = 0, n = gates.size(); i < n; ++i) { - Var v = s.newVar(); - gates[i]->setVar(v); - } - - // Hard code the model construction here... - // [2] AIG 4 1 2 ==> [2] = [0] & [1] - s.addAigCNF(gates[2]->getVar(), gates[0]->getVar(), false, - gates[1]->getVar(), false); - // [4] AIG 5 1 3 ==> [4] = [0] & [3] - s.addAigCNF(gates[4]->getVar(), gates[0]->getVar(), false, - gates[3]->getVar(), false); - // [5] AIG 6 !4 !5 ==> [5] = ![2] & ![4] - s.addAigCNF(gates[5]->getVar(), gates[2]->getVar(), true, - gates[4]->getVar(), true); - // [7] AIG 7 !2 !3 ==> [7] = ![1] & ![3] - s.addAigCNF(gates[7]->getVar(), gates[1]->getVar(), true, - gates[3]->getVar(), true); - // [8] AIG 8 !7 1 ==> [8] = ![7] & [0] - s.addAigCNF(gates[8]->getVar(), gates[7]->getVar(), true, - gates[0]->getVar(), false); -} - -void reportResult(const SatSolver& solver, bool result) -{ - solver.printStats(); - cout << (result? "SAT" : "UNSAT") << endl; - if (result) { - for (size_t i = 0, n = gates.size(); i < n; ++i) - cout << solver.getValue(gates[i]->getVar()) << endl; - } -} - -int main() -{ - initCircuit(); - - SatSolver solver; - solver.initialize(); - - // - genProofModel(solver); - - bool result; - // k = Solve(Gate(5) ^ Gate(8)) - Var newV = solver.newVar(); - solver.addXorCNF(newV, gates[5]->getVar(), false, gates[8]->getVar(), false); - solver.assumeRelease(); // Clear assumptions - solver.assumeProperty(newV, true); // k = 1 - result = solver.assumpSolve(); - reportResult(solver, result); -} diff --git a/src/sat/test/satTest2 b/src/sat/test/satTest2 deleted file mode 100644 index bbcd886bd26b4b2e8be7c791b6c475f0d105cb71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 194256 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[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 -#include -#include "sat.h" - -using namespace std; - -class Gate -{ -public: - Gate(unsigned i = 0): _gid(i) {} - ~Gate() {} - - Var getVar() const { return _var; } - void setVar(const Var& v) { _var = v; } - -private: - unsigned _gid; // for debugging purpose... - Var _var; -}; - -// -//[0] PI 1 (a) -//[1] PI 2 (b) -//[2] AIG 4 1 2 -//[3] PI 3 (c) -//[4] AIG 5 1 3 -//[5] AIG 6 !4 !5 -//[6] PO 9 !6 -//[7] AIG 7 !2 !3 -//[8] AIG 8 !7 1 -//[9] PO 10 8 -// -vector gates; - -void -initCircuit() -{ - // Init gates - gates.push_back(new Gate(1)); // gates[0] - gates.push_back(new Gate(2)); // gates[1] - gates.push_back(new Gate(4)); // gates[2] - gates.push_back(new Gate(3)); // gates[3] - gates.push_back(new Gate(5)); // gates[4] - gates.push_back(new Gate(6)); // gates[5] - gates.push_back(new Gate(9)); // gates[6] - gates.push_back(new Gate(7)); // gates[7] - gates.push_back(new Gate(8)); // gates[8] - gates.push_back(new Gate(10)); // gates[9] - - // POs are not needed in this demo example -} - -void -genProofModel(SatSolver& s) -{ - // Allocate and record variables; No Var ID for POs - for (size_t i = 0, n = gates.size(); i < n; ++i) { - Var v = s.newVar(); - gates[i]->setVar(v); - } - - // Hard code the model construction here... - // [2] AIG 4 1 2 ==> [2] = [0] & [1] - s.addAigCNF(gates[2]->getVar(), gates[0]->getVar(), false, - gates[1]->getVar(), false); - // [4] AIG 5 1 3 ==> [4] = [0] & [3] - s.addAigCNF(gates[4]->getVar(), gates[0]->getVar(), false, - gates[3]->getVar(), false); - // [5] AIG 6 !4 !5 ==> [5] = ![2] & ![4] - s.addAigCNF(gates[5]->getVar(), gates[2]->getVar(), true, - gates[4]->getVar(), true); - // [7] AIG 7 !2 !3 ==> [7] = ![1] & ![3] - s.addAigCNF(gates[7]->getVar(), gates[1]->getVar(), true, - gates[3]->getVar(), true); - // [8] AIG 8 !7 1 ==> [8] = ![7] & [0] - s.addAigCNF(gates[8]->getVar(), gates[7]->getVar(), true, - gates[0]->getVar(), false); -} - -void reportResult(const SatSolver& solver, bool result) -{ - solver.printStats(); - cout << (result? "SAT" : "UNSAT") << endl; - if (result) { - for (size_t i = 0, n = gates.size(); i < n; ++i) - cout << solver.getValue(gates[i]->getVar()) << endl; - } -} - -int main() -{ - initCircuit(); - - SatSolver solver; - solver.initialize(); - - // - genProofModel(solver); - - bool result; - // Solve(Gate(3) && Gate(6)) - Var newV = solver.newVar(); - solver.addXorCNF(newV, gates[5]->getVar(), false, gates[8]->getVar(), true); - solver.assumeRelease(); // Clear assumptions - solver.assumeProperty(newV, true); // Gate(3) = 1 - result = solver.assumpSolve(); - reportResult(solver, result); -} diff --git a/src/sat/test/satTest3 b/src/sat/test/satTest3 deleted file mode 100644 index 7302b2c2aefeb5724619148838d2c729fb49eefb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 194248 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

D2lY*ydj z^jP%z__NU!wa@AYQ8VTqZ0NUKp_VtoQNeaC31|6zxR1-!vFIKJL)>2lIx>GF2y`1;a`7D2JNsa!_W zIhMd~K7kZ(!=vdxrv*KMqjIas7Nqo;7yJ}Y2FAP*_dC!MDV8F{$g#pl#7f1~L`Z3r1;z1p=%D`ffCAit znL>fT<}yoRY(Rmxf$x||>FY&f0}7}zy){n{p{ukMIFnZ`O7T{GTWx~&1QN{SUv+{W zrpl*>WejDw*GEPxm|dXUK|~;l&%Um~T-SFa2J^I7?DV~egwh0k1W;fcg8h8Dza68N z?C2^pN1!~lN@47ff6?4)M<{w2@4y6M5KF^q#rxikzXNY~$B4c%Pbb@$9~}>2&~EW9 zdM0Je_mIR@pkg$xj>COWPGf#cPVER3lxOWB&eZn4l4x90X3oOc!ggkl{upjVEQte;^G7$aa6-jb@rgU3eveTp6gtM${PE7E4*5{P=}{6FMRaIClc zg`YyJiBs_@_Y2<*#xN#ReGw1-9WHkNgRceo@nAP!D_DR242v(Aq}lO?{D$67=7|ej zk2(|0%qo5^mz=6nxtGw&md?5Hi>+d@_-w!6&Kqe(YYeoXPLGb8VB!U4DL31x=O zXLvJj;VzPhG4oE`s5RsW`Wn^$GZvN?Q(8;N8Gt-og*ut%sJAZq+ap1{YK%uAVsMAz zFt3T^w!-twFDn<_F?t#lUrd5*$QueVokOw=F`Y3b5()Q+q53vSsbHoY%#U4r(GNd$ zjFeIUpBa)5zQ4Fpc#+c%u=g2nQsAYPl~}I>Pu1(}*wpJ)%i#y-vp}HgezT3HA1pG! zg+l>+0b&A-<-5u1{$#OoFAz(}o$$5*6`rIALt zC1wxH+-gfRjosVaK)4`au7odb%kxGAhycCt`4Ky!-no371B!xrx`TNq5{kX zOuVEZaUK&-FGx%Z5@z2m!kcL7j^3=~-B2jTzZOiWEOF!5DKXzJ zOg84>L)kOB&5ocP^6%VuZGO)Do1br*7e4|11Zwti`TzL|@Fy^ad|duh(Q!Wpu2K2N zSxKox-h8^iAKI?UVFg2W9zMonrT2Crz5o96`=l8Wj_Jk?M%CC@UeqLtyO|$3H2+${{SIqmD(rC3zSD-p9!IQi?;*(}mk&5ZsXSuJ%PT zTsJJPRVC&k1lE-qh2WauSK=5M;Zcvd>=QEV$Bp&oG>rl9{)uZwdi>mYFhVk=#GHT>P{kG&n4^pzdBVGS@^*xo z>~gq)HD`WPfx=)6wgG79`#2zD^?$oBIHqjTcE0lYS|IKaamxe(qlvl7W;<|L9Y0CgTvTNBCW@!3ueP578W!c0cw zFDSO5yM=%x!c|oP#X5dMNOC0cJ@7pW0BOy!)NE4#=v6?od1G3*Y7N~P1=O2$1%R9Y z^jyD=0vLUSL{jz;n480}ZuzDMaz?rrO#l-A65We9?#gXLH$4$#odz zdBz7+W`WCahLoS79E=5W^XyKVYvv#WxTo}W(ERK{`TDzn5He|s3LuocE}3sYDN380 zppW-!=%0`nnssOYCc+4&;n_8X2|p`L_+eqfDTN7#6(-2JFyUg~WJSXXj~6D~U6^oX zVFIO_M`Lnf!ghrTf2DSWi(OfmaD8FIMTH473KPmD!3GFrq@dhi_=;^|+svwOU4^Nl zp}+e_0WR8XlexYSS9;u)g{jg<&nrxoUj2>2)H$R(wJ=pI$F~Z3m`~hkg}4itI;kKP z%hFW^+3^{y;zF#Y=8>uS6@|Thd1FCRiy2!;tJUmUnAB!IUzpTkt}P_rYg!7)r%kFb zDQDiq1cYPwks#o|&tHy#LSmPCV1kW7diajuO>A-NK~DGgL)rK#{EuU)|3mzLp~rXC zaaPN?Y8>u2t|mkG0On7QZ(&jywt1hfx#5H4kI#~yF+<(%Jjf_7xw&vN_!as5OI)yz zdqZTKt{fE5i?AwJD>G&g2d;t{CS=TKSwDQ!m4>++4ggqd@%B*D))yOM?9Ke{L*-I-2tvz`SED#B3A&^mrJ-az`7T%4=gl6_vP+1@#X) z7RNjDbAXVVK^HAEFCC6tVhLQzTBLv(SP$2kbLNV@kp;c17qGnfAlhRy^S7ATGqx9v z#kt_bTtas2W({M9Zq%m-7S4QAVX_&+TrLlC98w~gz&1NsN9#4Ze*>n7+f`sya58+K zIgQAAuy8PcL}L}`f0?vNHx|h-B+gPgMqF z1SlL|LiXol?Jbo{aDAImIG(6Hi4z`o8?0u0J#1h)R%H{`-0@eUns&0|ALYfyhaip|Ax{lgZyZVbDPl@!okC4 z^a-#b?P>8z*Vxct&OD@5g!L=vzbZe~$3Am7eNE{Z@r*ejcu1S6{sZ+dZMSVw0A_>_ z!g;jq&&lwIzNLDq+dF}mGk>!3#zU`p0}sc^SEJAmF@Vmwaz{ys5(Q;@R$?sD0pj6 z5~2>!ouonKnr^Yjwu#f)f2bcnpMrkDQr|RQpB)Z2_Fw zuGdC((g86DoZ1@fL~QFG`ZYL+H4rTo`AycBTv-RV-aKskm?(*%S84AfGIxXBuHC;w8g)6g z;6W+UBH3*@tH7JX5Neven)L1PjiItprVkh{G1GlROPKVT|fjo<0n&Fhbr--O44 zpl}JC0G4l`VxSM2uoLFA}{}zwErD2T51!wr2PZ_$QK8Yzy2Tg-aNjo;_Blb*;e)tL0Q5s z_E1_XCyo=g;t&*)CKzESKo=@0vK$L!Nl3DjP}+*EC2VzpvOmS8EGetmm$HbZ?28Jt zENwwh76AnWrI13~yuUMZjx@d&L{Fdh{p*$dnYs6SXMVGsJ9qBfxzZTlP1YyqTiQsp zE-j4fTXF74E!wJ`BR zrQ1YCH#dEfvBj`I`GhG0#rdnGaw_f!#!%My+oSD6{q1Qcc+~YL*AIp3`!Tw#XX&ic zc+5;JqH_96;yA5qbO?PRsKD1f-5c4MW9~gSphKuySo-T~c^==gR`_Up)BQAKdR~kZ zs;Skwe{s7hMW~eK-c_T$RP+C>iRZ9KC0vg`ZmY!6|R{Wms!n z=^KbwxsUTTLtS+7ZMtit#XzF3z@nV6YX4L1PjJc+7acu*UU*jZ)_oF^;Q2VZ{%=P= zL7(ky169UfmHN~*o|CkGJgR?^`k_4N#HfDwexClHvu+fGf99xfK^v-{{C`xbqrTqt zb5b66+vzaMBc&5R)NT6_0Q#O~^u+o?=}cs#7f+pbl6eb@n~;89ScB^ijpUaUj-UDI zFZGlM!lJ*|cx8!&>dz#HYCQ-KL*X$EpX|W3DG1e&v{O zU(NnekDJlg%rUku=;vR(PxB)@?4g^`=Gp-ClK7z#u4l^JM-}4d`?2>+>-yE_71spv zG0(r|nM<3}aW&Vxo@lIVT2*O(J!m6+k#0jjp^2k~_`NmSLa7`3rI#`Mtz2+iXq?}- znoCnaIG5{m%RpiDQS)mM)1OuDQKQNv_SN;dm!=;}PazMC>CAUQi)eQ1^!yBWg|N|S zv**wR;Axvpz^3#7MW@*z>s3r?tvQJAf8vX0Uwpo~edzC-);iyI`}y+uXkC6iMxi!@ z`(`nA}#QV_BsEO;=nnP{n{#t2&r3XmkcpkOJcW8eT#yk&H#wTiY z>#m;fYWnZuRma%$tL1l&j~1_^i`=w{FB%`|`)r~xtV~jwN!epa;R*blFEEqN9B4p=d)1y^#{7YEKns%=T;$K`b`DMO4giA zv6QF;p~pSG0u=9&O1FsTkp&W@t%J_^w1Z2F*5nb5zBr?2Vwx$+m=Rv(eg?x-`@b*h zFHBv^^vg1`GKNQ3JGi=pP5CojMHqz64^7CFO8e@lbk*U$i(&ogrWkY)SM#&m=V>b^ znEAdh=s#&b>|vcK+6CQs<@e2|QI6^Fsmyfi;p=Zy?@=9}(D_2SX>6cx`UO}J4$W_$ zd7fz}1xzgprKwa!-I{SC={we|Jh-CJDpq+)uJ?8IaYw}eV?#A{kMs6TxCcw$QhDIt z7u||E88zm6rjNNkE&G(Vrd%A?_wj!lq5{$rFZCX1_iJdOBRpx-bMK+(7ESL*^e*mW zr`&hS!MEu{r}}TJ^v7n_P>XIaUDm><*gT`chPdl?(C-^dcOVFz<-z8A+W1l4E+feO z#C6_jC!<=XVKmbP>>swrQNu9lFbbB_S2Q&T*N4DU%pGEti+JUvF`Y(az_5-Kg^N5+x#Q8A4Ffz3?|1A^Q=TZH9=|Ut{sbi-(k*JPj zXnvIV1|n(o+xWr)ENP~gurl2fZ`174*vW(@%)RIzYnwdDvL9e3$fU6cBwQ9e>Mugn z(UmNfBx-4{4n)6l{DX83t*3aJwGD;8WzKMJUck&~;S~SV=AzL5kF|8#ThyM}wl8CXL0=9! zjPCg-^Dr7s5I6I^^%JIkI4w~pPAfdn?8mKIhovCUdhl?2`?NFBKf_1|BN#_?%n{Rg z9`;k~LKyWaXw^DwExP-)=4%i?KK`}SPTC1UrI+8-g&jsi7%sJ% zOc7aM;_KeNSSEy!+6YqHl!kbx4U9~?XW7$GoPsar=r2DUK|=F$FQe5<+?0+nhv}OT zxa5)jNa;URU)>z(n-JUt^zY43s1fs@t4fP>p{UKywIb2}Lis0L=DSz9N@_kUBJIPF zm1;bEavVocbbccy^Io|%XBVgucP298VqAvfJLC9iT0i<<-JU?H>8FO1 zDJtG|!uG|{wqK+}wC!=phk(bK2y}_*VKyd%SfMu4r=|*mwNO{f^Sc z`&;{3sBu4{`@O$hdKZ@*J;C62wN4yY z-{81jEU2WHpTS6_fU;IiVBc@_Z@zv=-`yxJL#fAF>p(NU9P_@gGG6SMKH7kl@sGE9 zCt8Lp)7*p6O0YkEeISIaa3i+PAAX-F3hTFdxDY=m9YvLO#;^8w7wIVB_U zS-HQGY1RyHWs4;|IN+@6$x57N6!H&d z)~1f}r5+zw?IF+m+8k_ee4nL5tYN(mrS3D2T+5}Ee?{YAeG9QGZR9=8u18})pK^l?2Qk2xq@kB)<#D({o(DnAB%Ghjn&dd^(mSg#)6w!*hM_VKTi&c{CgdU|T~ zd`buZPYk^}i5_B>P{T(`Kc;?%rn0k@3dyA94-3=o8Thnx8Uko6_^{~)>DlX-5S{9O z*mS07;g!)@aSi?j1jRTGF?4+HJMotAJnkpn-3-H~N|mbT|Fqc~>nRAjG||jos(JgU z^lu)!KKM6V2V>Ed@zd`4aD8BIrH^-BU-JJOPFv}nj4t<`N)FcYj=DUwEFJy_9{e@# zb>F3%U$wy0Ki!L4>iW{RboifZgkyb2`rXnR_XCbVKL2`s$Ey)WuT$5TUfg)>`i?)B zQ1g!NR*u5;KV!cEgqM8R(XD;IMS3%PIS%2w%2z-4pY^2x>Q?RFOY~n-OZdwA`qGi) zts?Ji@}R_`kn49DT&mRiT~=xTSnVID{U2#Rr~MPOf0FipqWx2}f2#IR*Z!H>AJYC= z+CNA8=W73a?O&+ChYwSTMjZ`b~v z+P_Qt_h>(_{rk25p!Ofq{v+CdO#4r0|0(SkwEv9upVR&ywf}$*NP3@Po|Bm+mrv3M|U)KId+W%PlpJ;!b_CM49zqJ1!?W<*UcAB(L>r<}ZWt{dW zXn&ISr)Ym8?R&JpiS{?u{^r`BuKlgFzm4{{)4o^xJ8FMt?eD7n8QTA<_P?h6J+<%C z{!Hz+X}?|jbG5&>_V?BPH?`lP{R6arp!OGNf1&ojrTrz^@6>)k`(4^!s{O;Xe}wkG zqy6t`|NGhxX@9x)d$ixH{XXpDd zwEq+BpQ8O!wST(y&(!{q_RrG(Iody0`{!%_LhWCy{a+M`alkN#WE+c(o*lJ>5my=!T2nD*#f3~!%Hd$aI3^!DkrH%NOY(B6%-M}27D z)3leMy=izBeY=PDX42kwXfH^6^c>pv3))*id)L$6zO?rw?aidUH)wAL?KPp>etSFG zLqXNso6_F5D0C9-DYs` z7pJ{DY414Nqc!*Y*3jM+wD$|zyO{Q90_yFvXzvEvJB9Y{qrD%|p8n}hmiAtuV@J{6 z`?MFLy?@i*Vc1Kiq6xJi7LV>3Nu|^dGy1}rVA{Luu3p+%xw|ra+;N7zyc1Tv@qtXA z5%#J6WKYz)-+tc1yB00=t5yBscsv(;4)&2e+n@68u%EYc*^(t{ zd2~fAF~2VyOQ=9Pne5eN$YjImEJc|g4-aIbi+X}OZaSJt#s{M+5nWXyG@9r!=|m{C zV610P%5=u=R4Q{Q9?QzHJ-n?dlI%|*$&A{eH??PCAReEwyXp_8%_3B4AJGEcc6-gGg+=zpNjPaBguh8Hkz(g zwf^K_^zd*t(xR#^X-kLGg+kQtS(t$FdQF<&M+}3LOi&@oJg+pfd{AzOa|kkjb(#6 ze~Ra@lu910OcOH|h4mAMh0_@{43sk2OA=~{l%-uXHp%F-pzRxrRGJ(acE1gNzI*VZ z&PCnxmL6G0-2Eo08PeoUy(rEkH1JLvIWYofFI3?ZjH>q2QB{I=;77c$!Vs`+AV-ukZ zJIYKUnZ9%k|6w)}jYs=4-hKD;W{y>8rD|Cx`MUQDXOroDmwt2ay_upjsQ(RSy@}nu zyCrt>Mps3m(VmRAKfEf|KhW>Z45U)YbT-=KrFe8NRjsr9h?L5r?+W@4SwM$Ae&EGl z%u_0lJL)UgD)oBX?0Frh-?D1k>o+^_hYy^y%e9N>8G}CM{eA8;@s+(j_Sorwv!?v& z;)nM!$G_ci;RW>hkY+0ISx4I(?e*%<`}^eCPQ|G}o$9rWt4=j^}!qOZGl zQh3SnHTQKcb$}bsnn$<`F17qCue#Jnu5UijySuhiKBau_Q(bC- z8`Et^xUp#S-L5@8cezR~E2>(5(JroS6r#b6$Lhonxh5Xp?0V6a!Tu9X`&ANMf6PDn-qpKT>UtiEP@u_W5qzAVGe7sGM#5Co)83Ul3 zoAx`cS)JcJ@!ZL-8=6mQ2HZ04U5o&v3K+7uk_uCHyG|;*l@IT8`X-$^PNlzz|3vPZ zblEtp7Bo+(&s~%58>dcg!tO&&lU^RD3bgz4=1HHAQx`R3_s`9f&L6Mdq}?l9Cfzb# z-Oz&Fk6I>SQu<%Cd$)Vi2jkVl?nhB5U5~BQaY`LmYWdu)UU%<|X^e3bFB|9j`8cP| zwo>?l#CGqxE@@J0ns!p^nx=`5G`ViEPlJ`-)8k$nuO1(d^gb9r@w5r9b>l~+x8C)Y zSrZRY`z}=KB$xXZms;ccmM+h*%k>M_?wvn#sViOXKTL5w z)Pv3LH^-?Lo83PjuikHV-!)#H*y4U`ygI+debxkZZHxQv3F`h9cWHupzQuj^MD@28 zH`eSw-tB&SqB_^@K4+4;+U>q~lFGZ??@Ut9xZS^)jGDXeo~%A`yWf}$1GvwaqRtqH z0zE(OT`I)=Q>?;MyYNhR&sN)hU8!%mm%9$B2Cl#8VwdYImzt&2EcdUedP%l*-K^?=KL;so_)m;0Ov>K`um_*sMo2}v@O{&9_xI~_8It&qCZJv0e+x1TKGbpjK2IsrQghO51m%L)XuLGz&qlO z)v8>>9jNL_$2gb&K;HkrIs7NK|3n&}K@WSQHK6TPKfda1sd^B5zBf&Kk%Ox` zTx=yd^5xq+zW72`4F%0MfVQC-?TfZBum1F*eGxZ44GT0Z(6B(m0u2i^EYPq(!vYNp zG%V1tK*ItJ3p6ayut38C4GT0Z(6B(m0u2i^EYPq(!vYNpG%V1tK*ItJ3p6ayut38C z4GT0Z(6B(m0u2i^EYPq(!vYNpG%V1tK*ItJ3p6ayut38C4GT0Z(6B(m0u2i^EYPq( z!vYNpG%V1tK*ItJ3;h4t0-Lv*-`^K9{Coc+%rC_FG=wjEe2gE;gnX5QvGeyZCX_wcrOsNo!MLr<{oShEfN z(`x|$B)dm zywGe%7W0eh%mSQ_NnhpF!o#@phQoK|XJe zr+#O)9n3jyHvw)}Dc%Oo;CR=Yt>UeR?dDl)ju(E*TddaIQNj* zhPb_8?Gckcmp{k$Dl9a|^Us>?@atyltrV-a66?Rp{5tddyj{oJCJvv%+cw^QleY_b+r``O@wS(@Dc&B-+mm>ECU4K@?WMfE zhPSu!HqYC~c>5f0r9N21jaMp?BaLmt0u2i^EYPq(!vYNpG%V1tK*ItJ3p6ayut38C z4GT0Z(6B(m0u2i^EYPq(!vYNpG%V1tK*ItJ3p6ayut38C4GT0Z(6B(m0u2i^EYPq( z!vYNpG%V1tK*ItJ3p6ayut38C4GT0Z(6B(m0u2i^EYPq(!vYNpG%V1tz<*& zIFkudD#2KyH;F_#LLQyP(!<6kb31;0sz0ufDMwE{FsL$xNyFUa-uV0mzPEYTB9t06^( zY4y#IhX*pzU?RG5dDr4ugVD&MSxaJBe@q>kF~(^1Ws>RavPA5dfv65^ZC?`2WR~`Y z6TzNnZ+IY{UDWLh`u&4}rNOS)QeV(itbSdW&UR_g|HWGWU?mc#J}VQAMF0ep#J!y%Ttf3Oxj-_v#wOfR&#cwFB&;| zxv|h}YWb_GXJK|WxhRpH9bcYI#yLhdiBlFcFb6a1~1Q3O9CB2qP8^#YxhN~X}mnZB%gxNSu`xe{0J znB#P5)QX=P$n^QU7T3z6O^1!mV|FAS4X6EV)y`_>?Ueb_WR2`AA+>XA&-A5ZiKA-> z=cI9&hcnR{MUM;yQ0f{1u~nlJGH2Ld!!#UHt3n)9DY$J>4s+%s=iNW{+*E>U6rvg? z=c3YXv}r5hwTf8@tZBkZDA}sjVXI2un0hRZ)G}6p4u3%r5md8uIPOfnJGiKlbFFMf zhmUQ7qrz)tIx2!Q_nI}U)+=J4=Gt`{Tce&@)xbfv75C5PI_artr=BrZiq&XDv0C}y z;MhwW2RZXmJwdEy<}rVzk#{Y2#IM<^Vs>fU7R2JwSJe=57WT8$b}+ELm5SmMj$#1f?Z(xSA-5}9b4MtkOdQL8v}V~I#wcfns4YcCk| zfaE};CsRpmb|9Th_Kt3yJaDqE%J%MLd@!1B#g!aBV4y!W4`aGP3}Y*IQ7&2~9>!Ip z;#KeGof4-VX&o4igjZJ*ljc>4fmFUU#_R-|N2X$6*3C`K%g{)!Mt~U+)(BXFdu1X! zCSb2{Pmj@{5ms-Za#Nj)?Dbfq4K}UbQ7ebrFE9Q4Dz@Tk;jm#;+5y|wJ2upD( zQfHHCL%|dNF5S~`iL8@`(Y<9kE1*4+Os&R%sH-{@v_h?`z#JVrt}w?d_sd!tRRYH( zr*GIbiiX==&7)%y7w7UDa}<(~w$r#ZQEfXCdu~`d9cMbWNu=-a_2bqPKP(&{s9sEq zC2&?xG!o0;sdPznFj~C9@du==()y~cyVaM%;5pl! z4O_j;;%YeE86BnV&eC*9JD&El$@HRtK4G2R!M(z9WEZAm-81n-@1NTrUKQl?oimdf zm}ntwYik6z?O-+?j%72LK51=@9)tOhteyy=N24!~K5D>FJ4Ku zaZ?Xc{y1-V8p}j6HIay576)~377VrMqQkS6hcmHAFqz5XX4b!GX%LUXet-9zU|?}~ zTM%c=tQdx&O~pECVJxkUG^$H-OhN! z=VWF(=5(6Fr9FNS_eT+C;Nu&iDz(T$#){W)#hhElaG#bU={qHT@V!s?5+tGm*HM zn;BYwxjuquIZ?EM{{CcQ(URq@e*a8_W&7}~8?JA-_aK#7_ur=?X2?yFiE4e4>M}!IkEYS6MrpZCNy2MK z1y-8SEM$X$5}H%ba`XjZGgP?A?(AOZZ}H%PE>Ji2 zb(8coGe&n9)&7!}=%vwQHf)Pe^RTO$V z;mUL@OH%W31(jR11l7*{;aEbQyKA(!cS)=tr{$FyD{!VW>WvwysUPoERz)KN*=Vp2 z#ljneeZQkRnka=ybJWSMPIbGhRoy>+wt8+tTSlF;QKf_ax2Mu`pS>w}^cQSenIC_1 z)1~U_8LGK5+j^4=7ymNM%$ni$YIRdHdc*1g^=@->OaA*xO>9#iyUbIj8gAK3z2CA} z<;Lk}DfP*OR(0mIcJ)7-R33oT+gqBhU7f#^YNlbmy1c2z!?ikLd*>9v9Xl#_o60xM zR%@E)sN0+8s?VBv2y@mH)uJB`)SFGzB>byl>Nm~VsGj|}u9>Gno|>SVVwHJ|YoU9XYp!lb{)ti&~mnMg|dU7>nk* z=c@-==BVGfTYdV{L_U~%h^bE|&Q+&OZd0F3R!uYg>gkqNzq-J!ng-R|EnTf``tg5h zI*g}#bPwtdH;RrWi<@dcRGs6lJddiM?TGqf)ncS{lY4AR_qtouNY15NR6+a26R^B( zGali(l1bcO?T6{l+<01~2?l>m4=|pYgrR$s25>R;&g2#~bRwkOWZoUut}gltKXu-? zspBc;jUB5aYW3lcrX_87v}TW>U)>E^(X76@aD2?K9-kag_fCoU)$`l&gVtZX_7mXM zyQ$_;50H0_m&cm&MEzj$(WWgeLq93%9PkCb)lxmX@L}VeS-aJj3vnyOPeYkj}M} zbn359Msizm3THz$vW6;_Kb0z0nOJ>d62EIXabuo=Jp)k-r%~D?r&pq?k0oAlD#tr# zYt>|4gq$#WP`$bpGB|_c;|6A~twHs>$rx~^(0DT#g9Kx$JQFE*V=~K8|zeF-+grPj=>3A2=e(n;A zjdmMTcT7RI%vZ?uTOv^%MDGRoA@Rj2{HX0$`Hf-jOG%1w^-(q8#f{NA=oQVWQ!B6xjOS4e-uRWWk4%VjM5 z=x(5EDDJ4YgC}fMd0TzvMo8^CO0#giuI~uNrkAPe%8lf;?G-p>)L>iH;~UA0i{tgL zdLD5$^fL9tX^vNcxOD!G1~7CZ3f!Y!oQ7+D%y_ejbkc96 zstnykRT=%JT%F-r5l!gMnQjvCE~{T#gZ{zP@^;S`)DmXXFUCLIVZ)XE)Z-{*^^N>f zC}a5+eIjqyroWR)nvT+#=5QMMnX@H@@YB8W&W-5_Wj;Of#T&o|*K`Mgcq)IT?`yb8N<>+0K$+qbSX#XoL?D;;VyLrSB`%#o^F zHZk3#PV(-})VRIW)0@mu>o#pw4{X-1p4noyx^wzmbhW_B^}_=~TkFa;W> zQ5DYnHCunt9PlN(;Uc}?%KiGUm=x7{Td0;+Rr(4~B&ka_otugE<7vOwnlZm_`q*is zb<}{JlT&AGI(jnea$GFMS9HrMY74+OEka$hX-s{%Et=G;IMgE3b1!Wwb8z; zyO6e+3#nqkhCZ&;b5Q+bI@j@X)G<#X&28%JEp^$i z+p1!p+jgs1CZc|`C2OvRX80dejNB(i`J_?av|UB{KvmhJ{wm5FNJ*NecJ{!Z7VNI-iAGMpX%Cbzp#$7FMLjZ89usJ`QE}Gwvt;By;6LC zd(`h=BrN<}N4}tmgcrhBBNyYLY4pwL%&nzYy^RcW8AZ-tPJWquHFO2-7jK~bksE10 zf4@EgpE^zR9VA?Rzu!8cuEI$xKQJbbk1BZ-DUU};pLjG9t@ zd^?Pm9z(3=d6m~+g>6iaL@%~}w_Wum*YD}17jzlPSB2k0*HSq{r*B(%*{t5(R-gG# zx0NqN{2L`J|C#c^wRNE51>UpU;#zbbd~sWJs4Mg^DU*%$n|}2bbW^#PbrHx{MZI4v z(vgwBYX5ce%kc4x5l&;MOp|oh+rn$NLuO+S-vLA9-ym(_P57#;{h^XR@~J*TKAH%n ztZVnqc5)ei0?U*U0Q>w)`?+T9kHE*x#D0Bx*Y@q|{_V|c;*Ym)RiABdzk~h2TX{iz zJe^6>H{rScx$W`%W?l;a6!&I+uUp!lUjqNti@3*Aj^z`ye-h~&FSv)jW8Pz5fIJE( zQ(Rmrqrd(1yjPl@`9hTR*L1J`6tdw{D5KmO@`sIos?J*bxij=}klz2f z4mJL{v|l`5AGt{H{}1_v;bs~$JwjRiiVozpU${)~U!nag$uC~1Bfd)!*XjdT>A-8q zAGr>`8o7!5;k!`Lmg@9i#`!4q4T&w%K0dFv(B$>6qEg+ks?D3xpW28LY2+k_BxXaW-Q7AAXrLmm{Y(9#j=D7$?Ko;>90@aCEd zNTvg!F7L1_Kh0Z2iBaheSI!LqG!{w%8it`1$L(OFz z@OI>ziZBD!0`YV;$Qzmv8gY9&yxx&<-ZElQQ43Ap!0-fL%IEEXwPB?q;uoi|#)op# zLGLhf^`?l5QxVk{(gq52K$LT(hAA75&x5ETPX|te2d2^)dm!^b51}VT02*;2bB{0J z@pg0|;f{bO4{O5E2n>+t2^1(-N^8i40F>BE#S4tMJg|ljM#6b(@p|)aAI`B48Q>G} zg*;m9Lw+7FB7#tEN(mpIGM^i^Qfea%&OA7Pjrtw4kN>~h+svUh6aG0E|58hN_BK3m zYvNpmr)yTKgTr^_aN*ft$}hy>hY0U$((7f;G5?r(nE8C>Jo61;%D>2bFSBPqlioAT zKIS)=hxz}n{av$CdFJMAO#Os6bMV(3ysv`~ckl`aAE!B2$?s>v`fp@buhJ$5$1iE3(TF&zGWu< zcbNmseatE5A21Iwp9ZG#mHGcsUcuo-{(qZyb9nK)CjG~mJ>N6@0>{rYf572oX4m#6 zeeaPb{^rb{?;DouXNXy@pAlxcehSQcvcAlGkfawh>4li_WqaKptY!`|pUs@-{||UI zvpUnnzZXpX!_ZlV|Drip;r}qJ3rzS_uc_bAjfSse?zqSBZ^3l_^2{$Vt9wnj*rR-( z;eW8+^Pu6T9ZY$A{QnERnsZ8c9&>=h<^1HC<@^Qs|564JU$@7{O#0tt&M`}S7-n9< z;YI#`p+8~vK56tHR?i!ryrZ#KnRzQPmDlrv z37^B^L(I~CMwq4j6qu#`l$oXdcwRK=N&E3JFW~$F%wgsf^I6P8%nvZ<|6Ge5@hz5M?+|HAAmoAlpf z4lw_lImJA6XOn;76BB<&<}&k4X3wW4d=aycxraHxJjk44{t5FCvz+e{=8HJI$SnQg z&^nW!^e1`dt2us|S=y85pCM2Kft^PbBcK(bCLN7 zFr_#2xk>LR4$m_m%RJm<{y*o%%mwBfnaj+NGy9rN{J%1XnBBXY^5vO#W-c>J|1r{H z^z%8~=QjLp<{Wcc(qq1o`A?Zf*O6aQQe4>6aSN0?`}nfN*Wf5QD> zO3$;I(f^j&$NVC5i1}0IA?5>S8~q6L3CsoNE0~MSe`NM;Zu0wtImC?FNmD=O2=g%W z^~@v8Mdm!SXO5|#XA6`5Az-Rsk@-qy&vX<1E^`O-*XEk|A?74=j`?BcBJ-AenfPVq z7_)Cnlm5?{^USwN_*N$TMdkqW$ILnAX?vUW^UU95E;66MthP4kJ;m&0-gqCQ?_lm^ z&N1K0thO=w7nlRg)Au!cwXF${FngGP4c6_C`DG5zF>kw{(GN3+m`*$Go0- zh`IY9t{?L$%%0s%ewQg7Udntk^AV2tAxHckNBlnK`&b`mE-M9N&4q7OZw+COL`YGOM1i1lHO&^lHOWoN$(owGRoV7eC0E1@o3%` z+>2+8jTe1ALUE{!d&29$IF0sCMmW0W3e&Nj;k3`iKXr+*zi_>JnGfHd^}?dJ%S-mRnaV$eaVN!XWxcTI z^N#Y{O!@%EnG|xD(1a_DU)eV+A8SuZU50`1^K8!Erey8IYtQrHS9KQkSp_7{Mo zkLYbCeUan;fc3(nFVl{tx0&<>j4LV18LSr;eFus0A*S+o5a2^hdU=2GE7l8BIF;WA zM;~I++e~_SpE1IEVbOa@jF0HOnyUHB`;U8BFD!aHzgqbZVO&gcUu3$m%31ta~*s&c-N`b`|oYca{qmhS?<4-Uk`cw zao&%9kN79F$Gv%M-_;<2ixL$pk_0O_i zSoA}*gAZ*ef17pwcn+hmwR=Z|qL#hrAh zY5zH9(W_>Y05O%{X069{M~7QQ&n)_skyrA!ne=6jKcDr&qW3xUHj`eyuhYqT;d=G* z{hsf!URd;ANB%Zb{__2tB8uwPy`5jJ{5{4!zB!m+y-m!FplQ=Nx*QNiW|oOS4{B^j?SFX3`gyn)>HhFD&|yLvOP#|1zUL zTguNYdON>P9JHDA@_jct?{xl!v0K;uOTHg>E$fBr)emub^Q;%HS3kn~0_%lEpF=(9 zLrnG05#U3t?RS{jFR|XoEc!e}#z*vdO;x>o|L;Gn7Z!caieD@L)Zr$rEzyq2{=%XU zIrKJD`3tP?X1%cJH+21}BTW8r)(eZi=*Zt@%3r?kcq!|JMZcl^J>NF@-@$re(RVoV zx0&(}u>LL93)ib3V*ONHhh%?Y(T8XUAKK9QvzhWQf5(LF$9iFkPvf659DPJ@v$o%N zP1peI<@=(d-=O`zXY?nsUcO%{`jF1On!nAIe~R@(tQQu2z@fL9^z!}Hi&-x$`VEy| zzVCVy>xJvp%lBh{$9my<^?@UeZC+x%u;}xS`rAzP_k7>z-($V7=yMLe&7>b8O8?-!Zn{rBIP<^A`1;;HCQ_(P&}ek0uHD1Twmds-;BYW_A;{__1| zFYARxAJXco-e%H!Up8S!vR+v9BaZi-Hj}@O}^}?dJ^Q)DAf%QLPy|Cyz9QoT!`OEj+?_<5N z=r@$V?@d$w^{f{beZY~w&6IzR^?r<#===$be#oJ>S(pDUwjb*~%%Zp7$B_MOCcS*W zznAsGqTf*cb0w4iYAHXn={soSIF6)Iw?{)M)Hj}>mHs% z%5om-g+=d08R$by<@XZcL#*r1`fH{B%oJWv`2!q3&w63e7m*Hqh$;Uf0Y1c(zx*EN zdDaV4IOXq!qYrVd@(0Q$>@CTkxn6yWZ;ym(#!98wqd<+y?W25Chf1WUbtSpkM;9eFI=xa!20jAUbtR;iuEbh3)ib3VttPF z!u9G$SpN&w3yXe3*RT9O>KfJyi{3upwc4**XU^YUtQQvjkfZ(BOzlU0k5!QRb9$oR zQ2FKeTd%QRxL&>d-s@x53yXe3^_Sm=O~yO{T|dI2-%$DG_hdV>URd-S%0Ki^WB>hG zFD&|Dhy86P`^)dwzR!AL(Ql~y@_V-*vR+v9UPt~mQ~rU^O!xD({bLed*z5G6K zJ?n)TfgY<@b#t)(eZ?E-&S8GwJ2`kgHfPEc%cmf161!zn{F2^}?dJ^Q)D={NC~osXyiz zNGtlhBY&GIfBAjp3#=Cwea@k`ne_5|&NAzTMIUhJZ6>|^{&O7Wxv2dJi@w95x0&>L zx2f;;tQW3Vuf`eu9M%hqKIh2aW?g>PFO~8$*Q;0KP5yn7KeOmlj{I$={N?wsKV!YH z=!YG8n@R7PVDi6|^}?d}I`lS^-pBf9SuZU5oI`Ij=|@;U1@n}2{)I*Fap-L(z5Jec z4(o+Q?{nyFCViRnKaBOlqPO$w#6g=$FTWT50qccDZ|6sPn@KOfFMf;l!u9Gy{QKf5 zA!9#b(R&^Bx0&+KvA&h{!lK7v{UN6EhYafeh4e+%{|^G_{0UQhdVaC(MS7b_FTam| zll8))??4*#AtrqX0Y1c}m)}#jhE4v$6kbpM^84$PST8JkFVdk8G3Dd_z;ucX42<5|6^D$Ecy|x zuIgdi4R; z-^O}j(R&=_x0%W>zppQ{URd-#hu&t=4{`oG^qBe!i{7?ZCl1<7`VrPgST9_!zQFn` zST8JkyS|ja&6K~a5Aavk3ya<^Z>{pndIH|4slTx3ZF`a4X3AgIA2^!z!lK_${<2=d zRjd~l{g5&rV#?oU%3szu_>}d+qPNRitNfmgO#d^#m)k$H=sk}7ZKnLa9KWCS!lF+( z^fr@zi1in$cIDZjAjJ&ycsru=0+j)klj z7QN4*x0&=IS&xJD!lDm2^fr@T*8BK?^}?d}IP^A?KF|5jJj&ExSoB_p-e%GlS${0+ zg+<@t(A!LUS%2gq)(h9Gm-R|oj^_5q>y?P!E^jC0XO)NYm-S7SuwGd7!&ZFK+pNpa z>z%A&y{wNS`VNQQX41?0DUV3`IX%(a=bQ4kne?*W%8qeUe__$v=bQ94lRnS+^{`%8 z^m#}5Z6>{}@A3reg+=dm=xrwbFs~0YzTcEzSoA4}-e%H!c)gbn)(eZ?&aV>(Z6>{s z^=GnPSoA(e{x*|d)~mUO^}_Y)hdBSoST8JkyS%l^Kf?OW5`6xd>(v)H{xa4Ji{9g? zzs*#CS#M`G>xD%haOiE;_UH9192rzp-9e^c@bp&7_z0qxMak@(YW8$f38H^s?Sm z59@_RpK|DJ*7-BHI`lS^Ue>d^hV{at_c`=7lU~-pdYJXXqVI6%ZPxYY z^1deZ|6i70*4NrN!`ILMQZMUqEn~f~l;7(pzs*#BFR#z_E7l9wtM6d_>#P?Ry=|{f z9JE>6pY=Or`TAiNeNLGVG3jk4y{sp;hV{at4;Z-;z0IVT^~bJey|Cy<9D18|{@a@N z`>y2AEP9VaZ!_s-eY5rfQ-9%l^|I;nevzQ({5nBu;{%Gz0IT_=KRa7 z7Z$zGp|_dzvOe3aK~sO>diAoN+X<`}7JbfxCtM)np1l+)19rlz-l9+TRPJXBNF(Ueeo4`Xa~w59@{N)ysN#`>rze z7Z!cqDlg@4vo1fcmp8(CSx-;&c6%Yc&7_z0_F7h({Dnnt*O&A*lU~;6+ky4MqE9LF zAtt@eq|f1{1%)kRy)Yfy8P1MhOE2sHoh#+%^h9shm-IGM{<2=+ldKmOy$5BW4>9R& zCcUgLIQ>{-KVi{(NsN!^y_yV@Ue+U=&3a+c+vTPFZ6Pwy zBI}!eVCpYiuU^(u+>Z6aq7PX1qWarR^_TS*dsr_ldfQ&L>?i9rzR!AL(T5!Q+f4bF zcQx&I)p30NFpJ*f(A!LUwVTna9~!-|=)DfT&7}9T{@bhO-9WGprXDeZWzFn<;-;|8kcf8T$!~-sjNUO!^|{pJBbQ=xuvb{cR?_ ztgrbv>xD&c=SO;*NiXYh?)+m@eqqtu`PIr_*6$o*y|Cy#C?b7`NpCadFYA4d%bEOz zMel`(JXw zdRedZHP#E)tM~Exrt4WRT(3UB`mY{u>?bVx4cSlDS6$3{VbKpO^C2et*-Z79^;mPq zoBV|-i0;2WIQkHi-e%Iv`mMJeZ}h?xzaG7;_xc>`g+)(k(1)1vx0&)E;`Ltte!R(F znBr4hFC2Y{N$(}VhnVyute}J^BLccVfM8z4|ii_hr3sy?R;Sb{Xr1>(%>s z{o4fVg+*_lZ?d1wWWNyWf697c(c9;X^uoVJeENN%tbcnev#fvnD6_18`)6iZ|MmlB zS^u`_M3bJZf4dp8tbaR$dF?)?zuJdc*1tW3S=PUeFw6S4E16~e+tZk3{o6~JW&PWm zm}ULjhnZ#l+dnbO`nMl2%lfy?Cz<-l`nOv!%lfx_Fw6S4`!mb>x81~3m6G*fgUqrX zY@GSBpBQ_rW|s9}PhpnzV9x`4aZSjF&TkKS{At2=nk%OYn8%>QUS|2dJ$@dk!{zt? zL(D_-P5cqfxE^0Ld_VILzL!Pmy}>NMZ)?Fpy!x&DesM?5ITd)u#P4R7->aX-9QuO^ zzngg&^M2S>k1`j}H~dHDK*8|8ne)uMqQX?)jxV65Rv5QZ_z}#qK2Jn5#y4|J_yDu4hl>BoY0Cc% z6aEWk?}LW%UolPi9}VMQA{yrMzsnrp`fl7}!pm%rU72OQiG7*#VlQS{4=XPE(@lOS zFw1&h7fAeNCj16w`M&5=63*xIO=ejyVm!10VWj(KD!t+i1UdhfVlL%sJ*wCvkgu(1f=$=ktb-U{3wc@Nvu?9R4fKO3C_z zcXD{{5EK6i4wv=aip;X!q?%0mW4yn}#NUir*7MtwS=N_3Na7!4;vXsDOAMdHEbC$Z zn%UQ3!f#{_F#le7KNDWmjQbV$?_~}z|JH<0nqtc9z1;B5%mK_ZPkqxh~}J1 zae8Z*18115lH~cv3L(K1TxMH4+u>;x5cczK&V@~n)*TtOY{x7RJr#yW9pTgmu zn~nZT<|1F;_X=a)lIrsubAkJp4~5s7@GUknIFC7$HsQ-PBY%#+nz_LC91^~p z%ftHeuMFSA;qv?4*En2-P56XqY>x{Jdo|}&nftTZ%sH;#66Vl|i63G1a{E43;+IVL zdCc&Wj>AE*B`v*#WY{t9!)F@`^4PBFVTG4%)$ zE9*Jz!7S?=EMS)J3;mc`<}a>dmidUsne$%ryzrqgzkli4)Z{m`kqQ4Xv#iJPJ7)QQ z)YmsN@nyY;6!D~-TGe6nClkAKs&B603psv>?Qt2ihk1lq)_1x~Ga4m6)V~yn(Z?<1 z=be{`agC2KzpCTo{_vKG{}vcJjMB~LQ^S;${><52hgbOf4nEGo=Q{X$2Y=?^{kIsM z{-A@eckufT{_6D6`k;eT4nD=fzjW~P4*t7?TehV9aus`QrCFO^+iRYK4|l{5I=I)t z{YGCoA3rc$$?q4A@LxN^Z*}mK4u09eA3NB!)o6QeVYpJB9UZ*8gIgUu$HCup@B#;S zI{0u0AL-!b4nE4kDF?51@bL~_WfGs_?0o`-t@?nStl;Qj>n zXSlz>y$tsXToLY7xYywR3imqP8*p#Jy#-f-dmHW@xOd_H2KOG^`*0t?mEk^w`v~su zaP)li54ca@K80Hc_fNRb;68`@7u>(${sXrjPQe~7xF)z}xE44!+&H-La8uznf}`gw z58TFZo4|bqZd16;;5LWb0&Y6omT+6aZ4I{#+;(tZh5H7a53Ut%792g7?GM)hHxF(; z+yc0R;1D+@Ww?aNTfA;g-Q226s5z5pdsz`wkpE-+d46 zNVxCA1>r()VYuaR5x5?>C|obx3b;PF7~D~CN5jS8`r+u=Fa>uE+{ti1flI^v6z&wb z3|tm&0Pa+{)8I~rI|J@axSzod!41N#ggYB)<5^w%O66zO5PXT%zDOsvXl+eLdj=xW z0}pWKG;1)Nrc*`5Y|F$}B&twXN!#cweR+ktdQ9S99IY8yO6soMR5hR@q6I z6YL*j1U^2t0vu2&sy-3gnjA7ZeL16kr|l~NW3sM>h_y|pXAD>g9b2?YPz_U6!pJJE zqpVU1a+G{=WUN^Nbg*Wz5KyB;I66Aj?%<+Ieq)m#9qMdSqe91KHY#{@t~F{>tw*GK z3TxHDS%aRj#l|7FiSAs@iR!6gj~<6LVq=;`Y;5W{=nP~KA z|0+`ub0ixbohHs}vT`x&D6@Ox)a#hOMIWIKczz!`7W){wV13L=d`>2sr4slnWznZv zr!kk)IMhyLE+=v*cM)v|g|pFiq=McX-5w{sFd9xR8r7rwTU%4nbR-!^^kpd#*NQi* z67Rs|%EXt%oSBrauB}Eov!nf~>}n}`jR@_iUVkj{Wiet2(tSx0+GB}KG|l72&RWHo z8%spey7T>F)9eNF9grMI^kg`z*?MHw>RTRN5li5dp_E2#0_?`lM>65TC^a*E_RO(4 z;hvtZWHReFH*|g5GYyTyG46|IqqyK~Q97ETQKCO4clk~edu}AzpF&{9-_;$o6?3DB z9#cfq)Hr%JjS{8NOuJg!bZwUMfwV22-#RwjDh-0|MCZ@^^4K#uHV=g>9bCH^__q2| zxIJdOv*Bz;VoFFR)}M;UdRHHKfFq7;-@nwl@3}X^qHc4(~I1!GoJ~p}_hHYhF zVoWS?aIJ<980b&U!(e(ahW033`>2#=V^BLPR>k;|PCL>$Fd7N3t|Vj(QwdL{lPmP; z$z)^wxW*jSXh#lTrk}%g3F-%n@bY+652KD6Rm{041fC}%;dt~5iZK`2d})l?3G@>V z>(4eV&VCNFvuzJ&G6VglJfn`|;SGt6u4ub?Fshh&)Y(8c6;4O`FtqGi+&Z&cLm-?E z_h;;M#T1n^tm~(1R126BP2dr6z!a_4iJhC6m!W4AM}_Am%(L2zYR zn(l?m+a!Z-w>nlGRpGs0qFQlcqhq1%q{1tzjb<*)sz>5&=#yj&S~=K0%I?*}<_XYm z?(fyZ1F0TL*%+?+nAz&1huT;;9y?arsukF(&v{B;om_1zbe3rmU86>|R(P8UN4JAp z39dP=t`)-!L}%ie7_Al0$9{7_H-l=l*|?yhGQ_VQ9&Lc?aXKUOVk_o%E72Yt8{+mm~-T9j!K*L zkIkSG7S39dHa8aGI5-iU^SqbksyofQnWwqx=vn@leX=(E+?9o#D%M>)cDta~PA$^3Ks z!>fYUi8i{{)(FO@L5ve(+03E{#)r{kg19{gv#V3Ek*QhjsMe^vb_ATQ#ENWRWk6(N z&1?$>F?tPBzBqB1Xvjp-f8+MPD1vf33xtw)(cxLk!AzbzrTA< zFtE70E!eM(Xfl}P3kKt{<&jh>7|R4B$wVd_Munnu4$%inJ2R2nFm8(fcNtq*ZrJ)W z+k?T(%5W-}q^i>-VjN~)KG546#ekhE2(x4`_{s7?I%{31ncr{a6VEKF-$W72ZTh?0 zVIVyoUAm}smVZ?wnxgr{p#P8slc4LArzCPTr5TwrlQP6$JzZrO0qsTe$GzbQZV<4dFG&4}HW){n8%t(% z2K1Z(33oEx+1A#0as?WcP8vg68MPy1rk(47GWa#cZk=h`A(~+;3m2S!RNi&TMm^ASq3aT2h?mHwSJQJv_bk)*{}=NA zs;Y5$dNUceMR38{m(c78^=#|W^a@U)9dMBl2GE^;YP-6@hOlRquM9SeH-yWj4lDSW)gk+l9Q4uAOtuGSETvFoOs}Y5ubx!F7Ky1~oaSYybD^6Xw$c7b3bWY#M`yAa!KomP z-c&G^TnUe!GJ6%yP8damZzSf)L?ItMgP`N0EhX{)w0E_?ZQMM(e^HY=+e!R!YrQ>g zZ)uRWz|b!TH+E8Eu^re>y8ZXhkEE#gv+tY~+b{#eHcL8*qDYG3Tkv17{j2)>dcK{# zn*Mb^MbqQg`YRdRF|Phno&PE8j&Y@Zk}Ib=lX*T*hO;HT*XsH0_;(g!BvJVKtOkD) z@c4>6RW#EjU((uPzKjCH}aYN|L zG`}vII!bi>T7CHWrwZqQy^m|siC^O;WvEI16O{678CsngZK8O&Cd)=_!mP6~81*Z52)Y4t zxs9#RW1gtsb^1P@&PSJW8xQN>X4}cnlg(`W`((0N_i!x~J*e{&i05yM*>-+|C%|YV z53`1TdLWpW+oy-#T?_1b8uhKNv_GF!8NIDzcgkQJH-69vuJ-Hk--IDiHV2fr;fht1)_<_ndi5l>lycW~(vIj@xk zI@_sV>W-qNVdntb@F^E{D8zRipdaSai5ME+0jXku`T94-G)bk_jB?+@W zX5xk2LRNM~3*~l(iFJZ(cWJwe08HIp1ZJ576Uvwa)6uUz+O~XV310auuxjiu$3-8K z$)m{}5)I`y0IV4`dAT39Fy0yQWlSDJ+l~;5PY7e+2LLO^x05^EpC3NeA51)!-sKh^9PDp&@!}1GC$M?$2taOb z?6zqTzl1wLT|NWq>il-K{ytexqd9noY_Ky@BRRFce?Ce}ctZ{$Vt?-d7*)zey-3_A5pgHE?r1b;U21<8JWW_6)eYKwey1dw*G;UC5=qBg}w-i?!;;A(QL##n8 z2e@j#0b?ih5nY_I&5C?D>Y!<0jN)`E_AO8?Os@U<%08UC-b+OPWGOpv8^k};8B9}; zH?Wez>$1elKs8ZSO}uJ4GC&%^=qt=s0g5tSBoDV& zPm5qwN!wjv$L6Hq5P?|$W=`pjaDk~riBm0-K> zz7hmvuI?CX{4UC24z}|}3(N^obzal~I^7x4#=v9T%<>R_lVfL z<#smXc(QcG5u`QieV^(p2=666IMn2)zOJ+gfmuTU!gxI8b0( zXi*$hg{Zzcg*MZxwMOU$zos;#+uYNA%F-QQ8@(Hh0TwM%^Bo+D!i68eoNR@jD%`{Y2pF z935}OfF*T~E>UkcPhSJwiENw?lPSlHQE1cSHXk-PVvFi-$=OD`QZOf! zKky>4B=Bg%%topcnp4kCllS`3laY=j-Xlv)W&?u-yBOjECwIzYrgJE9kqEbJ*j@j2 zZWHJftsS5|yPY6*B(!PlUGoAVdx-vpQA{GO6jtkz5Dy9MeqiG|1^ErTAj?A@C*S8& z#5xD|yOwhfHlPVkPvit{eYPJIX-aQ7xu+G!2TkLfi-n@x;mbx}090tNzDkk1JLzN& z+5qlmR9+b2PQvq+RNSn)vZQjFHps`{vly9YaxyNY@csfKLoh zUQ+@=gl0wAX5=JW-Hr_vUgKKzb;}M{AjrJkMZNc49IU6%FG6y20zT8Ze@5I2NU`_j zdF665NC4Zwdt)}bevd{Ibss2wcHkhL(*haZ>|q$#X0rVR7nH_g-DWxRT(0Y*$ zb@Cbc7n>6pSx-2XW41YY`*C^2|9VYH3n%|uEoR?W>pxCzk&1VBf@JKI&HCm9w0wem zs_n@u8;bw@xp=A-L3th&|LIeQWWYvMFh<$=4<$LcYX%cSivYjiB?h zCK$Y3l{qryjbttAKzW3<#2lq{k<2Jua6C%1coS)=c^NkFRARoHGBJ?dL2&LY>0zL; z)jQ~eu+B#=t{VrIYd$oeBb)n|%@SXi|uQNujVHCUrT8D^0NvdYH#$JG}1Z$|4d* z&YO&r(~DE8yyjKai>llS@p=Vx!eV1yZ7i2v?U3Y0D$5o#)l+zQt_BbTY^-3CDPx9) zHH2hhRMUct3`(SUaG0V)8b&Ig#5GcK>F;JmyE(I1u1HH`EtY;z21d!xiAce*mp*O4 zYgeqrD?8(rdJ{(3n_@%?t7QyF_tt7DD4|jQQ8H4f(W1q+SO=?XQ7^V_@sCu+I?ZO| zlLbZQJ00Qm+nJOQRLgc9t~Q*PJwS_Gv1?Ww6TFVytFDSsc0Q3dMpDp^U^7gh_Iq9& zSzzf9Tgr;LmB;a?UIjG|O70>sO$1WHqM7P>AZ#+a^VBd~tMk<@6&9OoKPBL>wKP3u zhbXd{OzjIN^7b>(^Nxesf9>a#(uu`^l`gA6W8RjR-~PqldG{PH`8p_&<{kIGv@Rg6 z`z@dS;$`#0Uh>uSLv(Ea+4p=UL}wE1bAXm$7GGr5Xpsevu6wVWU9~aXJALdoA=7MBRb@0vQ>z4k=hh$bHW^fgG37V*WN_^)|CFzk^ic~K7tgQ%w6ngH za)zdo5jbMU0nNCJPI4bzf?|A|sye~#R^!lWJVmA=5YKHg!mPsM$kVC>t|_QcrI~H2 z>TB{<^gC1=GyzQqF${l0=9^;6z+>^H@C3R}ScFtRb$Xk&xRhtP8Iwdh9cVkkb+Z|E zGF8x((=!=xJFinYZDyK1hg_TazQ@Z zF$r+HUZKu&=xtAhS%9=S39yHxd=rbjzmnuJW6-3A=K?2Mb3hWs*;WUWfRJOxpj^`7 z#Z8w!s%kdmza29M>5nIL!Pqfl@ZXg&xZlqCGUa)@MC)7Af(b|54`Wk;Tx;3dkl5pE z8^@GJN#;DJG;$*7F{Kfy11OztGu%k6)+9IZUD1W(5gp6(m_QVx-gn5SY0!;waq}kC ziHrcA&MSIAQfKIx(#R$Bk135PmzgPHlZooyMP38HgpLroM}o$NbWCZ?E1bua#_(@e zWD8Jr5xPw|h#Z>IT?98x2RZw1NokZ#|M0)U5xcj{7lljh2K=)Bu!S0bCIHytx8 z`OiNgH@?H4-8p7fa!rAdj7Z1V)aXE0H#hPwf_#?5u#Ay=Wc>FsD~<9Q-R6h={WWuR q|L`o$T#)iVE81Cue(5jXw1{^;rg27@w100J=L_U*${(+L_3Hn2PIdeM diff --git a/src/sat/test/tags b/src/sat/test/tags deleted file mode 100644 index e5c45ed6..00000000 --- a/src/sat/test/tags +++ /dev/null @@ -1,467 +0,0 @@ -!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ -!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ -!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ -!_TAG_PROGRAM_NAME Exuberant Ctags // -!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ -!_TAG_PROGRAM_VERSION 5.6 // -AND itp.h /^ virtual AigPtr AND( const AigPtr & a , const AigPtr & b){return _ref.createAND( a, b);}$/;" f class:SITP -AigCal itp.h /^class AigCal$/;" c -CC_MIN itp.h /^ int CC_MIN;\/\/ $/;" m class:ITPMgr -CONST_MODE itp.h /^ enum CONST_MODE{ ON_THE_FLY , NONE , POST };$/;" g class:ITPMgr -Checker itp.h /^ Checker():TRA_INT(0){}$/;" f struct:Checker -Checker itp.h /^struct Checker : virtual public ProofTraverser $/;" s -Clause SolverTypes.h /^ Clause(bool learnt, const vec& ps, ClauseId id_ = ClauseId_NULL) {$/;" f class:Clause -Clause SolverTypes.h /^class Clause {$/;" c -ClauseId SolverTypes.h /^typedef int ClauseId; \/\/ (might have to use uint64 one day...)$/;" t -ClauseId_NULL SolverTypes.h /^const int ClauseId_NULL = INT_MIN;$/;" v -Clause_new SolverTypes.h /^inline Clause* Clause_new(bool learnt, const vec& ps, ClauseId id = ClauseId_NULL) {$/;" f -DEFAULTS File.h 40;" d -DEFAULTS File.h 48;" d -Datum Global.h /^ typedef T Datum;$/;" t class:vec -Exception_EOF File.h /^class Exception_EOF {};$/;" c -File File.h /^ File(cchar* name, cchar* mode) : DEFAULTS {$/;" f class:File -File File.h /^ File(int fd, FileMode mode, bool own_fd = true) : DEFAULTS {$/;" f class:File -File File.h /^ File(void) : DEFAULTS {}$/;" f class:File -File File.h /^class File {$/;" c -FileMode File.h /^enum FileMode { READ, WRITE };$/;" g -File_BufSize File.h 22;" d -File_h File.h 2;" d -GClause SolverTypes.h /^ GClause(void* d) : data(d) {}$/;" f class:GClause -GClause SolverTypes.h /^class GClause {$/;" c -GClause_NULL SolverTypes.h 135;" d -GClause_new SolverTypes.h /^inline GClause GClause_new(Clause* c) { assert(((uintp)c & 1) == 0); return GClause((void*)c); }$/;" f -GClause_new SolverTypes.h /^inline GClause GClause_new(Lit p) { return GClause((void*)(((intp)index(p) << 1) + 1)); }$/;" f -Gate satTest.cpp /^ Gate(unsigned i = 0): _gid(i) {}$/;" f class:Gate -Gate satTest.cpp /^class Gate$/;" c file: -Global_h Global.h 21;" d -Heap Heap.h /^ Heap(C c) : comp(c) { heap.push(-1); }$/;" f class:Heap -Heap Heap.h /^class Heap {$/;" c -Heap_h Heap.h 21;" d -I64_fmt Global.h 41;" d -I64_fmt Global.h 47;" d -ITE itp.h /^ virtual AigPtr ITE(const AigPtr & c , const AigPtr & t , const AigPtr & f){ return OR( AND(c,t),AND(~c,f)) ; }$/;" f class:AigCal -ITP itp.h /^ ITP(){}$/;" f class:ITP -ITP itp.h /^class ITP : virtual public ProofTraverser $/;" c -ITPMgr itp.h /^ ITPMgr( ):$/;" f class:ITPMgr -ITPMgr itp.h /^class ITPMgr$/;" c -ITP_CONTAINER itp.h /^ int ITP_CONTAINER;$/;" m class:ITPMgr -ITP_H itp.h 2;" d -ITP_PHASE itp.h /^ int ITP_PHASE;$/;" m class:ITPMgr -InterpolantITP itp.h /^class InterpolantITP : virtual public ProofTraverser $/;" c -Key Global.h /^ typedef int Key;$/;" t class:vec -L_LIT Solver.h 205;" d -L_lit Solver.h 206;" d -LessThan_default Sort.h /^struct LessThan_default {$/;" s -Lit SolverTypes.h /^ Lit() : x(2*var_Undef) {} \/\/ (lit_Undef)$/;" f class:Lit -Lit SolverTypes.h /^ explicit Lit(Var var, bool sgn = false) : x((var+var) + (int)sgn) {}$/;" f class:Lit -Lit SolverTypes.h /^class Lit {$/;" c -MITP itp.h /^ MITP( ) :ITP(){}$/;" f class:MITP -MITP itp.h /^class MITP : virtual public ITP , virtual public AigCal , virtual public ProofTraverser $/;" c -MITP_H mitp.h 2;" d -MODE itp.h /^ int MODE;$/;" m class:ITPMgr -MVITP mitp.h /^class MVITP : virtual public ProofTraverser $/;" c -MultiSITP itp.cpp /^MultiSITP::MultiSITP(unsigned n ) : _sitp( n , NULL )$/;" f class:MultiSITP -MultiSITP itp.h /^class MultiSITP : virtual public ProofTraverser $/;" c -NONE itp.h /^ enum CONST_MODE{ ON_THE_FLY , NONE , POST };$/;" e enum:ITPMgr::CONST_MODE -ON_THE_FLY itp.h /^ enum CONST_MODE{ ON_THE_FLY , NONE , POST };$/;" e enum:ITPMgr::CONST_MODE -OR itp.h /^ virtual AigPtr OR( const AigPtr & a , const AigPtr & b){ return ~( AND ( (~a) , (~b)) );}$/;" f class:AigCal -PFT_CONTAINER itp.h /^ int PFT_CONTAINER;$/;" m class:ITPMgr -PITP itp.h /^ PITP():ITP(){}$/;" f class:PITP -PITP itp.h /^class PITP : virtual public ITP , virtual public AigCal , virtual public ProofTraverser $/;" c -POST itp.h /^ enum CONST_MODE{ ON_THE_FLY , NONE , POST };$/;" e enum:ITPMgr::CONST_MODE -Proof Proof.cpp /^Proof::Proof()$/;" f class:Proof -Proof Proof.cpp /^Proof::Proof(ProofTraverser& t)$/;" f class:Proof -Proof Proof.h /^class Proof {$/;" c -ProofTraverser Proof.h /^struct ProofTraverser {$/;" s -Proof_h Proof.h 21;" d -READ File.h /^enum FileMode { READ, WRITE };$/;" e enum:FileMode -SAT_H sat.h 10;" d -SITP itp.cpp /^SITP::SITP( StrashCkt & r , bool p):_ref(r)$/;" f class:SITP -SITP itp.h /^class SITP : virtual public ITP , virtual public AigCal , virtual public InterpolantITP $/;" c -SMITP itp.h /^ SMITP( StrashCkt & k , bool p ):SITP(k,p){}$/;" f class:SMITP -SMITP itp.h /^class SMITP : virtual public SITP , virtual public MITP$/;" c -SPITP itp.h /^ SPITP( StrashCkt & k , bool p):SITP(k,p){}$/;" f class:SPITP -SPITP itp.h /^class SPITP: virtual public SITP , virtual public PITP$/;" c -STATIC_ASSERTION_FAILURE Global.h /^template <> struct STATIC_ASSERTION_FAILURE{};$/;" s -SatSolver sat.h /^ SatSolver() { }$/;" f class:SatSolver -SatSolver sat.h /^class SatSolver$/;" c -SearchParams Solver.h /^ SearchParams(double v = 1, double c = 1, double r = 0) : var_decay(v), clause_decay(c), random_var_freq(r) { }$/;" f struct:SearchParams -SearchParams Solver.h /^struct SearchParams {$/;" s -Solver Solver.h /^ Solver() : ok (true)$/;" f class:Solver -Solver Solver.h /^class Solver {$/;" c -SolverStats Solver.h /^ SolverStats() : starts(0), decisions(0), propagations(0), conflicts(0)$/;" f struct:SolverStats -SolverStats Solver.h /^struct SolverStats {$/;" s -SolverTypes_h SolverTypes.h 22;" d -Solver_h Solver.h 21;" d -Sort_h Sort.h 21;" d -TEMPLATE_FAIL Global.h 58;" d -TRA_INT Proof.h /^ int TRA_INT;$/;" m class:Proof -TRA_INT itp.h /^ int TRA_INT;$/;" m struct:Checker -TempFiles Proof.cpp /^class TempFiles {$/;" c file: -Var SolverTypes.h /^typedef int Var;$/;" t -VarA itp.cpp /^const int ITP::VarA;$/;" m class:ITP file: -VarA itp.h /^ static const int VarA = -1 ;$/;" m class:ITP -VarB itp.cpp /^const int ITP::VarB;$/;" m class:ITP file: -VarB itp.h /^ static const int VarB = -2 ; $/;" m class:ITP -VarOrder VarOrder.h /^ VarOrder(const vec& ass, const vec& act) :$/;" f class:VarOrder -VarOrder VarOrder.h /^class VarOrder {$/;" c -VarOrder_h VarOrder.h 21;" d -VarOrder_lt VarOrder.h /^ VarOrder_lt(const vec& act) : activity(act) { }$/;" f struct:VarOrder_lt -VarOrder_lt VarOrder.h /^struct VarOrder_lt {$/;" s -VarUnknow itp.h /^ static const int VarUnknow = -3 ; $/;" m class:ITP -WRITE File.h /^enum FileMode { READ, WRITE };$/;" e enum:FileMode -__SGI_STL_INTERNAL_RELOPS Global.h 265;" d -_assump sat.h /^ vec _assump; \/\/ Assumption List for assumption solve$/;" m class:SatSolver -_curVar sat.h /^ Var _curVar; \/\/ Variable currently$/;" m class:SatSolver -_gid satTest.cpp /^ unsigned _gid; \/\/ for debugging purpose...$/;" m class:Gate file: -_interpolant itp.h /^ AigPtr _interpolant;$/;" m class:SITP -_interpolant itp.h /^ AigPtr _interpolant; \/\/ constructed $/;" m class:ITPMgr -_inv itp.h /^ bool _inv;$/;" m class:ITP -_itp itp.h /^ SITP * _itp; \/\/ construction $/;" m class:ITPMgr -_pf itp.h /^ Proof * _pf; \/\/ proof $/;" m class:ITPMgr -_pft itp.h /^ ProofTraverser * _pft; \/\/ internal $/;" m class:ITPMgr -_ref itp.h /^ StrashCkt & _ref;$/;" m class:SITP -_sitp itp.h /^ vector _sitp;$/;" m class:MultiSITP -_solver sat.h /^ Solver *_solver; \/\/ Pointer to a Minisat solver$/;" m class:SatSolver -_subITP itp.h /^ vector _subITP;$/;" m class:ITP -_var satTest.cpp /^ Var _var;$/;" m class:Gate file: -activity Solver.h /^ vec activity; \/\/ A heuristic measurement of the activity of a variable.$/;" m class:Solver -activity SolverTypes.h /^ float& activity () const { return *((float*)&data[size()]); }$/;" f class:Clause -activity VarOrder.h /^ const vec& activity; \/\/ var->act. Pointer to external activity table.$/;" m class:VarOrder -activity VarOrder.h /^ const vec& activity;$/;" m struct:VarOrder_lt -addAndCNF sat.h /^ void addAndCNF(Lit f, Lit a, Lit b) {$/;" f class:SatSolver -addBinary Solver.h /^ void addBinary (Lit p, Lit q) { addBinary_tmp [0] = p; addBinary_tmp [1] = q; addClause(addBinary_tmp); }$/;" f class:Solver -addBinary_tmp Solver.h /^ vec addBinary_tmp;$/;" m class:Solver -addClause Solver.h /^ void addClause (const vec& ps , bool A = true) { newClause(ps , false , ClauseId_NULL , A); } $/;" f class:Solver -addRoot Proof.cpp /^ClauseId Proof::addRoot(vec& cl, bool A)$/;" f class:Proof -addTernary Solver.h /^ void addTernary(Lit p, Lit q, Lit r) { addTernary_tmp[0] = p; addTernary_tmp[1] = q; addTernary_tmp[2] = r; addClause(addTernary_tmp); }$/;" f class:Solver -addTernary_tmp Solver.h /^ vec addTernary_tmp;$/;" m class:Solver -addUnit Solver.h /^ void addUnit (Lit p) { addUnit_tmp [0] = p; addClause(addUnit_tmp); }$/;" f class:Solver -addUnit_tmp Solver.h /^ vec addUnit_tmp;$/;" m class:Solver -analyze Solver.cpp /^void Solver::analyze(Clause* confl, vec& out_learnt, int& out_btlevel)$/;" f class:Solver -analyzeFinal Solver.cpp /^void Solver::analyzeFinal(Clause* confl, bool skip_first)$/;" f class:Solver -analyze_removable Solver.cpp /^bool Solver::analyze_removable(Lit p, uint min_level)$/;" f class:Solver -analyze_seen Solver.h /^ vec analyze_seen;$/;" m class:Solver -analyze_stack Solver.h /^ vec analyze_stack;$/;" m class:Solver -analyze_tmpbin Solver.h /^ Clause* analyze_tmpbin;$/;" m class:Solver -analyze_toclear Solver.h /^ vec analyze_toclear;$/;" m class:Solver -assertProperty sat.h /^ void assertProperty(Var prop, bool val) {$/;" f class:SatSolver -assigns Solver.h /^ vec assigns; \/\/ The current assignments (lbool:s stored as char:s).$/;" m class:Solver -assigns VarOrder.h /^ const vec& assigns; \/\/ var->val. Pointer to external assignment table.$/;" m class:VarOrder -assume Solver.cpp /^bool Solver::assume(Lit p) {$/;" f class:Solver -assumeProperty sat.h /^ void assumeProperty(Var prop, bool val) {$/;" f class:SatSolver -assumeRelease sat.h /^ void assumeRelease() { _assump.clear(); }$/;" f class:SatSolver -assumpSolve sat.h /^ bool assumpSolve() { return _solver->solve(_assump); }$/;" f class:SatSolver -base itp.h /^ vector base;$/;" m class:ITP -beginChain Proof.cpp /^void Proof::beginChain(ClauseId start)$/;" f class:Proof -buf File.h /^ uchar* buf; \/\/ Read or write buffer.$/;" m class:File -cancelUntil Solver.cpp /^void Solver::cancelUntil(int level) {$/;" f class:Solver -cap Global.h /^ int cap;$/;" m class:vec -capacity Global.h /^ void capacity (int size) { grow(size); }$/;" f class:vec -cchar Global.h /^typedef const char cchar;$/;" t -chain itp.cpp /^void Checker::chain (const vec& cs, const vec& xs) $/;" f class:Checker -chain itp.cpp /^void MITP::chain( const vec & cs , const vec & xs )$/;" f class:MITP -chain itp.cpp /^void MultiSITP::chain (const vec& cs, const vec& xs)$/;" f class:MultiSITP -chain itp.cpp /^void PITP::chain( const vec & cs , const vec & xs )$/;" f class:PITP -chain_id Proof.h /^ vec chain_id;$/;" m class:Proof -chain_lit Proof.h /^ vec chain_lit;$/;" m class:Proof -check Solver.h /^inline void check(bool expr) { assert(expr); }$/;" f -claBumpActivity Solver.h /^ void claBumpActivity (Clause* c) { if ( (c->activity() += cla_inc) > 1e20 ) claRescaleActivity(); }$/;" f class:Solver -claDecayActivity Solver.h /^ void claDecayActivity () { cla_inc *= cla_decay; }$/;" f class:Solver -claRescaleActivity Solver.cpp /^void Solver::claRescaleActivity()$/;" f class:Solver -cla_decay Solver.h /^ double cla_decay; \/\/ INVERSE decay factor for clause activity: stores 1\/decay.$/;" m class:Solver -cla_inc Solver.h /^ double cla_inc; \/\/ Amount to bump next clause with.$/;" m class:Solver -clause Proof.h /^ vec clause;$/;" m class:Proof -clause SolverTypes.h /^ Clause* clause () const { return (Clause*)data; }$/;" f class:GClause -clause_decay Solver.h /^ double var_decay, clause_decay, random_var_freq; \/\/ (reasonable values are: 0.95, 0.999, 0.02) $/;" m struct:SearchParams -clauses Solver.h /^ vec clauses; \/\/ List of problem clauses.$/;" m class:Solver -clauses itp.h /^ vec< vec > clauses;$/;" m struct:Checker -clauses_literals Solver.h /^ int64 clauses_literals, learnts_literals, max_literals, tot_literals;$/;" m struct:SolverStats -clear Global.h /^void vec::clear(bool dealloc) {$/;" f class:vec -close File.cpp /^void File::close(void)$/;" f class:File -comp Heap.h /^ C comp;$/;" m class:Heap -compress Proof.cpp /^void Proof::compress(Proof& dst, ClauseId goal)$/;" f class:Proof -conflict Solver.h /^ vec conflict; \/\/ If problem is unsatisfiable under assumptions, this vector represent the conflict clause expressed in the assumptions.$/;" m class:Solver -conflict_id Solver.h /^ ClauseId conflict_id; \/\/ (In proof logging mode only.) ID for the clause 'conflict' (for proof traverseral). NOTE! The empty clause is always the last clause derived, but for conflicts under assumption, this is not necessarly true.$/;" m class:Solver -conflicts Solver.h /^ int64 starts, decisions, propagations, conflicts;$/;" m struct:SolverStats -copyTo Global.h /^ void copyTo(vec& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) new (©[i]) T(data[i]); }$/;" f class:vec -cpuTime Global.h /^static inline double cpuTime(void) {$/;" f -data Global.h /^ T* data;$/;" m class:vec -data SolverTypes.h /^ Lit data[1];$/;" m class:Clause -data SolverTypes.h /^ void* data;$/;" m class:GClause -decisionLevel Solver.h /^ int decisionLevel() const { return trail_lim.size(); }$/;" f class:Solver -decisions Solver.h /^ int64 starts, decisions, propagations, conflicts;$/;" m struct:SolverStats -decode64 File.h /^static inline int64 decode64(uint64 val) { return ((val & 1) == 0) ? (int64)(val >> 1) : ~(int64)(val >> 1); }$/;" f -default_params Solver.h /^ SearchParams default_params; \/\/ Restart frequency etc.$/;" m class:Solver -deleted Proof.cpp /^void Proof::deleted(ClauseId gone)$/;" f class:Proof -deleted Proof.h /^ virtual void deleted(ClauseId c){}$/;" f struct:ProofTraverser -deleted itp.cpp /^void Checker::deleted(ClauseId c) $/;" f class:Checker -deleted itp.cpp /^void MultiSITP::deleted(ClauseId c)$/;" f class:MultiSITP -done itp.cpp /^void Checker::done()$/;" f class:Checker -done itp.cpp /^void MultiSITP::done ()$/;" f class:MultiSITP -done itp.cpp /^void SITP::done()$/;" f class:SITP -drand Global.h /^static inline double drand(double& seed) {$/;" f -empty Heap.h /^ bool empty () { return heap.size() == 1; }$/;" f class:Heap -encode64 File.h /^static inline uint64 encode64(int64 val) { return (val >= 0) ? (uint64)val << 1 : (((uint64)(~val) << 1) | 1); }$/;" f -endChain Proof.cpp /^ClauseId Proof::endChain()$/;" f class:Proof -enqueue Solver.cpp /^bool Solver::enqueue(Lit p, Clause* from)$/;" f class:Solver -eof File.h /^ bool eof(void) {$/;" f class:File -expensive_ccmin Solver.h /^ int expensive_ccmin; \/\/ Controls conflict clause minimization. TRUE by default.$/;" m class:Solver -fd File.h /^ int fd; \/\/ Underlying file descriptor.$/;" m class:File -files Proof.cpp /^ vec files; \/\/ For clean-up purposed on abnormal exit.$/;" m class:TempFiles file: -flush File.h /^ void flush(void) {$/;" f class:File -fp Proof.h /^ File fp;$/;" m class:Proof -fp_name Proof.h /^ cchar* fp_name;$/;" m class:Proof -fpos Proof.h /^ int64 fpos;$/;" m class:Proof -genProofModel satTest.cpp /^genProofModel(SatSolver *s)$/;" f -getChar File.h /^ int getChar(void) {$/;" f class:File -getCharQ File.h /^ int getCharQ(void) { \/\/ Quick version with minimal overhead -- don't call this in the wrong mode!$/;" f class:File -getInt File.h /^static inline uint64 getInt (File& in) { return decode64(getUInt(in)); }$/;" f -getMode File.h /^ FileMode getMode(void) {$/;" f class:File -getUInt File.cpp /^uint64 getUInt(File& in)$/;" f -getVar satTest.cpp /^ Var getVar() const { return _var; }$/;" f class:Gate -getmin Heap.h /^ int getmin() {$/;" f class:Heap -grow Global.h /^void vec::grow(int min_cap) {$/;" f class:vec -growTo Global.h /^void vec::growTo(int size) {$/;" f class:vec -growTo Global.h /^void vec::growTo(int size, const T& pad) {$/;" f class:vec -hash SolverTypes.h /^ uint hash() const { return (uint)x; }$/;" f class:Lit -heap Heap.h /^ vec heap; \/\/ heap of ints$/;" m class:Heap -heap VarOrder.h /^ Heap heap;$/;" m class:VarOrder -heapProperty Heap.h /^ bool heapProperty() {$/;" f class:Heap -heapProperty Heap.h /^ bool heapProperty(int i) {$/;" f class:Heap -id SolverTypes.h /^ ClauseId& id () const { return *((ClauseId*)&data[size() + (int)learnt()]); }$/;" f class:Clause -id SolverTypes.h /^inline Lit id (Lit p, bool sgn) { Lit q; q.x = p.x ^ (int)sgn; return q; }$/;" f -id_counter Proof.h /^ ClauseId id_counter;$/;" m class:Proof -inHeap Heap.h /^ bool inHeap (int n) { assert(ok(n)); return indices[n] != 0; }$/;" f class:Heap -increase Heap.h /^ void increase (int n) { assert(ok(n)); assert(inHeap(n)); percolateUp(indices[n]); }$/;" f class:Heap -index SolverTypes.h /^inline int index (Lit p) { return p.x; } \/\/ A "toInt" method that guarantees small, positive integers suitable for array indexing.$/;" f -indices Heap.h /^ vec indices; \/\/ int -> index in heap$/;" m class:Heap -initCircuit satTest.cpp /^initCircuit()$/;" f -initialize sat.h /^ void initialize() {$/;" f class:SatSolver -insert Heap.h /^ void insert(int n) {$/;" f class:Heap -int64 Global.h /^typedef INT64 int64;$/;" t -int64 Global.h /^typedef long long int64;$/;" t -interpolant itp.h /^ virtual AigPtr interpolant(){return _interpolant;}$/;" f class:SITP -intp Global.h /^typedef INT_PTR intp;$/;" t -intp Global.h /^typedef __PTRDIFF_TYPE__ intp;$/;" t -irand Global.h /^static inline int irand(double& seed, int size) {$/;" f -isLit SolverTypes.h /^ bool isLit () const { return ((uintp)data & 1) == 1; }$/;" f class:GClause -itpGen itp.cpp /^AigPtr ITPMgr::itpGen()$/;" f class:ITPMgr -l_False Global.h /^const lbool l_False = toLbool(-1);$/;" v -l_True Global.h /^const lbool l_True = toLbool( 1);$/;" v -l_Undef Global.h /^const lbool l_Undef = toLbool( 0);$/;" v -last Global.h /^ T& last (void) { return data[sz-1]; }$/;" f class:vec -last Global.h /^ const T& last (void) const { return data[sz-1]; }$/;" f class:vec -last Proof.h /^ ClauseId last () { assert(id_counter != ClauseId_NULL); return id_counter - 1; }$/;" f class:Proof -lastToFirst_lt Solver.cpp /^ lastToFirst_lt(const vec& t) : trail_pos(t) {}$/;" f class:lastToFirst_lt -lastToFirst_lt Solver.cpp /^class lastToFirst_lt { \/\/ Helper class to 'analyze' -- order literals from last to first occurance in 'trail[]'.$/;" c file: -lbool Global.h /^ explicit lbool(int v) : value(v) { }$/;" f class:lbool -lbool Global.h /^ lbool() : value(0) { }$/;" f class:lbool -lbool Global.h /^ lbool(bool x) : value((int)x*2-1) { }$/;" f class:lbool -lbool Global.h /^class lbool {$/;" c -learnt SolverTypes.h /^ bool learnt () const { return size_learnt & 1; }$/;" f class:Clause -learnts Solver.h /^ vec learnts; \/\/ List of learnt clauses.$/;" m class:Solver -learnts_literals Solver.h /^ int64 clauses_literals, learnts_literals, max_literals, tot_literals;$/;" m struct:SolverStats -left Heap.h /^static inline int left (int i) { return i+i; }$/;" f -level Solver.h /^ vec level; \/\/ 'level[var]' is the decision level at which assignment was made.$/;" m class:Solver -lit SolverTypes.h /^ Lit lit () const { return toLit(((intp)data) >> 1); }$/;" f class:GClause -locked Solver.h /^ bool locked (const Clause* c) const { return reason[var((*c)[0])] == c; }$/;" f class:Solver -lseek64 File.h 13;" d -main satTest.cpp /^int main()$/;" f -max Global.h /^template static inline T max(T x, T y) { return (x > y) ? x : y; }$/;" f -max_literals Solver.h /^ int64 clauses_literals, learnts_literals, max_literals, tot_literals;$/;" m struct:SolverStats -memReadStat Global.h /^static inline int memReadStat(int field)$/;" f -memUsed Global.h /^static inline int64 memUsed() { return (int64)memReadStat(0) * (int64)getpagesize(); }$/;" f -memUsed Global.h /^static inline int64 memUsed() {$/;" f -min Global.h /^template static inline T min(T x, T y) { return (x < y) ? x : y; }$/;" f -mode File.h /^ FileMode mode; \/\/ Reading or writing.$/;" m class:File -model Solver.h /^ vec model; \/\/ If problem is satisfiable, this vector contains the model (if any).$/;" m class:Solver -moveTo Global.h /^ void moveTo(vec& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; }$/;" f class:vec -nAssigns Solver.h /^ int nAssigns() { return trail.size(); }$/;" f class:Solver -nClauses Solver.h /^ int nClauses() { return clauses.size(); }$/;" f class:Solver -nLearnts Solver.h /^ int nLearnts() { return learnts.size(); }$/;" f class:Solver -nVars Solver.h /^ int nVars () { return assigns.size(); }$/;" f class:Solver -newClause Solver.cpp /^void Solver::newClause(const vec& ps_, bool learnt, ClauseId id , bool A)$/;" f class:Solver -newVar Solver.cpp /^Var Solver::newVar() {$/;" f class:Solver -newVar VarOrder.h /^void VarOrder::newVar(void)$/;" f class:VarOrder -newVar sat.h /^ inline Var newVar() { _solver->newVar(); return ++_curVar; }$/;" f class:SatSolver -null File.h /^ bool null(void) { \/\/ TRUE if no file is opened.$/;" f class:File -ok Heap.h /^ bool ok(int n) { return n >= 0 && n < (int)indices.size(); }$/;" f class:Heap -ok Solver.h /^ bool ok; \/\/ If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used!$/;" m class:Solver -okay Solver.h /^ bool okay() { return ok; } \/\/ FALSE means solver is in an conflicting state (must never be used again!)$/;" f class:Solver -open File.cpp /^void File::open(cchar* name, cchar* mode_)$/;" f class:File -open File.cpp /^void File::open(int file_descr, FileMode m, bool own)$/;" f class:File -open Proof.cpp /^ char* open(File& fp)$/;" f class:TempFiles -open64 File.h 14;" d -operator != Global.h /^ bool operator != (const lbool& other) const { return value != other.value; }$/;" f class:lbool -operator != Global.h /^template static inline bool operator != (const T& x, const T& y) { return !(x == y); }$/;" f -operator != SolverTypes.h /^ bool operator != (GClause c) const { return data != c.data; }$/;" f class:GClause -operator () Solver.cpp /^ bool operator () (Lit p, Lit q) { return trail_pos[var(p)] > trail_pos[var(q)]; }$/;" f class:lastToFirst_lt -operator () Solver.cpp /^struct reduceDB_lt { bool operator () (Clause* x, Clause* y) { return x->size() > 2 && (y->size() == 2 || x->activity() < y->activity()); } };$/;" f struct:reduceDB_lt -operator () Sort.h /^ bool operator () (T x, T y) { return x < y; }$/;" f struct:LessThan_default -operator () VarOrder.h /^ bool operator () (Var x, Var y) { return activity[x] > activity[y]; }$/;" f struct:VarOrder_lt -operator < SolverTypes.h /^inline bool operator < (Lit p, Lit q) { return index(p) < index(q); } \/\/ '<' guarantees that p, ~p are adjacent in the ordering.$/;" f -operator <= Global.h /^template static inline bool operator <= (const T& x, const T& y) { return !(y < x); }$/;" f -operator = Global.h /^ vec& operator = (vec& other) { TEMPLATE_FAIL; }$/;" f class:vec -operator == Global.h /^ bool operator == (const lbool& other) const { return value == other.value; }$/;" f class:lbool -operator == SolverTypes.h /^ bool operator == (GClause c) const { return data == c.data; }$/;" f class:GClause -operator == SolverTypes.h /^inline bool operator == (Lit p, Lit q) { return index(p) == index(q); }$/;" f -operator > Global.h /^template static inline bool operator > (const T& x, const T& y) { return y < x; }$/;" f -operator >= Global.h /^template static inline bool operator >= (const T& x, const T& y) { return !(x < y); }$/;" f -operator T* Global.h /^ operator T* (void) { return data; } \/\/ (unsafe but convenient)$/;" f class:vec -operator [] Global.h /^ T& operator [] (int index) { return data[index]; }$/;" f class:vec -operator [] Global.h /^ const T& operator [] (int index) const { return data[index]; }$/;" f class:vec -operator [] SolverTypes.h /^ Lit operator [] (int i) const { return data[i]; }$/;" f class:Clause -operator [] SolverTypes.h /^ Lit& operator [] (int i) { return data[i]; }$/;" f class:Clause -operator [] itp.h /^ SITP & operator[]( unsigned i ){ return * (_sitp[i] ); }$/;" f class:MultiSITP -operator const T* Global.h /^ operator const T* (void) const { return data; }$/;" f class:vec -operator ~ Global.h /^ lbool operator ~ (void) const { return lbool(-value); }$/;" f class:lbool -operator ~ SolverTypes.h /^inline Lit operator ~ (Lit p) { Lit q; q.x = p.x ^ 1; return q; }$/;" f -order Solver.h /^ VarOrder order; \/\/ Keeps track of the decision variable order.$/;" m class:Solver -own_fd File.h /^ bool own_fd; \/\/ Do we own the file descriptor? If so, will close file in destructor.$/;" m class:File -parent Heap.h /^static inline int parent(int i) { return i >> 1; }$/;" f -percolateDown Heap.h /^ inline void percolateDown(int i)$/;" f class:Heap -percolateUp Heap.h /^ inline void percolateUp(int i)$/;" f class:Heap -pfGen itp.cpp /^ProofTraverser * ITPMgr::pfGen( Solver & S , StrashCkt & ckt) $/;" f class:ITPMgr -phase itp.h /^ vector< bool > phase;$/;" m struct:Checker -pop Global.h /^ void pop (void) { sz--, data[sz].~T(); }$/;" f class:vec -pos File.h /^ int pos; \/\/ Current position in buffer$/;" m class:File -printInfo sat.h /^ void printInfo() const {$/;" f class:SatSolver -printSolver sat.h /^ void printSolver() const { cout << "MiniSat ver 2.2.0"; }$/;" f class:SatSolver -progressEstimate Solver.cpp /^double Solver::progressEstimate()$/;" f class:Solver -progress_estimate Solver.h /^ double progress_estimate; \/\/ Set by 'search()'.$/;" m class:Solver -proof Solver.h /^ Proof* proof; \/\/ Set this directly after constructing 'Solver' to enable proof logging. Initialized to NULL.$/;" m class:Solver -propagate Solver.cpp /^Clause* Solver::propagate()$/;" f class:Solver -propagate_tmpbin Solver.h /^ Clause* propagate_tmpbin;$/;" m class:Solver -propagations Solver.h /^ int64 starts, decisions, propagations, conflicts;$/;" m struct:SolverStats -push Global.h /^ void push (const T& elem) { if (sz == cap) grow(sz+1); new (&data[sz]) T(elem); sz++; }$/;" f class:vec -push Global.h /^ void push (void) { if (sz == cap) grow(sz+1); new (&data[sz]) T() ; sz++; }$/;" f class:vec -putChar File.h /^ int putChar(int chr) {$/;" f class:File -putCharQ File.h /^ int putCharQ(int chr) { \/\/ Quick version with minimal overhead -- don't call this in the wrong mode!$/;" f class:File -putInt File.h /^static inline void putInt (File& out, int64 val) { putUInt(out, encode64(val)); }$/;" f -putUInt File.cpp /^void putUInt(File& out, uint64 val)$/;" f -qhead Solver.h /^ int qhead; \/\/ Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat).$/;" m class:Solver -random_seed VarOrder.h /^ double random_seed; \/\/ For the internal random number generator$/;" m class:VarOrder -random_var_freq Solver.h /^ double var_decay, clause_decay, random_var_freq; \/\/ (reasonable values are: 0.95, 0.999, 0.02) $/;" m struct:SearchParams -reason Solver.h /^ vec reason; \/\/ 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none.$/;" m class:Solver -reduceDB Solver.cpp /^void Solver::reduceDB()$/;" f class:Solver -reduceDB_lt Solver.cpp /^struct reduceDB_lt { bool operator () (Clause* x, Clause* y) { return x->size() > 2 && (y->size() == 2 || x->activity() < y->activity()); } };$/;" s file: -release Global.h /^ T* release (void) { T* ret = data; data = NULL; sz = 0; cap = 0; return ret; }$/;" f class:vec -releaseDescriptor File.h /^ int releaseDescriptor(void) { \/\/ Don't run UNIX function 'close()' on descriptor in 'File's 'close()'.$/;" f class:File -remove Solver.cpp /^void Solver::remove(Clause* c, bool just_dealloc)$/;" f class:Solver -removeWatch Solver.cpp /^void removeWatch(vec& ws, Clause* elem)$/;" f -reportf Solver.h 28;" d -reset sat.h /^ void reset() {$/;" f class:SatSolver -resetSolverData sat.h /^ void resetSolverData() { _assump.clear(); _curVar = 0; }$/;" f class:SatSolver -resolve Proof.cpp /^void Proof::resolve(ClauseId next, Lit x)$/;" f class:Proof -resolve itp.cpp /^AigPtr MITP::resolve(AigPtr p , Lit l , AigPtr q)$/;" f class:MITP -resolve itp.cpp /^AigPtr PITP::resolve(AigPtr p , Lit l , AigPtr q)$/;" f class:PITP -resolve itp.cpp /^void Checker::resolve(vec& main, vec& other, Lit l)$/;" f class:Checker -right Heap.h /^static inline int right (int i) { return i+i + 1; }$/;" f -root itp.cpp /^void Checker::root (const vec& c , bool A) $/;" f class:Checker -root itp.cpp /^void MITP::root( const vec & c , bool A)$/;" f class:MITP -root itp.cpp /^void MultiSITP::root (const vec& c , bool A)$/;" f class:MultiSITP -root itp.cpp /^void PITP::root( const vec & c , bool A)$/;" f class:PITP -root_level Solver.h /^ int root_level; \/\/ Level of first proper decision.$/;" m class:Solver -save Proof.cpp /^bool Proof::save(cchar* filename)$/;" f class:Proof -search Solver.cpp /^lbool Solver::search(int nof_conflicts, int nof_learnts, const SearchParams& params)$/;" f class:Solver -seek File.cpp /^void File::seek(int64 file_pos, int whence)$/;" f class:File -select VarOrder.h /^Var VarOrder::select(double random_var_freq)$/;" f class:VarOrder -selectionSort Sort.h /^template static inline void selectionSort(T* array, int size) {$/;" f -selectionSort Sort.h /^void selectionSort(T* array, int size, LessThan lt)$/;" f -set itp.h /^ void set( unsigned i , SITP * s ){ _sitp[i] = s ;}$/;" f class:MultiSITP -set itp.h /^ void set( bool i ){_inv = i; }$/;" f class:ITP -setBounds Heap.h /^ void setBounds (int size) { assert(size >= 0); indices.growTo(size,0); }$/;" f class:Heap -setMode File.h /^ void setMode(FileMode m) {$/;" f class:File -setVar satTest.cpp /^ void setVar(const Var& v) { _var = v; }$/;" f class:Gate -shrink Global.h /^ void shrink (int nelems) { assert(nelems <= sz); for (int i = 0; i < nelems; i++) sz--, data[sz].~T(); }$/;" f class:vec -sign SolverTypes.h /^inline bool sign (Lit p) { return p.x & 1; }$/;" f -simpDB_assigns Solver.h /^ int simpDB_assigns; \/\/ Number of top-level assignments since last execution of 'simplifyDB()'.$/;" m class:Solver -simpDB_props Solver.h /^ int64 simpDB_props; \/\/ Remaining number of propagations that must be made before next execution of 'simplifyDB()'.$/;" m class:Solver -simplify Solver.cpp /^bool Solver::simplify(Clause* c) const$/;" f class:Solver -simplifyDB Solver.cpp /^void Solver::simplifyDB()$/;" f class:Solver -size File.h /^ int size; \/\/ Size of buffer (at end of file, less than 'File_BufSize').$/;" m class:File -size Global.h /^ int size (void) const { return sz; }$/;" f class:vec -size SolverTypes.h /^ int size () const { return size_learnt >> 1; }$/;" f class:Clause -size itp.cpp /^unsigned SITP::size() $/;" f class:SITP -size_learnt SolverTypes.h /^ uint size_learnt;$/;" m class:Clause -solve Solver.cpp /^bool Solver::solve(const vec& assumps)$/;" f class:Solver -solve Solver.h /^ bool solve() { vec tmp; return solve(tmp); }$/;" f class:Solver -solve sat.h /^ bool solve() { _solver->solve(); return _solver->okay(); }$/;" f class:SatSolver -sort Sort.h /^template void sort(T* array, int size, LessThan lt) {$/;" f -sort Sort.h /^template void sort(vec& v, LessThan lt) {$/;" f -sort Sort.h /^template static inline void sort(T* array, int size) {$/;" f -sort Sort.h /^template void sort(vec& v) {$/;" f -sort Sort.h /^void sort(T* array, int size, LessThan lt, double& seed)$/;" f -sortUnique Sort.h /^template void sortUnique(vec& v, LessThan lt) {$/;" f -sortUnique Sort.h /^template static inline void sortUnique(T* array, int& size) {$/;" f -sortUnique Sort.h /^template void sortUnique(vec& v) {$/;" f -sortUnique Sort.h /^void sortUnique(T* array, int& size, LessThan lt)$/;" f -starts Solver.h /^ int64 starts, decisions, propagations, conflicts;$/;" m struct:SolverStats -stats Solver.h /^ SolverStats stats;$/;" m class:Solver -sz Global.h /^ int sz;$/;" m class:vec -tell File.cpp /^int64 File::tell(void)$/;" f class:File -temp_files Proof.cpp /^static TempFiles temp_files; \/\/ (should be singleton)$/;" v file: -toDimacs SolverTypes.h /^inline int toDimacs(Lit p) { return sign(p) ? -var(p) - 1 : var(p) + 1; }$/;" f -toInt Global.h /^ int toInt(void) const { return value; }$/;" f class:lbool -toInt Global.h /^inline int toInt (lbool l) { return l.toInt(); }$/;" f -toLbool Global.h /^inline lbool toLbool(int v) { return lbool(v); }$/;" f -toLit SolverTypes.h /^inline Lit toLit (int i) { Lit p; p.x = i; return p; } \/\/ Inverse of 'index()'.$/;" f -totGate satTest.cpp /^vector totGate;$/;" v -tot_literals Solver.h /^ int64 clauses_literals, learnts_literals, max_literals, tot_literals;$/;" m struct:SolverStats -trail Solver.h /^ vec trail; \/\/ Assignment stack; stores all assigments made in the order they were made.$/;" m class:Solver -trail_lim Solver.h /^ vec trail_lim; \/\/ Separator indices for different decision levels in 'trail[]'.$/;" m class:Solver -trail_pos Solver.cpp /^ const vec& trail_pos;$/;" m class:lastToFirst_lt file: -trail_pos Solver.h /^ vec trail_pos; \/\/ 'trail_pos[var]' is the variable's position in 'trail[]'. This supersedes 'level[]' in some sense, and 'level[]' will probably be removed in future releases.$/;" m class:Solver -trav Proof.h /^ ProofTraverser* trav;$/;" m class:Proof -traverse Proof.cpp /^void Proof::traverse(ProofTraverser& trav, ClauseId goal)$/;" f class:Proof -traverse itp.cpp /^void Checker::traverse( ProofTraverser & itp )$/;" f class:Checker -uchar Global.h /^typedef unsigned char uchar;$/;" t -uint64 Global.h /^typedef UINT64 uint64;$/;" t -uint64 Global.h /^typedef unsigned long long uint64;$/;" t -uintp Global.h /^typedef UINT_PTR uintp;$/;" t -uintp Global.h /^typedef unsigned __PTRDIFF_TYPE__ uintp;$/;" t -undo VarOrder.h /^void VarOrder::undo(Var x)$/;" f class:VarOrder -unit_id Solver.h /^ vec unit_id; \/\/ 'unit_id[var]' is the clause ID for the unit literal 'var' or '~var' (if set at toplevel).$/;" m class:Solver -unsign SolverTypes.h /^inline Lit unsign(Lit p) { Lit q; q.x = p.x & ~1; return q; }$/;" f -update VarOrder.h /^void VarOrder::update(Var x)$/;" f class:VarOrder -value Global.h /^ int value;$/;" m class:lbool -value Solver.h /^ lbool value(Lit p) const { return sign(p) ? ~toLbool(assigns[var(p)]) : toLbool(assigns[var(p)]); }$/;" f class:Solver -value Solver.h /^ lbool value(Var x) const { return toLbool(assigns[x]); }$/;" f class:Solver -var SolverTypes.h /^inline int var (Lit p) { return p.x >> 1; }$/;" f -varBumpActivity Solver.h /^ void varBumpActivity(Lit p) {$/;" f class:Solver -varDecayActivity Solver.h /^ void varDecayActivity () { if (var_decay >= 0) var_inc *= var_decay; }$/;" f class:Solver -varRescaleActivity Solver.cpp /^void Solver::varRescaleActivity()$/;" f class:Solver -var_Undef SolverTypes.h 37;" d -var_decay Solver.h /^ double var_decay; \/\/ INVERSE decay factor for variable activity: stores 1\/decay. Use negative value for static variable order.$/;" m class:Solver -var_decay Solver.h /^ double var_decay, clause_decay, random_var_freq; \/\/ (reasonable values are: 0.95, 0.999, 0.02) $/;" m struct:SearchParams -var_inc Solver.h /^ double var_inc; \/\/ Amount to bump next variable with.$/;" m class:Solver -vcs itp.h /^ vec< vec< ClauseId > > vcs;$/;" m struct:Checker -vec Global.h /^ vec (vec& other) { TEMPLATE_FAIL; }$/;" f class:vec -vec Global.h /^ vec(T* array, int size) : data(array), sz(size), cap(size) { } \/\/ (takes ownership of array -- will be deallocated with 'xfree()')$/;" f class:vec -vec Global.h /^ vec(int size) : data(NULL) , sz(0) , cap(0) { growTo(size); }$/;" f class:vec -vec Global.h /^ vec(int size, const T& pad) : data(NULL) , sz(0) , cap(0) { growTo(size, pad); }$/;" f class:vec -vec Global.h /^ vec(void) : data(NULL) , sz(0) , cap(0) { }$/;" f class:vec -vec Global.h /^class vec {$/;" c -verbosity Solver.h /^ int verbosity; \/\/ Verbosity level. 0=silent, 1=some progress report, 2=everything$/;" m class:Solver -vxs itp.h /^ vec< vec > vxs;$/;" m struct:Checker -watches Solver.h /^ vec > watches; \/\/ 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true).$/;" m class:Solver -x SolverTypes.h /^ int x;$/;" m class:Lit -xfree Global.h /^template static inline void xfree(T *ptr) {$/;" f -xmalloc Global.h /^template static inline T* xmalloc(size_t size) {$/;" f -xrealloc Global.h /^template static inline T* xrealloc(T* ptr, size_t size) {$/;" f -~AigCal itp.h /^ virtual ~AigCal(){};$/;" f class:AigCal -~File File.h /^ ~File(void) {$/;" f class:File -~Gate satTest.cpp /^ ~Gate() {}$/;" f class:Gate -~ITPMgr itp.cpp /^ITPMgr::~ITPMgr()$/;" f class:ITPMgr -~MITP itp.h /^ virtual ~MITP(){}$/;" f class:MITP -~MultiSITP itp.cpp /^MultiSITP::~MultiSITP()$/;" f class:MultiSITP -~PITP itp.h /^ virtual ~PITP(){}$/;" f class:PITP -~ProofTraverser Proof.h /^ virtual ~ProofTraverser(){}$/;" f struct:ProofTraverser -~SITP itp.h /^ virtual ~SITP(){}$/;" f class:SITP -~SMITP itp.h /^ virtual ~SMITP(){}$/;" f class:SMITP -~SPITP itp.h /^ virtual ~SPITP(){}$/;" f class:SPITP -~SatSolver sat.h /^ ~SatSolver() { }$/;" f class:SatSolver -~Solver Solver.h /^ ~Solver() {$/;" f class:Solver -~TempFiles Proof.cpp /^ ~TempFiles()$/;" f class:TempFiles -~vec Global.h /^ ~vec(void) { clear(true); }$/;" f class:vec diff --git a/src/sim/.depend.mak b/src/sim/.depend.mak index e69de29b..4299e5d4 100644 --- a/src/sim/.depend.mak +++ b/src/sim/.depend.mak @@ -0,0 +1,34 @@ +gvSimCmd.o: gvSimCmd.cpp gvSimCmd.h ../../include/gvCmdMgr.h \ + ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ + ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/base/main/main.h ../../include/base/abc/abc.h \ + ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ + ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ + ../../include/base/main/mainInt.h ../../include/base/main/main.h \ + ../../include/misc/tim/tim.h ../../include/map/if/if.h \ + ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ + ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ + ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ + ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ + ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ + ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ + ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ + ../../include/gvModMgr.h ../../include/gvCmdMgr.h ../../include/gvMsg.h \ + ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h \ + ../../include/gvNtk.h ../../include/gvAbcMgr.h \ + ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ + /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ + /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ + ../../include/kernel/log.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h \ + ../../include/kernel/utils.h ../../include/kernel/yosys.h diff --git a/src/vrf/.depend.mak b/src/vrf/.depend.mak index e69de29b..ed12a040 100644 --- a/src/vrf/.depend.mak +++ b/src/vrf/.depend.mak @@ -0,0 +1,29 @@ +gvVrfCmd.o: gvVrfCmd.cpp gvVrfCmd.h ../../include/gvCmdMgr.h \ + ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ + ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ + ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ + ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ + ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ + ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ + ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ + ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ + ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ + ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ + ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ + ../../include/base/main/main.h ../../include/base/abc/abc.h \ + ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ + ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ + ../../include/base/main/mainInt.h ../../include/base/main/main.h \ + ../../include/misc/tim/tim.h ../../include/map/if/if.h \ + ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ + ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ + ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ + ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ + ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ + ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ + ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ + ../../include/gvMsg.h ../../include/gvUsage.h ../../include/gvMsg.h \ + ../../include/gvIntType.h ../../include/gvModMgr.h \ + ../../include/gvCmdMgr.h ../../include/util.h ../../include/rnGen.h \ + ../../include/myUsage.h From 326d35c5c0db4ca0c69bf6bcb7185886de9be182 Mon Sep 17 00:00:00 2001 From: hchchiu Date: Wed, 29 Nov 2023 05:06:26 +0800 Subject: [PATCH 015/307] Update makefile for gvsat --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 071faa74..1d00e2e1 100755 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -SRCPKGS = util cmd mod abc yosys bdd itp ntk cir sim vrf ext prove -LIBPKGS = util cmd mod abc yosys bdd itp ntk cir sim vrf prove +SRCPKGS = util cmd mod abc yosys bdd itp ntk cir sim vrf ext prove gvsat +LIBPKGS = util cmd mod abc yosys bdd itp ntk cir sim vrf prove gvsat MAIN = main From 2615f3f0ec7bf51eae4df5d298afcd5545045e13 Mon Sep 17 00:00:00 2001 From: hchchiu Date: Wed, 29 Nov 2023 05:08:27 +0800 Subject: [PATCH 016/307] Update clang-format config file --- .clang-format | 96 +++++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/.clang-format b/.clang-format index 7014a740..7972aae4 100644 --- a/.clang-format +++ b/.clang-format @@ -1,44 +1,58 @@ ---- -IndentWidth: 4 ---- -# Specify Language -Language: Cpp - -# ___ Short statement ___ -# "if (a) return"; can be put on a single line. -AllowShortIfStatementsOnASingleLine: AllIfsAndElse - -# If "true", "while (true) continue"; can be put on a single line. -AllowShortLoopsOnASingleLine: true - -# int f() { return 0; } can be put on a single line. -AllowShortFunctionsOnASingleLine: Inline - -# ___ Align ___ -# Horizontally aligns arguments after an open bracket. -AlignAfterOpenBracket: Align +#--- +#IndentWidth: 4 +#--- +## Specify Language +#Language: Cpp +# +## ___ Short statement ___ +## "if (a) return"; can be put on a single line. +#AllowShortIfStatementsOnASingleLine: AllIfsAndElse +# +## If "true", "while (true) continue"; can be put on a single line. +#AllowShortLoopsOnASingleLine: true +# +## int f() { return 0; } can be put on a single line. +#AllowShortFunctionsOnASingleLine: Inline +# +## ___ Align ___ +## Horizontally aligns arguments after an open bracket. +#AlignAfterOpenBracket: Align +# +## Align consecutive declarations +#AlignConsecutiveDeclarations: +# Enabled: true +# AcrossComments: true +# Consecutive: true +# +## Align consecutive assignments. +#AlignConsecutiveAssignments: Consecutive +# +## The return type of the function on its own line. +#AlwaysBreakAfterDefinitionReturnType: TopLevel +# +## The column limit. +#ColumnLimit: 80 +# +## Extern and Class indent setting +#BreakBeforeBraces: Custom +#BraceWrapping: +# AfterExternBlock: true +# AfterClass: true +# AfterEnum: true +# +#IndentAccessModifiers: true +#PointerAlignment: Left + + +BasedOnStyle: Google -# Align consecutive declarations -AlignConsecutiveDeclarations: - Enabled: true - AcrossComments: true - Consecutive: true - -# Align consecutive assignments. -AlignConsecutiveAssignments: Consecutive - -# The return type of the function on its own line. -AlwaysBreakAfterDefinitionReturnType: TopLevel - -# The column limit. -ColumnLimit: 80 +IndentWidth: 4 +# no column limit +ColumnLimit: 0 -# Extern and Class indent setting -BreakBeforeBraces: Custom -BraceWrapping: - AfterExternBlock: true - AfterClass: true - AfterEnum: true +AlignTrailingComments: true +AlignAfterOpenBracket: true +IndentRequires: false -IndentAccessModifiers: true -PointerAlignment: Left +# puts public, private, on the same column with class definition +AccessModifierOffset: -4 From aceb27cdd084e6e6806ef735615f18d99ec92dcf Mon Sep 17 00:00:00 2001 From: hchchiu Date: Wed, 29 Nov 2023 05:11:00 +0800 Subject: [PATCH 017/307] Update abc version to commit 6ca7eab --- engine/abc.script | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/abc.script b/engine/abc.script index 5c10f68f..9aad96d6 100755 --- a/engine/abc.script +++ b/engine/abc.script @@ -2,8 +2,8 @@ git clone https://github.com/berkeley-abc/abc cd abc -# switch to stable commit(581c58b) -git reset 581c58b +# switch to stable commit(6ca7eab) +git reset 6ca7eab # make abc make -j12 From 2cb0d6ffb5fefee3dfdcb90545b3cccec1fcd351 Mon Sep 17 00:00:00 2001 From: hchchiu Date: Wed, 6 Dec 2023 03:33:07 +0800 Subject: [PATCH 018/307] Organize the code for abc interface --- .clang-format | 28 +- Makefile | 4 +- src/abc/gvAbcCmd.cpp | 19 +- src/abc/gvAbcMgr.cpp | 169 ++++++++- src/abc/gvAbcMgr.h | 71 ++-- src/bdd/bddCmd.cpp | 77 ++--- src/cir/cirAig.cpp | 259 ++++++-------- src/cir/cirCmd.cpp | 22 +- src/cmd/gvCmdComm.cpp | 102 +++--- src/cmd/gvCmdMgr.cpp | 38 +- src/gvsat/gvSat.cpp | 6 +- src/gvsat/gvSat.h | 4 +- src/itp/gvSatCmd.cpp | 8 +- src/itp/gvSatMgr.cpp | 50 +-- src/itp/gvSatMgr.h | 23 +- src/main/main.cpp | 3 +- src/mod/gvModCmd.cpp | 77 ++--- src/mod/gvModCmd.h | 1 - src/ntk/.depend.mak | 105 ------ src/ntk/.extheader.mak | 7 - src/ntk/.map.txt | 0 src/ntk/.mapGold.txt | 23 -- src/ntk/.mapOld.txt | 23 -- src/ntk/Makefile | 7 - src/ntk/abcc | 1 - src/ntk/gvNtk.cpp | 583 ------------------------------- src/ntk/gvNtk.h | 265 -------------- src/ntk/gvNtkBdd.cpp | 180 ---------- src/ntk/gvNtkCmd.cpp | 728 --------------------------------------- src/ntk/gvNtkCmd.h | 16 - src/prove/proveBdd.cpp | 3 +- src/prove/proveCmd.cpp | 56 ++- src/sim/gvSimCmd.cpp | 73 ++-- src/util/gvUsage.h | 265 +++++++------- src/vrf/gvVrfCmd.cpp | 239 +++++++------ src/yosys/gvYosysCmd.cpp | 11 +- src/yosys/gvYosysMgr.cpp | 12 +- src/yosys/gvYosysMgr.h | 2 +- 38 files changed, 868 insertions(+), 2692 deletions(-) delete mode 100644 src/ntk/.depend.mak delete mode 100644 src/ntk/.extheader.mak delete mode 100644 src/ntk/.map.txt delete mode 100644 src/ntk/.mapGold.txt delete mode 100644 src/ntk/.mapOld.txt delete mode 100644 src/ntk/Makefile delete mode 120000 src/ntk/abcc delete mode 100644 src/ntk/gvNtk.cpp delete mode 100644 src/ntk/gvNtk.h delete mode 100644 src/ntk/gvNtkBdd.cpp delete mode 100644 src/ntk/gvNtkCmd.cpp delete mode 100644 src/ntk/gvNtkCmd.h diff --git a/.clang-format b/.clang-format index 7972aae4..ae89c096 100644 --- a/.clang-format +++ b/.clang-format @@ -5,14 +5,14 @@ #Language: Cpp # ## ___ Short statement ___ -## "if (a) return"; can be put on a single line. -#AllowShortIfStatementsOnASingleLine: AllIfsAndElse +# "if (a) return"; can be put on a single line. +AllowShortIfStatementsOnASingleLine: AllIfsAndElse # ## If "true", "while (true) continue"; can be put on a single line. #AllowShortLoopsOnASingleLine: true # ## int f() { return 0; } can be put on a single line. -#AllowShortFunctionsOnASingleLine: Inline +# AllowShortFunctionsOnASingleLine: Inline # ## ___ Align ___ ## Horizontally aligns arguments after an open bracket. @@ -24,8 +24,8 @@ # AcrossComments: true # Consecutive: true # -## Align consecutive assignments. -#AlignConsecutiveAssignments: Consecutive +# Align consecutive assignments. +AlignConsecutiveAssignments: Consecutive # ## The return type of the function on its own line. #AlwaysBreakAfterDefinitionReturnType: TopLevel @@ -33,12 +33,12 @@ ## The column limit. #ColumnLimit: 80 # -## Extern and Class indent setting -#BreakBeforeBraces: Custom -#BraceWrapping: -# AfterExternBlock: true -# AfterClass: true -# AfterEnum: true +# Extern and Class indent setting +BreakBeforeBraces: Custom +BraceWrapping: + AfterExternBlock: true + # AfterClass: true + # AfterEnum: true # #IndentAccessModifiers: true #PointerAlignment: Left @@ -56,3 +56,9 @@ IndentRequires: false # puts public, private, on the same column with class definition AccessModifierOffset: -4 + +AlignConsecutiveShortCaseStatements: + Enabled: true +# Bin Pack +# BinPackArguments: true +# BinPackParameters: true \ No newline at end of file diff --git a/Makefile b/Makefile index 1d00e2e1..533e04a0 100755 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -SRCPKGS = util cmd mod abc yosys bdd itp ntk cir sim vrf ext prove gvsat -LIBPKGS = util cmd mod abc yosys bdd itp ntk cir sim vrf prove gvsat +SRCPKGS = util cmd mod abc yosys bdd itp cir sim vrf ext prove gvsat +LIBPKGS = util cmd mod abc yosys bdd itp cir sim vrf prove gvsat MAIN = main diff --git a/src/abc/gvAbcCmd.cpp b/src/abc/gvAbcCmd.cpp index e57ede8e..8dcc3349 100644 --- a/src/abc/gvAbcCmd.cpp +++ b/src/abc/gvAbcCmd.cpp @@ -12,7 +12,6 @@ #include "gvMsg.h" #include "util.h" - bool initAbcCmd() { if (abcMgr) delete abcMgr; abcMgr = new AbcMgr; @@ -46,12 +45,12 @@ GVABCReadCmd::exec(const string& option) { } void GVABCReadCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: ABCRead " << endl; + cout << "Usage: ABCRead " << endl; } void GVABCReadCmd::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "ABCRead: " - << "Read netlist by ABC." << endl; + cout << setw(20) << left << "ABCRead: " + << "Read netlist by ABC." << endl; } //---------------------------------------------------------------------- @@ -78,12 +77,12 @@ GVABCPrintCmd::exec(const string& option) { } void GVABCPrintCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: ABCPrint " << endl; + cout << "Usage: ABCPrint " << endl; } void GVABCPrintCmd::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "ABCPrint: " - << "Print netlist information." << endl; + cout << setw(20) << left << "ABCPrint: " + << "Print netlist information." << endl; } //---------------------------------------------------------------------- @@ -111,12 +110,12 @@ GVABCOriginalCmd::exec(const string& option) { } void GVABCOriginalCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: ABCCMD " << endl; + cout << "Usage: ABCCMD " << endl; } void GVABCOriginalCmd::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "ABCCMD: " - << "Directly call ABC's command." << endl; + cout << setw(20) << left << "ABCCMD: " + << "Directly call ABC's command." << endl; } #endif \ No newline at end of file diff --git a/src/abc/gvAbcMgr.cpp b/src/abc/gvAbcMgr.cpp index 983ad0c2..8d8efd91 100644 --- a/src/abc/gvAbcMgr.cpp +++ b/src/abc/gvAbcMgr.cpp @@ -1,27 +1,35 @@ #include "gvAbcMgr.h" + +#include +#include +#include +#include +#include + #include "base/abc/abc.h" #include "bdd/cudd/cudd.h" +#include "cirMgr.h" +#include "cirGate.h" #include "gvAbcNtk.h" #include "sat/cnf/cnf.h" -#include -#include -#include +#include "util.h" AbcMgr* abcMgr; -void -AbcMgr::init() { +AbcMgr::AbcMgr() : pGia(NULL) { + init(); +} + +void AbcMgr::init() { Abc_Start(); pAbc = Abc_FrameGetGlobalFrame(); } -void -AbcMgr::reset() { +void AbcMgr::reset() { delete pAbc; } -void -AbcMgr::abcReadDesign(string& fileName) { +void AbcMgr::abcReadDesign(string& fileName) { char pFileName[128]; strcpy(pFileName, fileName.c_str()); char Command[1000]; @@ -29,3 +37,146 @@ AbcMgr::abcReadDesign(string& fileName) { Cmd_CommandExecute(pAbc, Command); pNtkMgr = new abcNtkMgr(pAbc->pNtkCur); } + +void AbcMgr::readVerilog(const ABCParam& opt) { + char* pFileName = opt.pFileName; + char* pTopModule = opt.pTopModule; + char* pDefines = opt.pDefines; + int fBlast = opt.fBlast; + int fInvert = opt.fInvert; + int fTechMap = opt.fTechMap; + int fSkipStrash = opt.fSkipStrash; + int fCollapse = opt.fCollapse; + int fVerbose = opt.fVerbose; + pGia = Wln_BlastSystemVerilog(pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fVerbose); +} + +void AbcMgr::readAig(const ABCParam& opt) { + char* pFileName = opt.pFileName; + int fSkipStrash = opt.fSkipStrash; + int fGiaSimple = opt.fGiaSimple; + int fCheck = opt.fCheck; + pGia = Gia_AigerRead(pFileName, fGiaSimple, fSkipStrash, fCheck); +} + +static string gateName(const string& name, const int& bit) { + return name + "[" + to_string(bit) + "]"; +} + +void AbcMgr::buildAigName(map& id2Name) { + ifstream mapFile; + string buffer; + string type; + string name; + int idx = 0, bit = 0; + + mapFile.open(".map.txt"); + assert(mapFile.is_open()); + while (mapFile) { + if (!(mapFile >> type)) break; + mapFile >> buffer; // idx + myStr2Int(buffer, idx); + mapFile >> buffer; // bit + myStr2Int(buffer, bit); + mapFile >> buffer; // name + name = buffer; + if (type == "input") id2Name[Gia_ObjId(pGia, Gia_ManPi(pGia, idx))] = gateName(name, bit); + else if (type == "output") id2Name[Gia_ObjId(pGia, Gia_ManPo(pGia, idx))] = gateName(name, bit); + else if (type == "latch") { + Gia_Obj_t* ro = Gia_ObjRiToRo(pGia, Gia_ManRi(pGia, idx)); + Gia_Obj_t* ri = Gia_ManRi(pGia, idx); + + id2Name[Gia_ObjId(pGia, ro)] = gateName(name, bit); + id2Name[Gia_ObjId(pGia, ri)] = gateName(name, bit) + "_ns"; + } + } +} + +void AbcMgr::travPreprocess() { + // increment the global travel id for circuit traversing usage + Gia_ManIncrementTravId(pGia); + + // since we don't want to traverse the constant node, set the TravId of the + // constant node to be as the global one + Gia_ObjSetTravIdCurrent(pGia, Gia_ManConst0(pGia)); +} + +void AbcMgr::travAllObj(vector& piList, vector& poList, vector& roList, vector& riList, + vector& totGateList, map& id2Name, const CirFileType& fileType) { + Gia_Obj_t *pObj, *pObjRi, *pObjRo; // the obj element of gia + size_t i, iPi = 0, iPpi = 0, iPo = 0, iRi = 0, iRo = 0; + map PPI2RO; + + Gia_ManForEachObj(pGia, pObj, i) { + if (Gia_ObjIsPi(pGia, pObj)) { + int gateId = Gia_ObjId(pGia, pObj); + if (gateId <= piList.size()) { + CirPiGate* gate = new CirPiGate(Gia_ObjId(pGia, pObj), 0); + piList[iPi++] = gate; + totGateList[gateId] = gate; + } else { + CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); + roList[iRo++] = gate; + totGateList[gateId] = gate; + } + } else if (Gia_ObjIsPo(pGia, pObj)) { + string poName = ""; + CirPoGate* gate = new CirPoGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); + poName = (id2Name.count(gate->getGid())) ? id2Name[gate->getGid()] : to_string(Gia_ObjId(pGia, pObj)); + char* n = new char[poName.size() + 1]; + strcpy(n, poName.c_str()); + gate->setName(n); + gate->setIn0(cirMgr->getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); + poList[iPo++] = gate; + totGateList[Gia_ObjId(pGia, pObj)] = gate; + } else if (Gia_ObjIsAnd(pObj)) { + CirAigGate* gate = new CirAigGate(Gia_ObjId(pGia, pObj), 0); + int fanin0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + int fanin1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); + if (PPI2RO.count(fanin0)) fanin0 = PPI2RO[fanin0]; + if (PPI2RO.count(fanin1)) fanin1 = PPI2RO[fanin1]; + gate->setIn0(cirMgr->getGate(fanin0), Gia_ObjFaninC0(pObj)); + gate->setIn1(cirMgr->getGate(fanin1), Gia_ObjFaninC1(pObj)); + totGateList[Gia_ObjId(pGia, pObj)] = gate; + } else if (Gia_ObjIsRo(pGia, pObj)) { + int gateId = Gia_ObjId(pGia, pObj); + if (fileType == VERILOG) { + PPI2RO[gateId] = 0; + if (iPpi < iRo) PPI2RO[gateId] = roList[iPpi]->getGid(); + iPpi++; + } else if (fileType == AIGER) { + CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); + roList[iRo++] = gate; + totGateList[gateId] = gate; + } + } else if (Gia_ObjIsRi(pGia, pObj)) { + CirRiGate* gate = new CirRiGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); + string str = to_string(Gia_ObjId(pGia, pObj)); + str = str + "_ns"; + char* n = new char[str.size() + 1]; + strcpy(n, str.c_str()); + gate->setName(n); + gate->setIn0(cirMgr->getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); + riList[iRi++] = gate; + totGateList[Gia_ObjId(pGia, pObj)] = gate; + } else if (Gia_ObjIsConst0(pObj)) { + totGateList[0] = CirMgr::_const0; + } else { + cout << "not defined gate type" << endl; + assert(true); + } + } + + Gia_ManForEachRiRo(pGia, pObjRi, pObjRo, i) { + if (i == cirMgr->getNumLATCHs()) break; + + int riGid = Gia_ObjId(pGia, pObjRi), roGid = 0; + // int roGid = PPI2RO[Gia_ObjId(pGia,pObjRo)]; + // int roGid = Gia_ObjId(pGia,pObjRo); + if (fileType == VERILOG) roGid = PPI2RO[Gia_ObjId(pGia, pObjRo)]; + else if (fileType == AIGER) roGid = Gia_ObjId(pGia, pObjRo); + CirGate* riGate = cirMgr->getGate(riGid); + CirRoGate* roGate = static_cast(cirMgr->getGate(roGid)); + roGate->setIn0(riGate, false); + } +} \ No newline at end of file diff --git a/src/abc/gvAbcMgr.h b/src/abc/gvAbcMgr.h index aad2a128..ffbf0037 100644 --- a/src/abc/gvAbcMgr.h +++ b/src/abc/gvAbcMgr.h @@ -1,48 +1,73 @@ #ifndef GV_ABC_MGR #define GV_ABC_MGR +#include +#include +#include + #include "base/abc/abc.h" #include "base/main/main.h" #include "base/main/mainInt.h" +#include "cirGate.h" #include "gvAbcNtk.h" -#include using namespace std; class AbcMgr; -extern AbcMgr* abcMgr; +extern AbcMgr* abcMgr; typedef struct Abc_Frame_t_ Abc_Frame_t; -typedef struct Abc_Ntk_t_ Abc_Ntk_t; -typedef struct Abc_Obj_t_ Abc_Obj_t; +typedef struct Abc_Ntk_t_ Abc_Ntk_t; +typedef struct Abc_Obj_t_ Abc_Obj_t; extern "C" { - void Abc_Start(); - void Abc_Stop(); + void Abc_Start(); + void Abc_Stop(); + int Cmd_CommandExecute(Abc_Frame_t* pAbc, const char* sCommand); Abc_Frame_t* Abc_FrameGetGlobalFrame(); - int Cmd_CommandExecute(Abc_Frame_t* pAbc, const char* sCommand); - Abc_Ntk_t* Abc_FrameReadNtk(Abc_Frame_t* p); - Gia_Man_t* Wln_BlastSystemVerilog(char* pFileName, char* pTopModule, char* pDefines, int fSkipStrash, int fInvert, int fTechMap, int fVerbose); + Abc_Ntk_t* Abc_FrameReadNtk(Abc_Frame_t* p); + Gia_Man_t* Wln_BlastSystemVerilog(char* pFileName, char* pTopModule, char* pDefines, int fSkipStrash, int fInvert, int fTechMap, int fVerbose); } +struct ABCParam { + ABCParam() : fBlast(0), fInvert(0), fTechMap(0), fSkipStrash(0), fCollapse(0), fVerbose(0), fGiaSimple(0), fCheck(0), pTopModule(NULL), pDefines(NULL) { + pFileName = new char[100]; + }; + char* pFileName; + char* pTopModule; + char* pDefines; + int fBlast; + int fInvert; + int fTechMap; + int fSkipStrash; + int fCollapse; + int fVerbose; + int fGiaSimple; + int fCheck; +}; -class AbcMgr -{ - public: - AbcMgr() { init(); } - ~AbcMgr() { reset(); } - - void init(); - void reset(); +class AbcMgr { +public: + AbcMgr(); + ~AbcMgr() { reset(); } - void abcReadDesign(string&); + void init(); + void reset(); + void abcReadDesign(string&); + void readAig(const ABCParam&); + void readVerilog(const ABCParam&); + void buildAigName(map&); + void travPreprocess(); + void travAllObj(vector& piList, vector& poList, vector& roList, vector& riList, + vector& totGateList, map& id2Name, const CirFileType& fileType); - Abc_Frame_t* get_Abc_Frame_t() { return pAbc; } - abcNtkMgr* get_abcNtkMgr() { return pNtkMgr; } + Abc_Frame_t* get_Abc_Frame_t() { return pAbc; } + abcNtkMgr* get_abcNtkMgr() { return pNtkMgr; } + Gia_Man_t* pGia; - private: - Abc_Frame_t* pAbc; - abcNtkMgr* pNtkMgr; +private: + Abc_Frame_t* pAbc; + abcNtkMgr* pNtkMgr; }; #endif diff --git a/src/bdd/bddCmd.cpp b/src/bdd/bddCmd.cpp index c62a6c5a..cf11e3fc 100644 --- a/src/bdd/bddCmd.cpp +++ b/src/bdd/bddCmd.cpp @@ -18,7 +18,7 @@ #include "cirGate.h" #include "cirMgr.h" #include "gvMsg.h" -#include "gvNtk.h" +// #include "gvNtk.h" #include "util.h" using namespace std; @@ -83,7 +83,7 @@ BResetCmd::exec(const string& option) { } void BResetCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) + cout << "Usage: BRESET <(size_t nSupports)> <(size_t hashSize)> " << "<(size_t cacheSize)>" << endl; } @@ -123,8 +123,8 @@ BSetVarCmd::exec(const string& option) { } void BSetVarCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BSETVar <(size_t level)> <(string varName)>" - << endl; + cout << "Usage: BSETVar <(size_t level)> <(string varName)>" + << endl; } void BSetVarCmd::help() const { @@ -158,8 +158,8 @@ BInvCmd::exec(const string& option) { } void BInvCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BINV <(string varName)> <(string bddName)>" - << endl; + cout << "Usage: BINV <(string varName)> <(string bddName)>" + << endl; } void BInvCmd::help() const { @@ -197,8 +197,8 @@ BAndCmd::exec(const string& option) { } void BAndCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BAND <(string varName)> <(string bddName)>..." - << endl; + cout << "Usage: BAND <(string varName)> <(string bddName)>..." + << endl; } void BAndCmd::help() const { @@ -236,8 +236,8 @@ BOrCmd::exec(const string& option) { } void BOrCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BOR <(string varName)> <(string bddName)>..." - << endl; + cout << "Usage: BOR <(string varName)> <(string bddName)>..." + << endl; } void BOrCmd::help() const { @@ -276,8 +276,8 @@ BNandCmd::exec(const string& option) { } void BNandCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BNAND <(string varName)> <(string bddName)>..." - << endl; + cout << "Usage: BNAND <(string varName)> <(string bddName)>..." + << endl; } void BNandCmd::help() const { @@ -316,8 +316,8 @@ BNorCmd::exec(const string& option) { } void BNorCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BNOR <(string varName)> <(string bddName)>..." - << endl; + cout << "Usage: BNOR <(string varName)> <(string bddName)>..." + << endl; } void BNorCmd::help() const { @@ -355,8 +355,8 @@ BXorCmd::exec(const string& option) { } void BXorCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BXOR <(string varName)> <(string bddName)>..." - << endl; + cout << "Usage: BXOR <(string varName)> <(string bddName)>..." + << endl; } void BXorCmd::help() const { @@ -395,8 +395,8 @@ BXnorCmd::exec(const string& option) { } void BXnorCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BXNOR <(string varName)> <(string bddName)>..." - << endl; + cout << "Usage: BXNOR <(string varName)> <(string bddName)>..." + << endl; } void BXnorCmd::help() const { @@ -435,8 +435,8 @@ BCofactorCmd::exec(const string& option) { } void BCofactorCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BCOFactor <-Positive | -Negative> <(string " - "varName)> <(string bddName)>\n"; + cout << "Usage: BCOFactor <-Positive | -Negative> <(string " + "varName)> <(string bddName)>\n"; } void BCofactorCmd::help() const { @@ -473,8 +473,8 @@ BExistCmd::exec(const string& option) { } void BExistCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BEXist <(size_t level)> <(string varName)> " - "<(string bddName)>\n"; + cout << "Usage: BEXist <(size_t level)> <(string varName)> " + "<(string bddName)>\n"; } void BExistCmd::help() const { @@ -522,8 +522,8 @@ BCompareCmd::exec(const string& option) { } void BCompareCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BCOMpare <(string bddName)> <(string bddName)>" - << endl; + cout << "Usage: BCOMpare <(string bddName)> <(string bddName)>" + << endl; } void BCompareCmd::help() const { @@ -563,7 +563,7 @@ BSimulateCmd::exec(const string& option) { } void BSimulateCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) + cout << "Usage: BSIMulate <(string bddName)> <(bit_string inputPattern)>" << endl; } @@ -596,7 +596,7 @@ BReportCmd::exec(const string& option) { return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, options[i - 1]); fileName = options[i]; - doFile = true; + doFile = true; } else if (myStrNCmp("-ADDRess", options[i], 5) == 0) { if (doAddr) return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[i]); @@ -630,14 +630,14 @@ BReportCmd::exec(const string& option) { cout << bnode << endl; // always set to false afterwards - BddNodeV::_debugBddAddr = false; + BddNodeV::_debugBddAddr = false; BddNodeV::_debugRefCount = false; return GV_CMD_EXEC_DONE; } void BReportCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) + cout << "Usage: BREPort <(string bddName)> [-ADDRess] [-REFcount]\n " << " [-File <(string fileName)>]" << endl; } @@ -672,7 +672,7 @@ BDrawCmd::exec(const string& option) { } void BDrawCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BDRAW <(string bddName)> <(string fileName)>" << endl; + cout << "Usage: BDRAW <(string bddName)> <(string fileName)>" << endl; } void BDrawCmd::help() const { @@ -685,7 +685,6 @@ void BDrawCmd::help() const { //---------------------------------------------------------------------- GVCmdExecStatus BSetOrderCmd::exec(const string& option) { - // if(!valid()) return GV_CMD_EXEC_ERROR; if (setBddOrder) { gvMsg(GV_MSG_WAR) << "BDD Variable Order Has Been Set !!" << endl; return GV_CMD_EXEC_ERROR; @@ -698,7 +697,7 @@ BSetOrderCmd::exec(const string& option) { return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[1]); } string token = options[0]; - bool file = false; + bool file = false; if (myStrNCmp("-File", token, 2) == 0) file = true; else if (myStrNCmp("-RFile", token, 3) == 0) @@ -706,18 +705,16 @@ BSetOrderCmd::exec(const string& option) { else return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); bddMgrV->restart(); - // V3NtkHandler* const handler = v3Handler.getCurHandler(); - // setBddOrder = gvNtkMgr->setBddOrder(file); setBddOrder = cirMgr->setBddOrder(file); if (!setBddOrder) gvMsg(GV_MSG_ERR) << "Set BDD Variable Order Failed !!" << endl; else - gvMsg(GV_MSG_IFO) << "Set BDD Variable Order Succeed !!" << endl; + cout << "Set BDD Variable Order Succeed !!" << endl; return GV_CMD_EXEC_DONE; } void BSetOrderCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BSETOrder < -File | -RFile >" << endl; + cout << "Usage: BSETOrder < -File | -RFile >" << endl; } void BSetOrderCmd::help() const { cout << setw(20) << left << "BSETOrder: " @@ -756,28 +753,22 @@ BConstructCmd::exec(const string& option) { return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, options[0]); int num = 0; - GVNetId netId; CirGate* gate; if (!myStr2Int(options[1], num) || (num < 0)) return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); if (isGate) { - // if ((unsigned)num >= gvNtkMgr->getNetSize()) { if ((unsigned)num >= cirMgr->getNumTots()) { gvMsg(GV_MSG_ERR) << "Gate with Id " << num << " does NOT Exist in Current Cir !!" << endl; return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } - // netId = GVNetId::makeNetId(num, 0, gvNtkMgr->getGateType(gvNtkMgr->getGVNetId(num))); gate = cirMgr->getGate(num); } else if (isOutput) { - // if ((unsigned)num >= gvNtkMgr->getOutputSize()) { if ((unsigned)num >= cirMgr->getNumPOs()) { gvMsg(GV_MSG_ERR) << "Output with Index " << num << " does NOT Exist in Current Cir !!" << endl; return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } - // netId = gvNtkMgr->getOutput(num); gate = cirMgr->getPo(num); } - // gvNtkMgr->buildBdd(netId); cirMgr->buildBdd(gate); } @@ -785,8 +776,8 @@ BConstructCmd::exec(const string& option) { } void BConstructCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BConstruct <-Gateid | -Output | -All > " - << endl; + cout << "Usage: BConstruct <-Gateid | -Output | -All > " + << endl; } void BConstructCmd::help() const { diff --git a/src/cir/cirAig.cpp b/src/cir/cirAig.cpp index a9660114..2e37d3cd 100644 --- a/src/cir/cirAig.cpp +++ b/src/cir/cirAig.cpp @@ -10,183 +10,117 @@ #include -#include "base/abc/abc.h" #include "gvAbcMgr.h" -#include "gvModMgr.h" +#include "gvAbcNtk.h" #include "gvYosysMgr.h" -#include "kernel/yosys.h" #include "util.h" -string gateName(const string& name, const int& bit) { - return name + "[" + to_string(bit) + "]"; -} - -void parseAigMapping(Gia_Man_t* pGia, map& id2Name) { - string buffer; - ifstream mapFile; - int idx, bit; - string name; - - mapFile.open(".map.txt"); - assert(mapFile.is_open()); - while (mapFile) { - if (!(mapFile >> buffer)) break; - // input - if (buffer == "input") { - mapFile >> buffer; - myStr2Int(buffer, idx); - mapFile >> buffer; - myStr2Int(buffer, bit); - mapFile >> buffer; - name = buffer; - id2Name[Gia_ObjId(pGia, Gia_ManPi(pGia, idx))] = gateName(name, bit); - } - // output - else if (buffer == "output") { - mapFile >> buffer; - myStr2Int(buffer, idx); - mapFile >> buffer; - myStr2Int(buffer, bit); - mapFile >> buffer; - name = buffer; - id2Name[Gia_ObjId(pGia, Gia_ManPo(pGia, idx))] = gateName(name, bit); - } - // FF - else if (buffer == "latch") { - mapFile >> buffer; - myStr2Int(buffer, idx); - mapFile >> buffer; - myStr2Int(buffer, bit); - mapFile >> buffer; - name = buffer; - id2Name[Gia_ObjId(pGia, Gia_ObjRiToRo(pGia, Gia_ManRi(pGia, idx)))] = gateName(name, bit); - id2Name[Gia_ObjId(pGia, Gia_ManRi(pGia, idx))] = gateName(name, bit) + "_ns"; - } - } -} - - const bool CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { - // log_make_debug = true; - CirGateV gateV; - Gia_Man_t* pGia = NULL; // the gia pointer of abc - Gia_Obj_t *pObj, *pObjRi, *pObjRo; // the obj element of gia - unsigned iPi = 0, iPpi = 0, iPo = 0, iRi = 0, iRo = 0; - unsigned piNum = 0; - map PPI2RO; + Gia_Man_t* pGia = NULL; // the gia pointer of abc map id2Name; - - // abc function parameters - char* pFileName = new char[100]; - // cout << "filename = " << fileName << endl; - strcpy(pFileName, fileName.c_str()); - char* pTopModule = NULL; - char* pDefines = NULL; - int fBlast = 1; - int fInvert = 0; - int fTechMap = 1; - int fSkipStrash = 0; - int fCollapse = 0; - int c, fVerbose = 0; - int i, *pWire; - - if (fileType == AIGER) - pGia = Gia_AigerRead(pFileName, 0, fSkipStrash, 0); - else if (fileType == VERILOG) - pGia = Wln_BlastSystemVerilog(pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fVerbose); + ABCParam param; + strcpy(param.pFileName, fileName.c_str()); + cout << "filename = " << fileName << endl; + + if (fileType == AIGER) { + abcMgr->readAig(param); + pGia = abcMgr->pGia; + } else if (fileType == VERILOG) { + param.fBlast = 1; + param.fTechMap = 1; + abcMgr->readVerilog(param); + pGia = abcMgr->pGia; + } if (!pGia) { cerr << "Cannot open design \"" << fileName << "\"!!" << endl; return false; } + if (fileType == VERILOG) { - yosysMgr->buildMapping(fileName); - parseAigMapping(pGia, id2Name); + yosysMgr->createMapping(fileName); + abcMgr->buildAigName(id2Name); } // initialize the size of the containers initCir(pGia, fileType); - // increment the global travel id for circuit traversing usage - Gia_ManIncrementTravId(pGia); - // since we don't want to traverse the constant node, set the TravId of the - // constant node to be as the global one - Gia_ObjSetTravIdCurrent(pGia, Gia_ManConst0(pGia)); + abcMgr->travPreprocess(); + abcMgr->travAllObj(_piList, _poList, _roList, _riList, _totGateList, id2Name, fileType); // traverse the obj's in topological order - Gia_ManForEachObj(pGia, pObj, i) { - if (Gia_ObjIsPi(pGia, pObj)) { - int gateId = Gia_ObjId(pGia, pObj); - if (gateId <= _piList.size()) { - CirPiGate* gate = new CirPiGate(Gia_ObjId(pGia, pObj), 0); - _piList[iPi++] = gate; - _totGateList[gateId] = gate; - } else { - CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); - _roList[iRo++] = gate; - _totGateList[gateId] = gate; - } - } else if (Gia_ObjIsPo(pGia, pObj)) { - string poName = ""; - CirPoGate* gate = new CirPoGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); - poName = (id2Name.count(gate->getGid())) ? id2Name[gate->getGid()] : to_string(Gia_ObjId(pGia, pObj)); - char* n = new char[poName.size() + 1]; - strcpy(n, poName.c_str()); - gate->setName(n); - gate->setIn0(getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); - _poList[iPo++] = gate; - _totGateList[Gia_ObjId(pGia, pObj)] = gate; - } else if (Gia_ObjIsAnd(pObj)) { - CirAigGate* gate = new CirAigGate(Gia_ObjId(pGia, pObj), 0); - int fanin0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); - int fanin1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); - if (PPI2RO.count(fanin0)) fanin0 = PPI2RO[fanin0]; - if (PPI2RO.count(fanin1)) fanin1 = PPI2RO[fanin1]; - gate->setIn0(getGate(fanin0), Gia_ObjFaninC0(pObj)); - gate->setIn1(getGate(fanin1), Gia_ObjFaninC1(pObj)); - _totGateList[Gia_ObjId(pGia, pObj)] = gate; - } else if (Gia_ObjIsRo(pGia, pObj)) { - int gateId = Gia_ObjId(pGia, pObj); - if (fileType == VERILOG) { - PPI2RO[gateId] = 0; - if (iPpi < iRo) PPI2RO[gateId] = _roList[iPpi]->getGid(); - iPpi++; - } else if (fileType == AIGER) { - CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); - _roList[iRo++] = gate; - _totGateList[gateId] = gate; - } - } else if (Gia_ObjIsRi(pGia, pObj)) { - CirRiGate* gate = new CirRiGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); - string str = to_string(Gia_ObjId(pGia, pObj)); - str = str + "_ns"; - char* n = new char[str.size() + 1]; - strcpy(n, str.c_str()); - gate->setName(n); - gate->setIn0(getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); - _riList[iRi++] = gate; - _totGateList[Gia_ObjId(pGia, pObj)] = gate; - } else if (Gia_ObjIsConst0(pObj)) { - _totGateList[0] = CirMgr::_const0; - } else { - cout << "not defined gate type" << endl; - assert(true); - } - } - - Gia_ManForEachRiRo(pGia, pObjRi, pObjRo, i) { - if (i == getNumLATCHs()) break; - - int riGid = Gia_ObjId(pGia, pObjRi), roGid = 0; - // int roGid = PPI2RO[Gia_ObjId(pGia,pObjRo)]; - // int roGid = Gia_ObjId(pGia,pObjRo); - if (fileType == VERILOG) - roGid = PPI2RO[Gia_ObjId(pGia, pObjRo)]; - else if (fileType == AIGER) - roGid = Gia_ObjId(pGia, pObjRo); - CirGate* riGate = getGate(riGid); - CirRoGate* roGate = static_cast(getGate(roGid)); - roGate->setIn0(riGate, false); - } + // int i; + // Gia_ManForEachObj(pGia, pObj, i) { + // if (Gia_ObjIsPi(pGia, pObj)) { + // int gateId = Gia_ObjId(pGia, pObj); + // if (gateId <= _piList.size()) { + // CirPiGate* gate = new CirPiGate(Gia_ObjId(pGia, pObj), 0); + // _piList[iPi++] = gate; + // _totGateList[gateId] = gate; + // } else { + // CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); + // _roList[iRo++] = gate; + // _totGateList[gateId] = gate; + // } + // } else if (Gia_ObjIsPo(pGia, pObj)) { + // string poName = ""; + // CirPoGate* gate = new CirPoGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); + // poName = (id2Name.count(gate->getGid())) ? id2Name[gate->getGid()] : to_string(Gia_ObjId(pGia, pObj)); + // char* n = new char[poName.size() + 1]; + // strcpy(n, poName.c_str()); + // gate->setName(n); + // gate->setIn0(getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); + // _poList[iPo++] = gate; + // _totGateList[Gia_ObjId(pGia, pObj)] = gate; + // } else if (Gia_ObjIsAnd(pObj)) { + // CirAigGate* gate = new CirAigGate(Gia_ObjId(pGia, pObj), 0); + // int fanin0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + // int fanin1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); + // if (PPI2RO.count(fanin0)) fanin0 = PPI2RO[fanin0]; + // if (PPI2RO.count(fanin1)) fanin1 = PPI2RO[fanin1]; + // gate->setIn0(getGate(fanin0), Gia_ObjFaninC0(pObj)); + // gate->setIn1(getGate(fanin1), Gia_ObjFaninC1(pObj)); + // _totGateList[Gia_ObjId(pGia, pObj)] = gate; + // } else if (Gia_ObjIsRo(pGia, pObj)) { + // int gateId = Gia_ObjId(pGia, pObj); + // if (fileType == VERILOG) { + // PPI2RO[gateId] = 0; + // if (iPpi < iRo) PPI2RO[gateId] = _roList[iPpi]->getGid(); + // iPpi++; + // } else if (fileType == AIGER) { + // CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); + // _roList[iRo++] = gate; + // _totGateList[gateId] = gate; + // } + // } else if (Gia_ObjIsRi(pGia, pObj)) { + // CirRiGate* gate = new CirRiGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); + // string str = to_string(Gia_ObjId(pGia, pObj)); + // str = str + "_ns"; + // char* n = new char[str.size() + 1]; + // strcpy(n, str.c_str()); + // gate->setName(n); + // gate->setIn0(getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); + // _riList[iRi++] = gate; + // _totGateList[Gia_ObjId(pGia, pObj)] = gate; + // } else if (Gia_ObjIsConst0(pObj)) { + // _totGateList[0] = CirMgr::_const0; + // } else { + // cout << "not defined gate type" << endl; + // assert(true); + // } + // } + + // Gia_ManForEachRiRo(pGia, pObjRi, pObjRo, i) { + // if (i == getNumLATCHs()) break; + + // int riGid = Gia_ObjId(pGia, pObjRi), roGid = 0; + // // int roGid = PPI2RO[Gia_ObjId(pGia,pObjRo)]; + // // int roGid = Gia_ObjId(pGia,pObjRo); + // if (fileType == VERILOG) roGid = PPI2RO[Gia_ObjId(pGia, pObjRo)]; + // else if (fileType == AIGER) roGid = Gia_ObjId(pGia, pObjRo); + // CirGate* riGate = getGate(riGid); + // CirRoGate* roGate = static_cast(getGate(roGid)); + // roGate->setIn0(riGate, false); + // } // CONST1 Gate _const1 = new CirAigGate(getNumTots(), 0); addTotGate(_const1); @@ -199,16 +133,15 @@ const bool CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { void CirMgr::initCir(Gia_Man_t* pGia, const CirFileType& fileType) { // Create lists - // cout << "initializing ..." << endl; int piNum = 0, regNum = 0, poNum = 0, totNum = 0; if (fileType == VERILOG) { - piNum = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; + piNum = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; regNum = Gia_ManRegNum(pGia) - 1; } else if (fileType == AIGER) { - piNum = Gia_ManPiNum(pGia); + piNum = Gia_ManPiNum(pGia); regNum = Gia_ManRegNum(pGia); } - poNum = Gia_ManPoNum(pGia); + poNum = Gia_ManPoNum(pGia); totNum = Gia_ManObjNum(pGia); _piList.resize(piNum); diff --git a/src/cir/cirCmd.cpp b/src/cir/cirCmd.cpp index 6bab72d4..b7a1f697 100644 --- a/src/cir/cirCmd.cpp +++ b/src/cir/cirCmd.cpp @@ -100,7 +100,7 @@ GVCmdExecStatus CirReadCmd::exec(const string& option) { } void CirReadCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: CIRRead <-Verilog | -Aiger> <(string fileName)> [-Replace]" << endl; + cout << "Usage: CIRRead <-Verilog | -Aiger> <(string fileName)> [-Replace]" << endl; } void CirReadCmd::help() const { @@ -173,12 +173,12 @@ CirGateCmd::exec(const string& option) { if (myStrNCmp("-FANIn", options[i], 5) == 0) { if (doFanin || doFanout) return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); - doFanin = true; + doFanin = true; checkLevel = true; } else if (myStrNCmp("-FANOut", options[i], 5) == 0) { if (doFanin || doFanout) return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[i]); - doFanout = true; + doFanout = true; checkLevel = true; } else if (!thisGate) { if (!myStr2Int(options[i], gateId) || gateId < 0) @@ -251,7 +251,7 @@ void CirGateCmd::help() const { // void // CirSweepCmd::usage(const bool& verbose) const // { -// gvMsg(GV_MSG_IFO) << "Usage: CIRSWeep" << endl; +// cout << "Usage: CIRSWeep" << endl; // } // void @@ -293,7 +293,7 @@ void CirGateCmd::help() const { // void // CirOptCmd::usage(const bool& verbose) const // { -// gvMsg(GV_MSG_IFO) << "Usage: CIROPTimize" << endl; +// cout << "Usage: CIROPTimize" << endl; // } // void @@ -339,7 +339,7 @@ void CirGateCmd::help() const { // void // CirStrashCmd::usage(const bool& verbose) const // { -// gvMsg(GV_MSG_IFO) << "Usage: CIRSTRash" << endl; +// cout << "Usage: CIRSTRash" << endl; // } // void @@ -418,7 +418,7 @@ void CirGateCmd::help() const { // void // CirSimCmd::usage(const bool& verbose) const // { -// gvMsg(GV_MSG_IFO) << "Usage: CIRSIMulate <-Random | -File >\n" +// cout << "Usage: CIRSIMulate <-Random | -File >\n" // << " [-Output (string logFile)]" << endl; // } @@ -459,7 +459,7 @@ void CirGateCmd::help() const { // void // CirFraigCmd::usage(const bool& verbose) const // { -// gvMsg(GV_MSG_IFO) << "Usage: CIRFraig" << endl; +// cout << "Usage: CIRFraig" << endl; // } // void @@ -531,7 +531,7 @@ void CirGateCmd::help() const { // void // CirWriteCmd::usage(const bool& verbose) const // { -// gvMsg(GV_MSG_IFO) << "Usage: CIRWrite [(int gateId)][-Output (string aagFile)]" << endl; +// cout << "Usage: CIRWrite [(int gateId)][-Output (string aagFile)]" << endl; // } // void @@ -595,7 +595,7 @@ void CirGateCmd::help() const { // void // CirMiterCmd::usage(const bool& verbose) const // { -// gvMsg(GV_MSG_IFO) << "Usage: CIRMiter <(string inFile1)> <(string inFile2)> " << endl; +// cout << "Usage: CIRMiter <(string inFile1)> <(string inFile2)> " << endl; // } // void @@ -629,7 +629,7 @@ void CirGateCmd::help() const { // void // CirEffortCmd::usage(const bool& verbose) const // { -// gvMsg(GV_MSG_IFO) << "Usage: CIREFFort <(int effortLimit)>" << endl; +// cout << "Usage: CIREFFort <(int effortLimit)>" << endl; // } // void diff --git a/src/cmd/gvCmdComm.cpp b/src/cmd/gvCmdComm.cpp index 6590d86d..3748d5c7 100644 --- a/src/cmd/gvCmdComm.cpp +++ b/src/cmd/gvCmdComm.cpp @@ -2,13 +2,15 @@ #define GV_CMD_COMM_C #include "gvCmdComm.h" + +#include + #include "gvMsg.h" #include "gvUsage.h" #include "util.h" -#include -bool -initCommonCmd() { + +bool initCommonCmd() { return (gvCmdMgr->regCmd("DOfile", 2, new GVDofileCmd) && gvCmdMgr->regCmd("HELp", 3, new GVHelpCmd) && gvCmdMgr->regCmd("HIStory", 3, new GVHistoryCmd) && @@ -25,7 +27,7 @@ GVHelpCmd::exec(const string& option) { vector options; GVCmdExec::lexOptions(option, options); - bool verbose = false, revealed = false; + bool verbose = false, revealed = false; string cmd = ""; size_t n = options.size(); @@ -51,16 +53,16 @@ GVHelpCmd::exec(const string& option) { } } - if (revealed) gvCmdMgr->printHelps(true); // Print All Commands - else if (!cmd.size()) gvCmdMgr->printHelps(); // Print Commands + if (revealed) gvCmdMgr->printHelps(true); // Print All Commands + else if (!cmd.size()) gvCmdMgr->printHelps(); // Print Commands else { GVCmdExec* e = gvCmdMgr->getCmd(cmd); if (e) { e->usage(verbose); return GV_CMD_EXEC_DONE; - } // if exact match + } // if exact match GVCmdExecSubSet list = gvCmdMgr->getCmdListFromPart(cmd); - if (list.size()) { // if partial match + if (list.size()) { // if partial match GVCmdExecSubSet::iterator it = list.begin(); if (verbose) for (; it != list.end(); ++it) (*it)->usage(); @@ -72,22 +74,20 @@ GVHelpCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -GVHelpCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: HELp [<(string cmd) [-Verbose]>]" << endl; +void GVHelpCmd::usage(const bool& verbose) const { + cout << "Usage: HELp [<(string cmd) [-Verbose]>]" << endl; if (verbose) { - gvMsg(GV_MSG_IFO) + cout << "Param: (string cmd): The (partial) name of the command." << endl; - gvMsg(GV_MSG_IFO) << " -Verbose : Print usage in more detail." - << endl; + cout << " -Verbose : Print usage in more detail." + << endl; } } -void -GVHelpCmd::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "HELp: " - << "Print this help message." << endl; +void GVHelpCmd::help() const { + cout << setw(20) << left << "HELp: " + << "Print this help message." << endl; } //---------------------------------------------------------------------- @@ -106,7 +106,7 @@ GVQuitCmd::exec(const string& option) { else return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); } - gvMsg(GV_MSG_IFO) << "Are you sure to quit (Yes/No)? [No] "; + cout << "Are you sure to quit (Yes/No)? [No] "; char str[1024]; cin.getline(str, 1024); string ss = string(str); @@ -118,19 +118,17 @@ GVQuitCmd::exec(const string& option) { else return GV_CMD_EXEC_DONE; } -void -GVQuitCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: Quit [-Force]" << endl; +void GVQuitCmd::usage(const bool& verbose) const { + cout << "Usage: Quit [-Force]" << endl; if (verbose) { - gvMsg(GV_MSG_IFO) << "Param: -Force: Quit the program forcedly." - << endl; + cout << "Param: -Force: Quit the program forcedly." + << endl; } } -void -GVQuitCmd::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "Quit: " - << "Quit the execution." << endl; +void GVQuitCmd::help() const { + cout << setw(20) << left << "Quit: " + << "Quit the execution." << endl; } //---------------------------------------------------------------------- @@ -151,20 +149,18 @@ GVHistoryCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -GVHistoryCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: HIStory [(int nPrint)]" << endl; +void GVHistoryCmd::usage(const bool& verbose) const { + cout << "Usage: HIStory [(int nPrint)]" << endl; if (verbose) { - gvMsg(GV_MSG_IFO) << "Param: (int nPrint): The number of the latest " - "commands to be printed. (default = MAX)" - << endl; + cout << "Param: (int nPrint): The number of the latest " + "commands to be printed. (default = MAX)" + << endl; } } -void -GVHistoryCmd::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "HIStory: " - << "Print command history." << endl; +void GVHistoryCmd::help() const { + cout << setw(20) << left << "HIStory: " + << "Print command history." << endl; } //---------------------------------------------------------------------- @@ -188,19 +184,17 @@ GVDofileCmd ::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -GVDofileCmd ::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: DOfile <(string fileName)>" << endl; +void GVDofileCmd ::usage(const bool& verbose) const { + cout << "Usage: DOfile <(string fileName)>" << endl; if (verbose) { - gvMsg(GV_MSG_IFO) + cout << "Param: (string fileName): The file name of the script." << endl; } } -void -GVDofileCmd ::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "DOfile: " - << "Execute the commands in the dofile." << endl; +void GVDofileCmd ::help() const { + cout << setw(20) << left << "DOfile: " + << "Execute the commands in the dofile." << endl; } //---------------------------------------------------------------------- @@ -236,21 +230,19 @@ GVUsageCmd ::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -GVUsageCmd ::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: USAGE [-Time-only | -Memory-only]" << endl; +void GVUsageCmd ::usage(const bool& verbose) const { + cout << "Usage: USAGE [-Time-only | -Memory-only]" << endl; if (verbose) { - gvMsg(GV_MSG_IFO) + cout << "Param: -Time-only : Disable memory usage reporting." << endl; - gvMsg(GV_MSG_IFO) + cout << " -Memory-only: Disable time usage reporting." << endl; } } -void -GVUsageCmd ::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "USAGE: " - << "Report resource usage." << endl; +void GVUsageCmd ::help() const { + cout << setw(20) << left << "USAGE: " + << "Report resource usage." << endl; } #endif \ No newline at end of file diff --git a/src/cmd/gvCmdMgr.cpp b/src/cmd/gvCmdMgr.cpp index ed5a3a93..d1bdb50e 100644 --- a/src/cmd/gvCmdMgr.cpp +++ b/src/cmd/gvCmdMgr.cpp @@ -11,8 +11,8 @@ #include "gvMsg.h" #include "util.h" - -extern "C" { +extern "C" +{ #include #include } @@ -90,7 +90,7 @@ GVCmdExec::errorOption(GVCmdOptionError err, const string& opt) const { bool GVCmdExec::checkCmd(const string& check) const { unsigned len = this->getCmdLen(); - bool result = false; + bool result = false; size_t space = 0, nxt_space; for (unsigned word = 1; word <= len; ++word) { @@ -99,7 +99,7 @@ bool GVCmdExec::checkCmd(const string& check) const { for (unsigned i = space + 1; i <= nxt_space; ++i) { string checkMand = check.substr(space, i - space); - string checkOpt = check.substr(i, nxt_space - space - i); + string checkOpt = check.substr(i, nxt_space - space - i); if (checkMandCmd(checkMand, word) && (checkOpt.empty() || checkOptCmd(checkOpt, word))) { @@ -110,7 +110,7 @@ bool GVCmdExec::checkCmd(const string& check) const { if (result == false) return false; result = false; - space = nxt_space + 1; + space = nxt_space + 1; } return true; @@ -123,7 +123,7 @@ bool GVCmdExec::checkCmd(const string& check, size_t idx) const { for (unsigned i = 1, n = check.size(); i <= n; ++i) { string checkMand = check.substr(0, i); - string checkOpt = check.substr(i, n + 1 - i); + string checkOpt = check.substr(i, n + 1 - i); if (checkMandCmd(checkMand, idx) && (checkOpt.empty() || checkOptCmd(checkOpt, idx))) { @@ -187,7 +187,7 @@ bool GVCmdMgr::regCmd(const string& cmd, unsigned nCmp, GVCmdExec* e) { e->setOptCmd(str.substr(nCmp)); GVCmdExecSet::iterator it = _cmdLib.find(e->getGVCmdType()); - GVCmdExecSubSet* cmdSet = 0; + GVCmdExecSubSet* cmdSet = 0; if (it == _cmdLib.end()) { cmdSet = new GVCmdExecSubSet(); _cmdLib.insert(make_pair(e->getGVCmdType(), cmdSet)); @@ -198,8 +198,7 @@ bool GVCmdMgr::regCmd(const string& cmd, unsigned nCmp, GVCmdExec* e) { return true; } -bool GVCmdMgr::regCmd(const string& cmd, unsigned nCmp1, unsigned nCmp2, - GVCmdExec* e) { +bool GVCmdMgr::regCmd(const string& cmd, unsigned nCmp1, unsigned nCmp2, GVCmdExec* e) { assert(e); assert(cmd.size()); assert(nCmp1); @@ -228,7 +227,7 @@ bool GVCmdMgr::regCmd(const string& cmd, unsigned nCmp1, unsigned nCmp2, e->setOptCmd(str2.substr(nCmp2)); GVCmdExecSet::iterator it = _cmdLib.find(e->getGVCmdType()); - GVCmdExecSubSet* cmdSet = 0; + GVCmdExecSubSet* cmdSet = 0; if (it == _cmdLib.end()) { cmdSet = new GVCmdExecSubSet(); _cmdLib.insert(make_pair(e->getGVCmdType(), cmdSet)); @@ -241,7 +240,7 @@ bool GVCmdMgr::regCmd(const string& cmd, unsigned nCmp1, unsigned nCmp2, GVCmdExecStatus GVCmdMgr::execOneCmd() { // Read User Command Input - string str = ""; + string str = ""; char* execCmd = new char[1024]; if (_dofile.is_open()) { getline(_dofile, str); @@ -252,10 +251,13 @@ GVCmdMgr::execOneCmd() { execCmd = readline(getPrompt().c_str()); assert(execCmd); + // Detect dofile comment(#) for debugging + if (execCmd[0] == '#') return GV_CMD_EXEC_NOP; + if (addHistory(execCmd)) { add_history(_history.back().c_str()); string option = ""; - GVCmdExec* e = parseCmd(option); + GVCmdExec* e = parseCmd(option); // Check command types if (e) { GVCmdType cmdType = e->getGVCmdType(); @@ -394,14 +396,14 @@ GVCmdMgr::getCmdListFromPart(const string& cmd) const { void GVCmdMgr::printHelps(bool revealed) const { GVCmdExecSet::const_iterator it; GVCmdExecSubSet::iterator is; - gvMsg(GV_MSG_IFO) << endl; + cout << endl; for (it = _cmdLib.begin(); it != _cmdLib.end(); ++it) { if ((revealed) ^ (it->first != GV_CMD_TYPE_REVEALED)) { - gvMsg(GV_MSG_IFO) << "========== " << GVCmdTypeString[it->first] - << " Commands : ==========" << endl; + cout << "========== " << GVCmdTypeString[it->first] + << " Commands : ==========" << endl; for (is = it->second->begin(); is != it->second->end(); ++is) (*is)->help(); - gvMsg(GV_MSG_IFO) << endl; + cout << endl; } } } @@ -409,13 +411,13 @@ void GVCmdMgr::printHelps(bool revealed) const { void GVCmdMgr::printHistory(int nPrint) const { int historySize = _history.size(); if (historySize == 0) { - gvMsg(GV_MSG_IFO) << "Empty command history!!" << endl; + cout << "Empty command history!!" << endl; return; } if ((nPrint < 0) || (nPrint > historySize)) nPrint = historySize; assert(historySize >= nPrint); for (int i = historySize - nPrint; i < historySize; ++i) - gvMsg(GV_MSG_IFO) << " " << i << ": " << _history[i] << endl; + cout << " " << i << ": " << _history[i] << endl; } bool GVCmdMgr::addHistory(char* cmd) { diff --git a/src/gvsat/gvSat.cpp b/src/gvsat/gvSat.cpp index 364b194e..b98f41ba 100644 --- a/src/gvsat/gvSat.cpp +++ b/src/gvsat/gvSat.cpp @@ -113,11 +113,11 @@ GVSatSolver::getDataValue(const size_t& var) const { return (isNegFormula(var)) ^ (gv_l_True == _solver->model[getOriVar(var)]); } -const size_t -GVSatSolver::getFormula(const GVNetId& id, const uint32_t& depth) { +// const size_t +// GVSatSolver::getFormula(const GVNetId& id, const uint32_t& depth) { // Var var = getVerifyData(id, depth); // return (id.fanin0Cp ? getNegVar(var) : getPosVar(var)); -} +// } void GVSatSolver::resizeNtkData(const uint32_t& num) { vector* tmp = new vector[_cirMgr->getNumTots()]; diff --git a/src/gvsat/gvSat.h b/src/gvsat/gvSat.h index 74e0c99e..2607d7cd 100644 --- a/src/gvsat/gvSat.h +++ b/src/gvsat/gvSat.h @@ -17,7 +17,7 @@ #include "cirGate.h" #include "cirMgr.h" #include "gvBitVec.h" -#include "gvNtk.h" +// #include "gvNtk.h" using namespace std; class SATMgr; @@ -42,7 +42,7 @@ class GVSatSolver { int getNumClauses() const { return _solver->nRootCla(); } // Network to Solver Functions - const size_t getFormula(const GVNetId&, const uint32_t&); + // const size_t getFormula(const GVNetId&, const uint32_t&); const GVBitVecX getDataValue(const CirGate*, const uint32_t&) const; const bool getDataValue(const size_t&) const; // Variable Interface Functions diff --git a/src/itp/gvSatCmd.cpp b/src/itp/gvSatCmd.cpp index cd16edf1..a4254629 100644 --- a/src/itp/gvSatCmd.cpp +++ b/src/itp/gvSatCmd.cpp @@ -60,7 +60,7 @@ SATVerifyItpCmd::exec(const string& option) { gvMsg(GV_MSG_ERR) << "Output with Index " << num << " does NOT Exist in Current Ntk !!" << endl; return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } - gate = cirMgr->getPo(num); + gate = cirMgr->getPo(num); monitorName = gate->getName(); } // get PO's input, since the PO is actually a redundant node and should be removed @@ -74,7 +74,7 @@ SATVerifyItpCmd::exec(const string& option) { } void SATVerifyItpCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: SATVerify ITP < -GateId | -Output >" << endl; + cout << "Usage: SATVerify ITP < -GateId | -Output >" << endl; } void SATVerifyItpCmd::help() const { @@ -118,7 +118,7 @@ SATVerifyBmcCmd::exec(const string& option) { return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); } monitorName = cirMgr->getPo(num)->getName(); - gate = cirMgr->getPo(num)->getIn0Gate(); + gate = cirMgr->getPo(num)->getIn0Gate(); } // get PO's input, since the PO is actually a redundant node and should be removed satMgr->verifyPropertyBmc(monitorName, gate); @@ -127,7 +127,7 @@ SATVerifyBmcCmd::exec(const string& option) { } void SATVerifyBmcCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: SATVerify BMC < -GateId | -Output < outputIndex >> " << endl; + cout << "Usage: SATVerify BMC < -GateId | -Output < outputIndex >> " << endl; } void SATVerifyBmcCmd::help() const { diff --git a/src/itp/gvSatMgr.cpp b/src/itp/gvSatMgr.cpp index 7644f6cf..ee69a36a 100644 --- a/src/itp/gvSatMgr.cpp +++ b/src/itp/gvSatMgr.cpp @@ -25,7 +25,7 @@ void SATMgr::verifyPropertyItp(const string &name, const CirGate *monitor) { // duplicate the network, so you can modified // the ntk for the proving property without // destroying the original network - _cirMgr = new CirMgr(); + _cirMgr = new CirMgr(); *_cirMgr = *cirMgr; SatProofRes pRes; GVSatSolver *gvSatSolver = new GVSatSolver(_cirMgr); @@ -48,7 +48,7 @@ void SATMgr::verifyPropertyBmc(const string &name, const CirGate *monitor) { // duplicate the network, so you can modified // the ntk for the proving property without // destroying the original network - _cirMgr = new CirMgr(); + _cirMgr = new CirMgr(); *_cirMgr = *cirMgr; SatProofRes pRes; GVSatSolver *gvSatSolver = new GVSatSolver(_cirMgr); @@ -97,7 +97,7 @@ void SATMgr::itpUbmc(const CirGate *monitor, SatProofRes &pRes) { bind(gvSatSolver); size_t num_clauses = getNumClauses(); - bool proved = false; + bool proved = false; gvSatSolver->assumeRelease(); // GVNetId S, R, R_prime, tmp1, tmp2, tmp3, tmp4; CirGate *S; @@ -220,8 +220,8 @@ void SATMgr::itpUbmc(const CirGate *monitor, SatProofRes &pRes) { // see if Si or Ri-1 equals to Ri unsigned gateSize = _cirMgr->getNumTots(); - R_prime = _cirMgr->createOrGate(R, S); - tmp5 = _cirMgr->createXorGate(R, R_prime); + R_prime = _cirMgr->createOrGate(R, S); + tmp5 = _cirMgr->createXorGate(R, R_prime); gvSatSolver->resizeNtkData(_cirMgr->getNumTots() - gateSize); gvSatSolver->addBoundedVerifyData(tmp5, 0); @@ -239,7 +239,7 @@ void SATMgr::itpUbmc(const CirGate *monitor, SatProofRes &pRes) { markOnsetClause(j); } num_clauses = getNumClauses(); - R = R_prime; + R = R_prime; } } if (proved) break; @@ -567,7 +567,7 @@ CirGate *SATMgr::buildItp(const string &proofName) const { } if (_varGroup[idx >> 1] == COMMON) { assert(_var2Net.find(idx >> 1) != _var2Net.end()); - nId = (_var2Net.find(idx >> 1))->second; + nId = (_var2Net.find(idx >> 1))->second; nId1 = (_var2Net.find(idx >> 1))->second; if ((idx & 1) == 1) nId1 = _cirMgr->createNotGate(nId1); if ((idx & 1) == 1) nId = _cirMgr->createNotGate(nId); @@ -579,7 +579,7 @@ CirGate *SATMgr::buildItp(const string &proofName) const { assert(_var2Net.find(idx >> 1) != _var2Net.end()); nId2 = (_var2Net.find(idx >> 1))->second; if ((idx & 1) == 1) nId2 = _cirMgr->createNotGate(nId2); - nId = _cirMgr->createOrGate(nId1, nId2); + nId = _cirMgr->createOrGate(nId1, nId2); nId1 = nId; } } @@ -594,7 +594,7 @@ CirGate *SATMgr::buildItp(const string &proofName) const { // Derived Clause tmp_cid = cid - (tmp >> 1); assert(claItpLookup.find(tmp_cid) != claItpLookup.end()); - nId = (claItpLookup.find(tmp_cid))->second; + nId = (claItpLookup.find(tmp_cid))->second; nId1 = (claItpLookup.find(tmp_cid))->second; while (1) { idx = rdr.get64(); @@ -607,32 +607,32 @@ CirGate *SATMgr::buildItp(const string &proofName) const { if (nId1 != nId2) { if (_varGroup[idx] == LOCAL_ON) { // Local to A. Build OR Gate. if (nId1 == CONST1 || nId2 == CONST1) { - nId = CONST1; + nId = CONST1; nId1 = nId; } else if (nId1 == CONST0) { - nId = nId2; + nId = nId2; nId1 = nId; } else if (nId2 == CONST0) { - nId = nId1; + nId = nId1; nId1 = nId; } else { // or - nId = _cirMgr->createOrGate(nId1, nId2); + nId = _cirMgr->createOrGate(nId1, nId2); nId1 = nId; } } else { // Build AND Gate. if (nId1 == CONST0 || nId2 == CONST0) { - nId = CONST0; + nId = CONST0; nId1 = nId; } else if (nId1 == CONST1) { - nId = nId2; + nId = nId2; nId1 = nId; } else if (nId2 == CONST1) { - nId = nId1; + nId = nId1; nId1 = nId; } else { // and - nId = _cirMgr->createAndGate(nId1, nId2); + nId = _cirMgr->createAndGate(nId1, nId2); nId1 = nId; } } @@ -652,13 +652,13 @@ CirGate *SATMgr::buildItp(const string &proofName) const { void SatProofRes::reportResult(const string &name) const { // Report Verification Result - gvMsg(GV_MSG_IFO) << endl; + cout << endl; if (isProved()) { - gvMsg(GV_MSG_IFO) << "Monitor \"" << name << "\" is safe." << endl; + cout << "Monitor \"" << name << "\" is safe." << endl; } else if (isFired()) { - gvMsg(GV_MSG_IFO) << "Monitor \"" << name << "\" is violated." << endl; + cout << "Monitor \"" << name << "\" is violated." << endl; } else { - gvMsg(GV_MSG_IFO) << "UNDECIDED at depth = " << _maxDepth << endl; + cout << "UNDECIDED at depth = " << _maxDepth << endl; } } @@ -668,16 +668,16 @@ void SatProofRes::reportCex(const CirGate *monitor, const CirMgr *const _cirMgr) // Output Pattern Value (PI + PIO) GVBitVecX dataValue; for (uint32_t i = 0; i <= _fired; ++i) { - gvMsg(GV_MSG_IFO) << i << ": "; + cout << i << ": "; for (int j = _cirMgr->getNumPIs() - 1; j >= 0; --j) { if (_satSolver->existVerifyData(_cirMgr->getPi(j), i)) { dataValue = _satSolver->getDataValue(_cirMgr->getPi(j), i); - gvMsg(GV_MSG_IFO) << dataValue[0]; + cout << dataValue[0]; } else { - gvMsg(GV_MSG_IFO) << 'x'; + cout << 'x'; } } - gvMsg(GV_MSG_IFO) << endl; + cout << endl; assert(_satSolver->existVerifyData(monitor, i)); } } diff --git a/src/itp/gvSatMgr.h b/src/itp/gvSatMgr.h index 6231c7b3..c5634aee 100644 --- a/src/itp/gvSatMgr.h +++ b/src/itp/gvSatMgr.h @@ -12,10 +12,11 @@ #include #include +#include #include #include -#include "gvNtk.h" +// #include "gvNtk.h" #include "gvSat.h" // #include "SolverTypesV.h" #include "cirGate.h" @@ -34,16 +35,16 @@ enum VAR_GROUP { class SatProofRes { public: - SatProofRes(GVSatSolver* s = 0) : _proved(GVNtkUD), _fired(GVNtkUD), _maxDepth(GVNtkUD), _satSolver(s) {} + SatProofRes(GVSatSolver* s = 0) : _proved(UINT_MAX), _fired(UINT_MAX), _maxDepth(UINT_MAX), _satSolver(s) {} - void setProved(uint32_t i) { _proved = i; } - void setFired(uint32_t i) { _fired = i; } + void setProved(size_t i) { _proved = i; } + void setFired(size_t i) { _fired = i; } - bool isProved() const { return (_proved != GVNtkUD); } - bool isFired() const { return (_fired != GVNtkUD); } + bool isProved() const { return (_proved != UINT_MAX); } + bool isFired() const { return (_fired != UINT_MAX); } - void setMaxDepth(uint32_t d) { _maxDepth = d; } - uint32_t getMaxDepth() const { return _maxDepth; } + void setMaxDepth(size_t d) { _maxDepth = d; } + size_t getMaxDepth() const { return _maxDepth; } void setSatSolver(GVSatSolver* s) { _satSolver = s; } GVSatSolver* getSatSolver() const { return _satSolver; } @@ -52,9 +53,9 @@ class SatProofRes { void reportCex(const CirGate*, const CirMgr* const) const; private: - uint32_t _proved; - uint32_t _fired; - uint32_t _maxDepth; // maximum proof depth + size_t _proved; + size_t _fired; + size_t _maxDepth; // maximum proof depth GVSatSolver* _satSolver; }; diff --git a/src/main/main.cpp b/src/main/main.cpp index 27f18b36..dc93120f 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -28,7 +28,6 @@ GVUsage gvUsage; GVCmdMgr* gvCmdMgr = new GVCmdMgr("gv"); extern bool initCommonCmd(); -extern bool initNtkCmd(); extern bool initSimCmd(); extern bool initVrfCmd(); extern bool initAbcCmd(); @@ -72,7 +71,7 @@ int main(int argc, char** argv) { } cout << "GV v0.3.0 - Copyright © 2022-2023, DVLab NTUEE.\n"; - if (!(initCommonCmd() && initNtkCmd() && initSimCmd() && initVrfCmd() && initAbcCmd() && + if (!(initCommonCmd() && initSimCmd() && initVrfCmd() && initAbcCmd() && initModCmd() && initBddCmd() && initProveCmd() && initItpCmd() && initCirCmd() && initYosysCmd())) return 1; diff --git a/src/mod/gvModCmd.cpp b/src/mod/gvModCmd.cpp index ece919e7..5c684926 100644 --- a/src/mod/gvModCmd.cpp +++ b/src/mod/gvModCmd.cpp @@ -2,17 +2,19 @@ #define GV_MOD_CMD_C #include "gvModCmd.h" + +#include +#include +#include +#include + #include "gvAbcMgr.h" #include "gvModMgr.h" #include "gvMsg.h" #include "kernel/yosys.h" #include "util.h" -#include -#include -#include -bool -initModCmd() { +bool initModCmd() { if (gvModMgr) delete gvModMgr; gvModMgr = new GVModMgr; return (gvCmdMgr->regCmd("SEt SYStem", 2, 3, new GVSetSystemCmd) && @@ -23,12 +25,12 @@ initModCmd() { GVCmdExecStatus GVSetSystemCmd::exec(const string& option) { if (!gvModMgr->getInputFileExist()) { - gvMsg(GV_MSG_IFO) << "[ERROR]: Please use command \"READ DESIGN\" to " - "read the input file first !!\n"; + cout << "[ERROR]: Please use command \"READ DESIGN\" to " + "read the input file first !!\n"; return GV_CMD_EXEC_NOP; } - bool setup = false, vrf = false; + bool setup = false, vrf = false; vector options; GVCmdExec::lexOptions(option, options); @@ -54,20 +56,17 @@ GVSetSystemCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -GVSetSystemCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: SEt SYStem " << endl; +void GVSetSystemCmd::usage(const bool& verbose) const { + cout << "Usage: SEt SYStem " << endl; } -void -GVSetSystemCmd::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "SEt System: " - << "Switch to setup/vrf mode." << endl; +void GVSetSystemCmd::help() const { + cout << setw(20) << left << "SEt System: " + << "Switch to setup/vrf mode." << endl; } GVCmdExecStatus GVResetCmd ::exec(const string& option) { - bool delete_abc = true; bool delete_yosys = true; @@ -103,28 +102,26 @@ GVResetCmd ::exec(const string& option) { // gvModMgr = new GVModMgr; } -void -GVResetCmd ::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: RESET SYStem [ Abc | Yosys ]" << endl; - gvMsg(GV_MSG_IFO) +void GVResetCmd ::usage(const bool& verbose) const { + cout << "Usage: RESET SYStem [ Abc | Yosys ]" << endl; + cout << " If engine is specified, only delete the ntk stored inside. " "However, it may be risky to only delete partial datas." << endl; } -void -GVResetCmd ::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "RESET SYStem: " - << "Delete all ntks in gv and reset to setup mode." - << endl; +void GVResetCmd ::help() const { + cout << setw(20) << left << "RESET SYStem: " + << "Delete all ntks in gv and reset to setup mode." + << endl; } GVCmdExecStatus GVSetWizardCmd::exec(const string& option) { - GVCmdExecStatus status = GV_CMD_EXEC_DONE; - bool isFile = false; - string wizardFileName = ""; - vector options; + GVCmdExecStatus status = GV_CMD_EXEC_DONE; + bool isFile = false; + string wizardFileName = ""; + vector options; gvModMgr->setWizard(true); GVCmdExec::lexOptions(option, options); @@ -151,14 +148,14 @@ GVSetWizardCmd::exec(const string& option) { // Start read the wizard file content ifstream infile(wizardFileName); if (!infile) { - gvMsg(GV_MSG_IFO) << "[ERROR]: Wizard file name \"" + wizardFileName + - "\" not found !!\n"; + cout << "[ERROR]: Wizard file name \"" + wizardFileName + + "\" not found !!\n"; return GV_CMD_EXEC_ERROR; } - string prompt = ""; + string prompt = ""; vector promptBound; - string bound; + string bound; while (1) { getline(infile, bound); @@ -172,7 +169,7 @@ GVSetWizardCmd::exec(const string& option) { } // Start the GV tutorial wizard - int promptPos = 0, wizardIdx = 0, progress = 1; + int promptPos = 0, wizardIdx = 0, progress = 1; bool firstPrompt = true, debug = false; system("clear"); while (status != GV_CMD_EXEC_QUIT) { @@ -206,14 +203,12 @@ GVSetWizardCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -GVSetWizardCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: Type \"WIZard\" " << endl; +void GVSetWizardCmd::usage(const bool& verbose) const { + cout << "Usage: Type \"WIZard\" " << endl; } -void -GVSetWizardCmd::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "WIZard: " - << "Start the GV turtorial wizard." << endl; +void GVSetWizardCmd::help() const { + cout << setw(20) << left << "WIZard: " + << "Start the GV turtorial wizard." << endl; } #endif diff --git a/src/mod/gvModCmd.h b/src/mod/gvModCmd.h index 819ec2a5..62a10579 100644 --- a/src/mod/gvModCmd.h +++ b/src/mod/gvModCmd.h @@ -2,7 +2,6 @@ #define GV_MOD_CMD_H #include "gvCmdMgr.h" -#include "gvModMgr.h" GV_COMMAND(GVSetSystemCmd, GV_CMD_TYPE_MOD); GV_COMMAND(GVResetCmd, GV_CMD_TYPE_MOD); diff --git a/src/ntk/.depend.mak b/src/ntk/.depend.mak deleted file mode 100644 index 71777112..00000000 --- a/src/ntk/.depend.mak +++ /dev/null @@ -1,105 +0,0 @@ -gvNtkBdd.o: gvNtkBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ - ../../include/bddNodeV.h ../../include/bddNodeV.h ../../include/gvMsg.h \ - gvNtk.h ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h -gvNtkCmd.o: gvNtkCmd.cpp gvNtkCmd.h ../../include/gvCmdMgr.h \ - ../../include/gvMsg.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/gvModMgr.h ../../include/gvCmdMgr.h gvNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h -gvNtk.o: gvNtk.cpp gvNtk.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/cirMgr.h \ - ../../include/cirDef.h ../../include/myHash.h ../../include/cirGate.h \ - ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ - ../../include/SolverTypesV.h ../../include/GlobalV.h \ - ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ - ../../include/cirGate.h ../../include/cirMgr.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h gvNtk.h ../../include/gvMsg.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/ntk/.extheader.mak b/src/ntk/.extheader.mak deleted file mode 100644 index 81497bb9..00000000 --- a/src/ntk/.extheader.mak +++ /dev/null @@ -1,7 +0,0 @@ -ntk.d: ../../include/gvNtkCmd.h ../../include/gvNtk.h -../../include/gvNtkCmd.h: gvNtkCmd.h - @rm -f ../../include/gvNtkCmd.h - @ln -fs ../src/ntk/gvNtkCmd.h ../../include/gvNtkCmd.h -../../include/gvNtk.h: gvNtk.h - @rm -f ../../include/gvNtk.h - @ln -fs ../src/ntk/gvNtk.h ../../include/gvNtk.h diff --git a/src/ntk/.map.txt b/src/ntk/.map.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ntk/.mapGold.txt b/src/ntk/.mapGold.txt deleted file mode 100644 index a247120e..00000000 --- a/src/ntk/.mapGold.txt +++ /dev/null @@ -1,23 +0,0 @@ -input 0 0 reset -input 1 0 clk -output 0 0 z1 -output 1 0 z2 -output 2 0 z3 -output 3 0 z4 -output 4 0 z5 -latch 0 0 x -latch 1 1 x -latch 2 2 x -latch 3 3 x -latch 4 4 x -latch 5 5 x -latch 6 6 x -latch 7 7 x -latch 8 0 y -latch 9 1 y -latch 10 2 y -latch 11 3 y -latch 12 4 y -latch 13 5 y -latch 14 6 y -latch 15 7 y diff --git a/src/ntk/.mapOld.txt b/src/ntk/.mapOld.txt deleted file mode 100644 index a247120e..00000000 --- a/src/ntk/.mapOld.txt +++ /dev/null @@ -1,23 +0,0 @@ -input 0 0 reset -input 1 0 clk -output 0 0 z1 -output 1 0 z2 -output 2 0 z3 -output 3 0 z4 -output 4 0 z5 -latch 0 0 x -latch 1 1 x -latch 2 2 x -latch 3 3 x -latch 4 4 x -latch 5 5 x -latch 6 6 x -latch 7 7 x -latch 8 0 y -latch 9 1 y -latch 10 2 y -latch 11 3 y -latch 12 4 y -latch 13 5 y -latch 14 6 y -latch 15 7 y diff --git a/src/ntk/Makefile b/src/ntk/Makefile deleted file mode 100644 index a7c9a1f5..00000000 --- a/src/ntk/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -PKGFLAG = $(DEBUG_FLAG) - -EXTHDRS = gvNtkCmd.h gvNtk.h - -include ../Makefile.in -include ../Makefile.lib - diff --git a/src/ntk/abcc b/src/ntk/abcc deleted file mode 120000 index c1ce9170..00000000 --- a/src/ntk/abcc +++ /dev/null @@ -1 +0,0 @@ -../../engine/abc/gv_src/ \ No newline at end of file diff --git a/src/ntk/gvNtk.cpp b/src/ntk/gvNtk.cpp deleted file mode 100644 index bcba938d..00000000 --- a/src/ntk/gvNtk.cpp +++ /dev/null @@ -1,583 +0,0 @@ -/**************************************************************************** - FileName [ gvNtk.cpp ] - PackageName [ gv/src/ntk ] - Synopsis [ GV Network ] - Author [ ] - Copyright [ ] -****************************************************************************/ -#include "gvNtk.h" -#include "cirMgr.h" -#include "cirGate.h" -#include "base/abc/abc.h" -#include "gvMsg.h" -#include "map" -#include "util.h" -#include - -// extern functions -extern "C" -{ - Gia_Man_t* Wln_BlastSystemVerilog(char* pFileName, char* pTopModule, - char* pDefines, int fSkipStrash, - int fInvert, int fTechMap, int fVerbose); -} -// declaration -GVRTLDesign* gvRTLDesign; -GVNtkMgr* gvNtkMgr; - -// ---------------------------------------------------------------------- -// constructor / deconstructor for GVNtkMgr -// ---------------------------------------------------------------------- -void -GVNtkMgr::reset() { - // info - _InputList.clear(); - _OutputList.clear(); - _InoutList.clear(); - _FFList.clear(); - _ConstList.clear(); - _FFConst0List.clear(); - // map - _id2FaninId.clear(); - _id2GVNetId.clear(); - _netId2Name.clear(); - _netName2Id.clear(); - _idRo2Ppi.clear(); - _idRo2Ri.clear(); - _idRi2Ro.clear(); - _id2Type.clear(); - // fanout info - _id2Fanout.clear(); - // flag - _miscList.clear(); - _globalMisc = 0; // Initial misc value = 0; - // file type - _fileType = 0; -} - -// ---------------------------------------------------------------------- -// print GV network -// ---------------------------------------------------------------------- -// recursively print the gia network -void -GVNtkMgr::print_rec(Gia_Man_t* pGia, Gia_Obj_t* pObj) { - // if the TravId of the node is equal to the global TravId, return - if (Gia_ObjIsTravIdCurrent(pGia, pObj)) { - return; - } - - // set the TravId of the node to be the same as the global TravId, that is - // mark it as traversed - Gia_ObjSetTravIdCurrent(pGia, pObj); - - // If we reach the combinational input(PI + RO (register output, or pseudo - // PI)), return - if (Gia_ObjIsCi(pObj)) { - return; - } - - /* AIG node: #fanin = 2 */ - if (Gia_ObjFaninNum(pGia, pObj) > 1) { - // create a new GVNetId corresponding to abc's id - GVNetId id = - GVNetId::makeNetId(Gia_ObjId(pGia, pObj), 0, GV_NTK_OBJ_AIG); - // map - _id2Type[id.id] = id.type; - // fanin phase - id.fanin0Cp = Gia_ObjFaninC0(pObj); - id.fanin1Cp = Gia_ObjFaninC1(pObj); - createNet(id, GV_NTK_OBJ_AIG); - - /* if fanin id is RO, replace it with PPI */ - // fanin 0 - if (_fileType == GV_NTK_TYPE_V) { - if (getTypeFromId(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))) == - GV_NTK_OBJ_RO) { - _id2FaninId[Gia_ObjId(pGia, pObj)].push_back( - getPpiIdFromRoId(Gia_ObjId(pGia, Gia_ObjFanin0(pObj)))); - GVFanout fanout; - fanout.id = Gia_ObjId(pGia, pObj); - fanout.fanin = 0; - _id2Fanout[getPpiIdFromRoId(Gia_ObjId(pGia, - Gia_ObjFanin0(pObj)))] - .push_back(fanout); - } else { - _id2FaninId[Gia_ObjId(pGia, pObj)].push_back( - Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); - GVFanout fanout; - fanout.id = Gia_ObjId(pGia, pObj); - fanout.fanin = 0; - _id2Fanout[Gia_ObjId(pGia, Gia_ObjFanin0(pObj))].push_back(fanout); - } - } - if (_fileType == GV_NTK_TYPE_AIG) { - _id2FaninId[Gia_ObjId(pGia, pObj)].push_back( - Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); - GVFanout fanout; - fanout.id = Gia_ObjId(pGia, pObj); - fanout.fanin = 0; - _id2Fanout[Gia_ObjId(pGia, Gia_ObjFanin0(pObj))].push_back(fanout); - } - // recursive traverse its left child - print_rec(pGia, Gia_ObjFanin0(pObj)); - - // fanin 1 - if (_fileType == GV_NTK_TYPE_V) { - if (getTypeFromId(Gia_ObjId(pGia, Gia_ObjFanin1(pObj))) == - GV_NTK_OBJ_RO) { - _id2FaninId[Gia_ObjId(pGia, pObj)].push_back( - getPpiIdFromRoId(Gia_ObjId(pGia, Gia_ObjFanin1(pObj)))); - GVFanout fanout; - fanout.id = Gia_ObjId(pGia, pObj); - fanout.fanin = 1; - _id2Fanout[getPpiIdFromRoId(Gia_ObjId(pGia, - Gia_ObjFanin1(pObj)))] - .push_back(fanout); - } else { - _id2FaninId[Gia_ObjId(pGia, pObj)].push_back( - Gia_ObjId(pGia, Gia_ObjFanin1(pObj))); - GVFanout fanout; - fanout.id = Gia_ObjId(pGia, pObj); - fanout.fanin = 1; - _id2Fanout[Gia_ObjId(pGia, Gia_ObjFanin1(pObj))].push_back(fanout); - } - } - if (_fileType == GV_NTK_TYPE_AIG) { - _id2FaninId[Gia_ObjId(pGia, pObj)].push_back( - Gia_ObjId(pGia, Gia_ObjFanin1(pObj))); - } - print_rec(pGia, Gia_ObjFanin1(pObj)); - } - /* PO and RI: #fanin = 1 */ - else if (Gia_ObjFaninNum(pGia, pObj) == 1) { - // fanin 0 - if (_fileType == GV_NTK_TYPE_V) { - if (getTypeFromId(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))) == - GV_NTK_OBJ_RO) { - _id2FaninId[Gia_ObjId(pGia, pObj)].push_back( - getPpiIdFromRoId(Gia_ObjId(pGia, Gia_ObjFanin0(pObj)))); - GVFanout fanout; - fanout.id = Gia_ObjId(pGia, pObj); - fanout.fanin = 0; - _id2Fanout[getPpiIdFromRoId(Gia_ObjId(pGia, - Gia_ObjFanin0(pObj)))] - .push_back(fanout); - - } else { - _id2FaninId[Gia_ObjId(pGia, pObj)].push_back( - Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); - GVFanout fanout; - fanout.id = Gia_ObjId(pGia, pObj); - fanout.fanin = 0; - _id2Fanout[Gia_ObjId(pGia, Gia_ObjFanin0(pObj))].push_back(fanout); - } - } - if (_fileType == GV_NTK_TYPE_AIG) { - _id2FaninId[Gia_ObjId(pGia, pObj)].push_back( - Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); - GVFanout fanout; - fanout.id = Gia_ObjId(pGia, pObj); - fanout.fanin = 0; - _id2Fanout[Gia_ObjId(pGia, Gia_ObjFanin0(pObj))].push_back(fanout); - } - // fanin phase - _id2GVNetId[Gia_ObjId(pGia, pObj)].fanin0Cp = Gia_ObjFaninC0(pObj); - - // recursive traverse its left child - print_rec(pGia, Gia_ObjFanin0(pObj)); - } -} - -// ---------------------------------------------------------------------- -// construct GV network -// ---------------------------------------------------------------------- -void -GVNtkMgr::createNet(const GVNetId& id, const int net_type) { - // assert(!isGVNetInverted(id)); - if (net_type == GV_NTK_OBJ_PI) { - _InputList.push_back(id); - } else if (net_type == GV_NTK_OBJ_PO) { - _OutputList.push_back(id); - } else if (net_type == GV_NTK_OBJ_FF_CS) { - _FFList.push_back(id); - } else { // AIG node - _id2GVNetId[id.id] = id; - } - return; -} - -void -GVNtkMgr::createNetFromAbc(char* pFileName) { - Gia_Man_t* pGia = NULL; // the gia pointer of abc - Gia_Obj_t *pObj, *pObjRi, *pObjRo; // the obj element of gia - - // abc function parameters - char* pTopModule = - NULL; // the top module can be auto detected by yosys, no need to set - char* pDefines = NULL; - int fBlast = 1; // blast the ntk to gia (abc's aig data structure) - int fInvert = 0; - int fTechMap = 1; - int fSkipStrash = 0; - int fCollapse = 0; - int c, fVerbose = 1; // set verbose to 1 to see which yosys command is used - int i, *pWire; - - // read and blast the RTL verilog file into gia - if (_fileType == GV_NTK_TYPE_V) { - pGia = Wln_BlastSystemVerilog(pFileName, pTopModule, pDefines, - fSkipStrash, fInvert, fTechMap, fVerbose); - } else if (_fileType == GV_NTK_TYPE_AIG) { - cout << "reading file" << endl; - pGia = Gia_AigerRead(pFileName, 0, fSkipStrash, 0); - cout << "reading file end" << endl; - } else { - cout << "Error type!!!!!!" << endl; - assert(false); - } - - // increment the global travel id for circuit traversing usage - Gia_ManIncrementTravId(pGia); - // since we don't want to traverse the constant node, set the TravId of the - // constant node to be as the global one - Gia_ObjSetTravIdCurrent(pGia, Gia_ManConst0(pGia)); - // create the PI and PPI - if (_fileType == GV_NTK_TYPE_V) { - Gia_ManForEachPi(pGia, pObj, i) { - // cout << "fff " << i << endl; - // PI - if (i <= (Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia))) { - // create a new GVNetId corresponding to abc's id - GVNetId id = - GVNetId::makeNetId(Gia_ObjId(pGia, pObj), 0, GV_NTK_OBJ_PI); - createNet(id, GV_NTK_OBJ_PI); - // map - _id2GVNetId[id.id] = id; - _id2Type[id.id] = id.type; - } - // PPI - else { - // create a new GVNetId corresponding to abc's id - GVNetId id = GVNetId::makeNetId(Gia_ObjId(pGia, pObj), 0, - GV_NTK_OBJ_FF_CS); - createNet(id, GV_NTK_OBJ_FF_CS); - // map - _id2GVNetId[id.id] = id; - _id2Type[id.id] = id.type; - } - } - } else if (_fileType == GV_NTK_TYPE_AIG) { - Gia_ManForEachPi(pGia, pObj, i) { - // cout << "fff " << i << endl; - // PI - // if (i <= (Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia))) { - // create a new GVNetId corresponding to abc's id - GVNetId id = - GVNetId::makeNetId(Gia_ObjId(pGia, pObj), 0, GV_NTK_OBJ_PI); - createNet(id, GV_NTK_OBJ_PI); - // map - _id2GVNetId[id.id] = id; - _id2Type[id.id] = id.type; - // } - // // PPI - // else { - // // create a new GVNetId corresponding to abc's id - // GVNetId id = GVNetId::makeNetId(Gia_ObjId(pGia, pObj), 0, - // GV_NTK_OBJ_FF_CS); - // createNet(id, GV_NTK_OBJ_FF_CS); - // // map - // _id2GVNetId[id.id] = id; - // _id2Type[id.id] = id.type; - // } - } - } - - // create the PO - Gia_ManForEachPo(pGia, pObj, i) { - // create a new GVNetId corresponding to abc's id - GVNetId id = - GVNetId::makeNetId(Gia_ObjId(pGia, pObj), 0, GV_NTK_OBJ_PO); - createNet(id, GV_NTK_OBJ_PO); - // map - _id2GVNetId[id.id] = id; - _id2Type[id.id] = id.type; - } - - // create the RI (register input, D in FF) - bool hasConst = false; - Gia_ManForEachRi(pGia, pObj, i) { - // create a new GVNetId corresponding to abc's id - GVNetId id = - GVNetId::makeNetId(Gia_ObjId(pGia, pObj), 0, GV_NTK_OBJ_FF_NS); - createNet(id, GV_NTK_OBJ_FF_NS); - // map - _id2GVNetId[id.id] = id; - _id2Type[id.id] = id.type; - if (_fileType == GV_NTK_TYPE_V) { - // the last FF is used to connect const0 - if (i == Gia_ManRegNum(pGia) - 1) { - // FF - _FFConst0List.push_back(id); - // create a new GVNetId for const 0 - GVNetId id_const0 = GVNetId::makeNetId(Gia_ObjId(pGia, Gia_ObjFanin0(pObj)), 0, GV_NTK_OBJ_CONST0); - createNet(id_const0, GV_NTK_OBJ_CONST0); - _ConstList.push_back(id_const0); - // map - _id2GVNetId[id_const0.id] = id_const0; - _id2Type[id_const0.id] = id_const0.type; - } - } - if (_fileType == GV_NTK_TYPE_AIG) { - // the last FF is used to connect const0 - // if (Gia_ObjId(pGia, Gia_ObjFanin0(pObj)) == 0) { - // hasConst = true; - // // FF - // _FFConst0List.push_back(id); - // // create a new GVNetId for const 0 - // GVNetId id_const0 = GVNetId::makeNetId( - // Gia_ObjId(pGia, Gia_ObjFanin0(pObj)), 0, GV_NTK_OBJ_CONST0); - // createNet(id_const0, GV_NTK_OBJ_CONST0); - // _ConstList.push_back(id_const0); - // // map - // _id2GVNetId[id_const0.id] = id_const0; - // _id2Type[id_const0.id] = id_const0.type; - // } - } - // if(!hasConst) { - // create a new GVNetId for const 0 - GVNetId id_const0 = GVNetId::makeNetId(0, 0, GV_NTK_OBJ_CONST0); - createNet(id_const0, GV_NTK_OBJ_CONST0); - _ConstList.push_back(id_const0); - // map - _id2GVNetId[id_const0.id] = id_const0; - _id2Type[id_const0.id] = id_const0.type; - // } - } - - // create the RO (register output, Q in FF) - GVNetId id; - Gia_ManForEachRo(pGia, pObj, i) { - // create a new GVNetId corresponding to abc's id - if (_fileType == GV_NTK_TYPE_V) { - id = - GVNetId::makeNetId(Gia_ObjId(pGia, pObj), 0, GV_NTK_OBJ_RO); - } - if (_fileType == GV_NTK_TYPE_AIG) { - id = - GVNetId::makeNetId(Gia_ObjId(pGia, pObj), 0, GV_NTK_OBJ_FF_CS); - } - // map - _id2GVNetId[id.id] = id; - _id2Type[id.id] = id.type; - // debug - if (_fileType == GV_NTK_TYPE_AIG) { - createNet(id, GV_NTK_OBJ_FF_CS); - } - // the last FF is used to connect const0 - if (_fileType == GV_NTK_TYPE_V) { - if (i < Gia_ManRegNum(pGia) - 1) { - _idRo2Ppi[id.id] = getFF(i).id; - } - } - } - - // map RI and RO - Gia_ManForEachRiRo(pGia, pObjRi, pObjRo, i) { - // map - _idRo2Ri[Gia_ObjId(pGia, pObjRo)] = Gia_ObjId(pGia, pObjRi); - _idRi2Ro[Gia_ObjId(pGia, pObjRi)] = Gia_ObjId(pGia, pObjRo); - // the last FF is used to connect const0 (skip) - if (i < Gia_ManRegNum(pGia)) { - if (_fileType == GV_NTK_TYPE_V) { - _id2FaninId[getPpiIdFromRoId(Gia_ObjId(pGia, pObjRo))].push_back( - Gia_ObjId(pGia, pObjRi)); - } - else if (_fileType == GV_NTK_TYPE_AIG) { - _id2FaninId[Gia_ObjId(pGia, pObjRo)].push_back( - Gia_ObjId(pGia, pObjRi)); - } - } - } - - // dfs traverse from each combinational output PO (primary output) and - // RI (register input, which can be viewed as pseudo PO) - Gia_ManForEachCo(pGia, pObj, i) { - print_rec(pGia, pObj); - } - - // propagate the bubble of Co's - Gia_ManForEachCo(pGia, pObj, i) { - _id2GVNetId[getFaninId(Gia_ObjId(pGia, pObj))[0]].cp ^= _id2GVNetId[Gia_ObjId(pGia, pObj)].fanin0Cp; - } - - // construct the net id/name mapping - if (_fileType == GV_NTK_TYPE_V) { - parseAigMapping(pGia); - } -} - -string -netName(string name, int bit) { - return name + "[" + to_string(bit) + "]"; -} - -// ---------------------------------------------------------------------- -// parse the aig mapping from the ".map.txt" file -// ---------------------------------------------------------------------- -void -GVNtkMgr::parseAigMapping(Gia_Man_t* pGia) { - string buffer; - ifstream mapFile; - int idx, bit; - string name; - - mapFile.open(".map.txt"); - assert(mapFile.is_open()); - while (mapFile) { - if (!(mapFile >> buffer)) break; - // input - if (buffer == "input") { - mapFile >> buffer; - myStr2Int(buffer, idx); - mapFile >> buffer; - myStr2Int(buffer, bit); - mapFile >> buffer; - name = buffer; - _netId2Name[Gia_ObjId(pGia, Gia_ManPi(pGia, idx))] = - netName(name, bit); - _netName2Id[netName(name, bit)] = - Gia_ObjId(pGia, Gia_ManPi(pGia, idx)); - } - // output - else if (buffer == "output") { - mapFile >> buffer; - myStr2Int(buffer, idx); - mapFile >> buffer; - myStr2Int(buffer, bit); - mapFile >> buffer; - name = buffer; - _netId2Name[Gia_ObjId(pGia, Gia_ManPo(pGia, idx))] = - netName(name, bit); - _netName2Id[netName(name, bit)] = - Gia_ObjId(pGia, Gia_ManPo(pGia, idx)); - } - // FF - else if (buffer == "latch") { - mapFile >> buffer; - myStr2Int(buffer, idx); - mapFile >> buffer; - myStr2Int(buffer, bit); - mapFile >> buffer; - name = buffer; - _netId2Name[Gia_ObjId(pGia, - Gia_ObjRiToRo(pGia, Gia_ManRi(pGia, idx)))] = - netName(name, bit); - _netName2Id[netName(name, bit)] = - Gia_ObjId(pGia, Gia_ObjRiToRo(pGia, Gia_ManRi(pGia, idx))); - _netId2Name[Gia_ObjId(pGia, Gia_ManRi(pGia, idx))] = - netName(name, bit) + "_ns"; - _netName2Id[netName(name, bit) + "_ns"] = - Gia_ObjId(pGia, Gia_ManRi(pGia, idx)); - } - } -} - -// ---------------------------------------------------------------------- -// print the information of all PI's -// ---------------------------------------------------------------------- -void -GVNtkMgr::printPi() { - cout << "\nPI :" << endl; - for (unsigned i = 0; i < getInputSize(); i++) { - // if (getNetNameFromId(getInput(i).id).length() != 0) - cout << "PI #" << setw(5) << i << " : net name = " << setw(20) - << getNetNameFromId(getInput(i).id) << " net id = " << setw(10) - << getInput(i).id << endl; - } -} - -// ---------------------------------------------------------------------- -// print the information of all PO's -// ---------------------------------------------------------------------- -void -GVNtkMgr::printPo() { - cout << "\nPO :" << endl; - for (unsigned i = 0; i < getOutputSize(); i++) { - cout << "PO #" << setw(5) << i << " : net name = " << setw(20) - << getNetNameFromId(getOutput(i).id) << " net id = " << setw(10) - << getOutput(i).id << endl; - } -} - -// ---------------------------------------------------------------------- -// print the information of all RI's -// ---------------------------------------------------------------------- -void -GVNtkMgr::printRi() { - cout << "\nFF :" << endl; - for (unsigned i = 0; i < getFFSize(); i++) { - cout << "FF #" << setw(5) << i << " : net name = " << setw(20) - << getNetNameFromId(getFF(i).id) << " net id = " << setw(10) - << getFF(i).id << endl; - } -} - -// ---------------------------------------------------------------------- -// print the information of all Obj in the aig ntk -// ---------------------------------------------------------------------- -void -GVNtkMgr::printSummary() { - // iterate through the net ids - for (auto obj : _id2GVNetId) { - cout << "net " << setw(7) << obj.first; - // if it has fanin - if (_id2FaninId.find(obj.first) != _id2FaninId.end()) { - cout << " , fanin0 = " << setw(7) << _id2FaninId[obj.first][0]; - // if it has the second fanin - if (_id2FaninId[obj.first].size() >= 2) - cout << setw(7) << " , fanin1 = " << _id2FaninId[obj.first][1]; - // cout << endl; - } else if (getGateType(getGVNetId(obj.first)) == GV_NTK_OBJ_PI) { - cout << " , PI, No fanin."; - } else if (getGateType(getGVNetId(obj.first)) == GV_NTK_OBJ_RO) { - cout << " , RO, No fanin. (Please also note that RO is overlapped " - "with PI, so no BDD " - "node is created.)"; - } - if (_id2Fanout.find(obj.first) != _id2Fanout.end()) { - for (int i = 0; i < _id2Fanout[obj.first].size(); ++i) { - cout << setw(7) << " fanout = " << setw(7) - << _id2Fanout[obj.first][i].id << "'s fanin" - << _id2Fanout[obj.first][i].fanin; - } - cout << endl; - } else { - cout << endl; - } - } -} -// ---------------------------------------------------------------------- -// create the new net -// ---------------------------------------------------------------------- -GVNetId -GVNtkMgr::createNet() { - GVNetId id = GVNetId::makeNetId(getNetSize()); - createNet(id, GV_NTK_OBJ_AIG); - return id; -} - -bool -GVNtkMgr::createGVAndGate(GVNetId& id, GVNetId id1, GVNetId id2) { - id.type = GV_NTK_OBJ_AIG; - // Modification for complement - id.fanin0Cp = id1.cp; - id.fanin1Cp = id2.cp; - _id2Type[id.id] = id.type; - vector faninIdList; - faninIdList.push_back(id1.id); - faninIdList.push_back(id2.id); - _id2FaninId[id.id] = faninIdList; - // Update the complement info - createNet(id, GV_NTK_OBJ_AIG); - return true; -} diff --git a/src/ntk/gvNtk.h b/src/ntk/gvNtk.h deleted file mode 100644 index bda9c6a9..00000000 --- a/src/ntk/gvNtk.h +++ /dev/null @@ -1,265 +0,0 @@ -/**************************************************************************** - FileName [ gvNtk.h ] - PackageName [ gv/src/ntk ] - Synopsis [ GV Network ] - Author [ ] - Copyright [ ] ->>>>>>> e49dc0e73d18f38a26c685cf95dad078bf400c08 -****************************************************************************/ - -#ifndef GV_NTK_H -#define GV_NTK_H -#include "gvAbcMgr.h" -#include "kernel/sigtools.h" // Sigmap -#include "kernel/utils.h" // Toposort -#include "kernel/yosys.h" -#include -#include - -USING_YOSYS_NAMESPACE - -// GV Ntk defines -#define isGVNetInverted(netId) (netId.cp) -#define getGVNetIndex(netId) (netId.id) - -// constant -const unsigned GVNtkUD = UINT_MAX; -// declaration -class GVNtkMgr; -extern GVNtkMgr* gvNtkMgr; - -// object types -typedef enum -{ - GV_NTK_OBJ_NONE, // 0: non-existent object - GV_NTK_OBJ_CONST0, // 1: constant 0 - GV_NTK_OBJ_CONST1, // 2: constant 1 - GV_NTK_OBJ_PI, // 3: primary input - GV_NTK_OBJ_PO, // 4: primary output - GV_NTK_OBJ_BUF, // 5: buffer node - GV_NTK_OBJ_AND, // 6: AND node - GV_NTK_OBJ_RO, // 7: Register Output - GV_NTK_OBJ_FF_CS, // 8: Flip Flop Current State - GV_NTK_OBJ_FF_NS, // 9: Flip Flop Next State - GV_NTK_OBJ_NOT, // 10: NOT node - GV_NTK_OBJ_LAST, // 11: last element of the type - GV_NTK_OBJ_AIG // 12: AIG node -} GV_Ntk_Type_t; - -typedef enum -{ - GV_NTK_TYPE_V, // 0: verilog - GV_NTK_TYPE_AIG, // 1: aig - GV_NTK_TYPE_BLIF, // 2: blif - GV_NTK_TYPE_BTOR // 3: btor -} GV_Ntk_Format_t; - -/* - _ _ _ _ _ _ _ _ _ _ _ _ _ _ - | | - (PI) ---------> | | ---------> (PO) - (PPI) .------------> | Combinational Network | -------------> (PPO) - | .---------> | | ----------> | - | | |_ _ _ _ _ _ _ _ _ _ _ _ _ _| | | - | | | | - | | _ _ _ _ _ _ _ _ _ _ | | - | <-------------- | | <-------------. | - | | Flip Flop (FF) | | - (RO=Q) <----------------- |_ _ _ _ _ _ _ _ _ _| <----------------. (RI=D) - (X: current state) (Y: next state) - -*/ - -//---------------------------------------------------------------------- -// GV Ntk Defines -//---------------------------------------------------------------------- -struct GVNetId { - unsigned cp : 1; - unsigned id : 31; - bool fanin0Cp; // fanin 0 is complement - bool fanin1Cp; // fanin 1 is complement - GV_Ntk_Type_t type : GV_NTK_OBJ_AIG; - static GVNetId makeNetId(unsigned i = GVNtkUD, unsigned c = 0, GV_Ntk_Type_t t = GV_NTK_OBJ_AIG, - bool f0cp = false, bool f1cp = false) { - GVNetId j; - j.cp = c; - j.id = i; - j.type = t; - j.fanin0Cp = f0cp; - j.fanin1Cp = f1cp; - return j; - } - GVNetId operator~() const { return makeNetId(id, cp ^ 1); } - const bool operator==(const GVNetId& i) const { return cp == i.cp && id == i.id; } - const bool operator!=(const GVNetId& i) const { return !(*this == i); } -}; - -// fanout info -struct GVFanout { - unsigned id; // the id of the fanout obj - unsigned fanin; // record which fanin is the obj -}; - -class GVNtkMgr -{ - public: - // ------------------------------------------------------------------------- - // Information - // ------------------------------------------------------------------------- - // Constructors for BV Network - GVNtkMgr() { reset(); }; - ~GVNtkMgr() { reset(); } - // get size - inline const uint32_t getNetSize() const { return _id2GVNetId.size(); } - inline const unsigned getInputSize() const { return _InputList.size(); } - inline const unsigned getOutputSize() const { return _OutputList.size(); } - inline const unsigned getInoutSize() const { return _InoutList.size(); } - inline const uint32_t getFFSize() const { return _FFList.size(); } - inline const uint32_t getConstSize() const { return _ConstList.size(); } - inline const uint32_t getFFConst0Size() const { return _FFConst0List.size(); } - // access function - inline const GVNetId& getInput(const unsigned& i) const { - assert(i < getInputSize()); - return _InputList[i]; - } - inline const GVNetId& getOutput(const unsigned& i) const { - assert(i < getOutputSize()); - return _OutputList[i]; - } - inline const GVNetId& getInout(const unsigned& i) const { - assert(i < getInoutSize()); - return _InoutList[i]; - } - inline const GVNetId& getFF(const unsigned& i) const { - assert(i < getFFSize()); - return _FFList[i]; - } - inline const GVNetId& getConst(const unsigned& i) const { - assert(i < getConstSize()); - return _ConstList[i]; - } - inline const GVNetId& getFFConst0(const unsigned& i) const { - assert(i < getFFConst0Size()); - return _FFConst0List[i]; - } - // GV net id - inline const GVNetId& getGVNetId(const unsigned& i) const { return _id2GVNetId.at(i); } - // GV gate type - inline const GV_Ntk_Type_t getGateType(const GVNetId& id) { return id.type; } - inline GV_Ntk_Type_t& getTypeFromId(const unsigned& i) { return _id2Type[i]; } - // fanin - inline const vector& getFaninId(const unsigned& i) const { return _id2FaninId.at(i); } - inline const bool hasFanout(const unsigned& i) const { return _id2Fanout.count(i); } - inline const vector& getFanout(const unsigned& i) const { return _id2Fanout.at(i); } - inline const GVNetId& getInputNetId(const GVNetId&, const uint32_t&) const; - // flag - inline void newMiscData() { - if (getNetSize() > _miscList.size()) { - _miscList.resize(getNetSize()); - } - ++_globalMisc; - } - inline bool isLatestMiscData(const GVNetId& id) const { return _globalMisc == _miscList[id.id]; } - inline void setLatestMiscData(const GVNetId& id) { _miscList[id.id] = _globalMisc; } - // mapping (get id) - inline unsigned getNetIdFromName(string name) { return _netName2Id[name]; } - inline unsigned getPpiIdFromRoId(unsigned id) { return _idRo2Ppi[id]; } - inline unsigned getRiIdFromRoId(unsigned id) { return _idRo2Ri[id]; } - inline unsigned getRoIdFromRiId(unsigned id) { return _idRi2Ro[id]; } - // mapping (get name) - inline string getNetNameFromId(unsigned id) { return _netId2Name[id]; } - - // ------------------------------------------------------------------------- - // Network - // ------------------------------------------------------------------------- - // construct ntk - void createNet(const GVNetId& id, const int net_type); - void createNetFromAbc(char*); - void parseAigMapping(Gia_Man_t* pGia); - void setFileType(unsigned type) { _fileType = type; }; - unsigned getFileType() { return _fileType; }; - // print ntk - void print_rec(Gia_Man_t* pGia, Gia_Obj_t* pObj); - // print functions - void printPi(); // print the information of all PI's - void printPo(); // print the information of all PO's - void printRi(); // print the information of all RI's - void printSummary(); // print the information of all Obj in the aig ntk - // generate net - GVNetId createNet(); - bool createGVAndGate(GVNetId&, GVNetId, GVNetId); - // ------------------------------------------------------------------------- - // BDD - // ------------------------------------------------------------------------- - // build the BDD - const bool setBddOrder(const bool&); - void buildNtkBdd(); - void buildBdd(const GVNetId& netId); - // DFS tranversal - void dfsOrder(const GVNetId&, vector&); - - protected: - // info - vector _InputList; // GVNetId of PI's - vector _OutputList; // GVNetId of PO's - vector _InoutList; // GVNetId of Inout's - vector _FFList; // GVNetId of Flip Flops (current state) - vector _ConstList; // GVNetId of Constants (const0) - vector _FFConst0List; // GVNetId of FF that stores const0 - // map - map> _id2FaninId; - map _id2GVNetId; - map _netId2Name; - map _netName2Id; - map _idRo2Ppi; // PPI: pseudo PI - map _idRo2Ri; // RO: register output (Q) - map _idRi2Ro; // RI: register input (D) - map _id2Type; - map> _id2Fanout; - // flag - vector _miscList; // global misc date list - unsigned _globalMisc; // global misc data for GVNetId in network - // file type - unsigned _fileType; - private: - void reset(); -}; - -// Inline function implementation -inline const GVNetId& -GVNtkMgr::getInputNetId(const GVNetId& id, const uint32_t& i) const { - unsigned faninId = getFaninId(id.id)[i]; - return getGVNetId(faninId); -} - -//---------------------------------------------------------------------- -// Forward Declarations -//---------------------------------------------------------------------- -class GVRTLDesign; - -//---------------------------------------------------------------------- -// Global Variables -//---------------------------------------------------------------------- -extern GVRTLDesign* gvRTLDesign; - -//---------------------------------------------------------------------- -// Data Structure : yosys -//---------------------------------------------------------------------- -class GVRTLDesign -{ - public: - // Constructors for GV RTL Design Instance - GVRTLDesign() {} - ~GVRTLDesign(); - - // Ntk Reference Functions - RTLIL::Design* getDesign() { return yosys_design; } - - private: -}; - -//---------------------------------------------------------------------- -// Inline Functions -//---------------------------------------------------------------------- - -#endif diff --git a/src/ntk/gvNtkBdd.cpp b/src/ntk/gvNtkBdd.cpp deleted file mode 100644 index dd4ade24..00000000 --- a/src/ntk/gvNtkBdd.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/**************************************************************************** - FileName [ v3NtkBdd.cpp ] - PackageName [ v3/src/ntk ] - Synopsis [ V3 Network to BDDs. ] - Author [ Cheng-Yin Wu ] - Copyright [ Copyright(c) 2012-present LaDs(III), GIEE, NTU, Taiwan ] -****************************************************************************/ - -#ifndef V3_NTK_C -#define V3_NTK_C - -#include "bddMgrV.h" // MODIFICATION FOR SoCV BDD -#include "bddNodeV.h" // MODIFICATION FOR SoCV BDD -#include "gvMsg.h" -#include "gvNtk.h" -#include "stack" -#include "util.h" - -extern BddMgrV* bddMgrV; // MODIFICATION FOR SoCV BDD - -const bool -GVNtkMgr::setBddOrder(const bool& file) { - unsigned supportSize = getInputSize() + getInoutSize() + 2 * getFFSize(); - unsigned bddspsize = bddMgrV->getNumSupports(); - if (supportSize >= bddMgrV->getNumSupports()) { - gvMsg(GV_MSG_ERR) - << "BDD Support Size is Smaller Than Current Design Required !!" - << endl; - return false; - } - // build support - unsigned supportId = 1; - // build PI (primary input) - for (unsigned i = 0, n = getInputSize(); i < n; ++i) { - GVNetId nId = (file) ? getInput(i) : getInput(n - i - 1); - string netName = getNetNameFromId(nId.id); - bddMgrV->addBddNodeV(nId.id, bddMgrV->getSupport(supportId)()); - bddMgrV->addBddNodeV(netName, bddMgrV->getSupport(supportId)()); - cout << " Name : " << netName << "-> Id : " << nId.id << endl; - cout << "Support Id : " << supportId << "\n\n"; - cout << " --- \n"; - ++supportId; - } - // build InOut (Not use) - for (unsigned i = 0, n = getInoutSize(); i < n; ++i) { - const GVNetId& nId = (file) ? getInout(i) : getInout(n - i - 1); - string netName = getNetNameFromId(nId.id); - bddMgrV->addBddNodeV(nId.id, bddMgrV->getSupport(supportId)()); - bddMgrV->addBddNodeV(netName, bddMgrV->getSupport(supportId)()); - ++supportId; - } - // build FF_CS (X: current state) - for (unsigned i = 0, n = getFFSize(); i < n; ++i) { - const GVNetId& nId = (file) ? getFF(i) : getFF(n - i - 1); - string netName = getNetNameFromId(nId.id); - bddMgrV->addBddNodeV(nId.id, bddMgrV->getSupport(supportId)()); - bddMgrV->addBddNodeV(netName, bddMgrV->getSupport(supportId)()); - // cout << " Name : " << netName << "-> Id : " << nId.id << endl; - // cout << "Support Id : " << supportId << "\n\n"; - // cout << " --- \n"; - ++supportId; - } - // build FF_NS (Y: next state) - // here we only create "CS_name + _ns" for y_i - for (unsigned i = 0, n = getFFSize(); i < n; ++i) { - const GVNetId& nId = (file) ? getFF(i) : getFF(n - i - 1); - GVNetId ri = getInputNetId(nId, 0); // get RI - string netName = getNetNameFromId(ri.id); - bddMgrV->addBddNodeV(netName, bddMgrV->getSupport(supportId)()); - ++supportId; - } - // Constants (const0 node, id=0) - for (uint32_t i = 0; i < getConstSize(); ++i) { - assert(getGateType(getConst(i)) == GV_NTK_OBJ_CONST0); - bddMgrV->addBddNodeV(getConst(i).id, BddNodeV::_zero()); - ++supportId; - } - // FF that stores const0 (take as const0 node) - for (uint32_t i = 0; i < getFFConst0Size(); ++i) { - assert(getGateType(getFFConst0(i)) == GV_NTK_OBJ_FF_NS); - bddMgrV->addBddNodeV(getFFConst0(i).id, BddNodeV::_zero()); - bddMgrV->addBddNodeV(getRoIdFromRiId(getFFConst0(i).id), - BddNodeV::_zero()); - ++supportId; - } - - return true; -} - -void -GVNtkMgr::buildNtkBdd() { - // TODO: build BDD for ntk here - // Perform DFS traversal from DFF inputs, inout, and output gates. - // Collect ordered nets to a GVNetVec - // Construct BDDs in the DFS order - - // build PO - stack s; - for (unsigned i = 0; i < getOutputSize(); ++i) { - s.push(getOutput(i)); - } - while (s.size() > 0) { - buildBdd(s.top()); - s.pop(); - } - - // build next state (RI) - for (unsigned i = 0; i < getFFSize(); ++i) { - GVNetId left = getInputNetId(getFF(i), 0); // get RI - if (bddMgrV->getBddNodeV(left.id) == (size_t)0) { - buildBdd(left); - } - BddNodeV ns = ((left.fanin0Cp) ? ~bddMgrV->getBddNodeV(left.id) - : bddMgrV->getBddNodeV(left.id)); - } -} - -void -GVNtkMgr::buildBdd(const GVNetId& netId) { - vector orderedNets; - - orderedNets.clear(); - orderedNets.reserve(getNetSize()); - - // set flag for DFS - newMiscData(); - dfsOrder(netId, orderedNets); - assert(orderedNets.size() <= getNetSize()); - - // TODO: build BDD for the specified net here - GVNetId left, right; - for (unsigned i = 0; i < orderedNets.size(); ++i) { - if (getGateType(orderedNets[i]) == GV_NTK_OBJ_AIG) { - // build fanin0 - left = getInputNetId(orderedNets[i], 0); - // build fanin1 - right = getInputNetId(orderedNets[i], 1); - if (bddMgrV->getBddNodeV(left.id) == (size_t)0) { - buildBdd(left); - } - if (bddMgrV->getBddNodeV(right.id) == (size_t)0) { - buildBdd(right); - } - BddNodeV newNode = - ((orderedNets[i].fanin0Cp) ? ~bddMgrV->getBddNodeV(left.id) - : bddMgrV->getBddNodeV(left.id)) & - ((orderedNets[i].fanin1Cp) ? ~bddMgrV->getBddNodeV(right.id) - : bddMgrV->getBddNodeV(right.id)); - bddMgrV->addBddNodeV(orderedNets[i].id, newNode()); - } - // PO, RI - else if ((getGateType(orderedNets[i]) == GV_NTK_OBJ_FF_NS) || - (getGateType(orderedNets[i]) == GV_NTK_OBJ_PO)) { - GVNetId fanin = getInputNetId(orderedNets[i], 0); - BddNodeV newNode = (orderedNets[i].fanin0Cp) - ? ~bddMgrV->getBddNodeV(fanin.id) - : bddMgrV->getBddNodeV(fanin.id); - bddMgrV->addBddNodeV(orderedNets[i].id, newNode()); - } - } -} - -// Put fanins of a net (id) into a vector (nets) in topological order -void -GVNtkMgr::dfsOrder(const GVNetId& id, vector& nets) { - if (isLatestMiscData(id)) return; - - setLatestMiscData(id); - // traverse fanin logics - const GV_Ntk_Type_t type = getGateType(id); - if ((type == GV_NTK_OBJ_FF_NS) || (type == GV_NTK_OBJ_PO)) { - dfsOrder(getInputNetId(id, 0), nets); - } else if (type == GV_NTK_OBJ_AIG) { - dfsOrder(getInputNetId(id, 0), nets); - dfsOrder(getInputNetId(id, 1), nets); - } - nets.push_back(id); // Record Order -} - -#endif \ No newline at end of file diff --git a/src/ntk/gvNtkCmd.cpp b/src/ntk/gvNtkCmd.cpp deleted file mode 100644 index 3a27e98b..00000000 --- a/src/ntk/gvNtkCmd.cpp +++ /dev/null @@ -1,728 +0,0 @@ -#ifndef GV_NTK_CMD_C -#define GV_NTK_CMD_C - -#include "gvNtkCmd.h" -#include "gvMsg.h" -#include "util.h" -#include -#include -#include - -#include "gvAbcMgr.h" -#include "gvModMgr.h" -#include "gvNtk.h" - -USING_YOSYS_NAMESPACE - -bool -initNtkCmd() { - if (gvNtkMgr) delete gvNtkMgr; - gvNtkMgr = new GVNtkMgr; - return (gvCmdMgr->regCmd("SEt Engine", 2, 1, new GVSetEngineCmd) && - gvCmdMgr->regCmd("REad Design", 2, 1, new GVReadDesignCmd) && - gvCmdMgr->regCmd("PRint Info", 2, 1, new GVPrintInfoCmd) && - gvCmdMgr->regCmd("FILE2 Aig", 4, 1, new GVFile2AigCmd) && - gvCmdMgr->regCmd("YOSYSCMD", 8, new GVYosysOriginalCmd) && - gvCmdMgr->regCmd("FILE2 BLIF", 4, 4, new GVFile2BlifCmd) && - gvCmdMgr->regCmd("WRite Aig", 2, 1, new GVWriteAigCmd) && - gvCmdMgr->regCmd("BLAst NTK", 3, 3, new GVBlastNtkCmd) && - gvCmdMgr->regCmd("PRInt Aig", 3, 1, new GVPrintAigCmd)); -} - -//---------------------------------------------------------------------- -// SEt Engine <(string engineName)> -//---------------------------------------------------------------------- - -GVCmdExecStatus -GVSetEngineCmd ::exec(const string& option) { - gvMsg(GV_MSG_IFO) << "I am GVSetEngineCmd" << endl; - - vector options; - GVCmdExec::lexOptions(option, options); - size_t n = options.size(); - - bool engABC = false, engYOSYS = false; - // try to match engine names - if (n == 0) - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, - "<(string engineName)>"); - else { - for (size_t i = 0; i < n; ++i) { - const string& token = options[i]; - if (myStrNCmp("yosys", token, 1) == 0) { - if (engABC | engYOSYS) - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, token); - engYOSYS = true; - continue; - } else if (myStrNCmp("abc", token, 1) == 0) { - if (engABC | engYOSYS) - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, token); - engABC = true; - continue; - } else { - if (!engABC && !engYOSYS) - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); - } - } - } - - // set current engine - if (engYOSYS) gvModMgr->setGVEngine(GV_MOD_ENGINE_YOSYS); - else if (engABC) gvModMgr->setGVEngine(GV_MOD_ENGINE_ABC); - - // print the successful message - int engPos = gvModMgr->getGVEngine(); - string engNameList[2] = {"yosys", "abc"}; - cout << "Set Engine \"" << engNameList[engPos] << "\" Success !!" << endl; - return GV_CMD_EXEC_DONE; -} - -void -GVSetEngineCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: SEt Engine <(string engineName)> " << endl; - gvMsg(GV_MSG_IFO) << "Param: <(string engineName)> : Name of the engine. " - "<(yosys) | (abc)>" - << endl; -} - -void -GVSetEngineCmd::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "SEt Engine: " - << "Set the specific engine to parse the design." << endl; -} - -//---------------------------------------------------------------------- -// REad Design <-Verilog | -Blif | -Aig | -btor> <(string fileName)> -//---------------------------------------------------------------------- - -GVCmdExecStatus -GVReadDesignCmd ::exec(const string& option) { - - // check option - vector options; - GVCmdExec::lexOptions(option, options); - - bool fileVerilog = false, fileBlif = false, fileAig = false, - fileBtor = false; - size_t n = options.size(); - string filename, topName; - - // try to match file type options - if (n == 0) fileVerilog = true; - else { - for (size_t i = 0; i < n; ++i) { - const string& token = options[i]; - if (myStrNCmp("-Verilog", token, 2) == 0) { - if (fileVerilog | fileBlif | fileAig | fileBtor) - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, token); - fileVerilog = true; - continue; - } else if (myStrNCmp("-Blif", token, 3) == 0) { - if (fileVerilog | fileBlif | fileAig | fileBtor) - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, token); - fileBlif = true; - continue; - } else if (myStrNCmp("-Aig", token, 2) == 0) { - if (fileVerilog | fileBlif | fileAig | fileBtor) - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, token); - fileAig = true; - continue; - } else if (myStrNCmp("-Btor", token, 3) == 0) { - if (fileVerilog | fileBlif | fileAig | fileBtor) - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, token); - fileBtor = true; - continue; - } else { - if (!fileVerilog && !fileBlif && !fileAig && !fileBtor) - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); - - if (filename == "") filename = token; - else return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, token); - continue; - } - } - } - // check filename - if (filename == "") - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, - "<(string filename)>"); - - // check file extension - if (fileVerilog) { - gvNtkMgr->setFileType(GV_NTK_TYPE_V); - string fileExt = filename.substr(filename.size() - 2, 2); - if (fileExt != ".v") - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, filename); - } else if (fileBlif) { - gvNtkMgr->setFileType(GV_NTK_TYPE_BLIF); - string fileExt = filename.substr(filename.size() - 5, 5); - if (fileExt != ".blif") - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, filename); - } else if (fileAig) { - gvNtkMgr->setFileType(GV_NTK_TYPE_AIG); - string fileExt = filename.substr(filename.size() - 4, 4); - if (fileExt != ".aig") - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, filename); - // set the aig file name - gvModMgr->setAigFileName(filename); - } else if (fileBtor) { - gvNtkMgr->setFileType(GV_NTK_TYPE_BTOR); - string fileExt = filename.substr(filename.size() - 5, 5); - if (fileExt != ".btor") - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, filename); - } - - // print the input file name - cout << "\nfile name: " << filename << "\n"; - - // set input file name to Mode manager - gvModMgr->setInputFileName(filename); - gvModMgr->setInputFileExist(true); - GVModEngine currEng = gvModMgr->getGVEngine(); - - // read design - if (currEng == GV_MOD_ENGINE_YOSYS) { - if (fileAig | fileBtor) { - gvMsg(GV_MSG_IFO) << "[ERROR]: Engine yosys doesn't support aig " - "file and btor file !!" - << endl; - return GV_CMD_EXEC_NOP; - } - string yosCommand = ""; - if (fileVerilog) yosCommand += "read_verilog -sv "; - else if (fileBlif) yosCommand += "read_blif "; - run_pass(yosCommand + filename); - run_pass("hierarchy -auto-top"); - if (gvRTLDesign->getDesign()->top_module()->name.str() != "") { - topName = gvRTLDesign->getDesign()->top_module()->name.str(); - gvModMgr->setTopModuleName(topName); - } - } else if (currEng == GV_MOD_ENGINE_ABC) { - abcMgr->abcReadDesign(filename); - } - - return GV_CMD_EXEC_DONE; -} - -void -GVReadDesignCmd ::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) - << "Usage: REad Design <-Verilog | -Blif | -Aig> <(string fileName)> " - << endl; -} - -void -GVReadDesignCmd ::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "REad Design: " - << "Read the Design." << endl; -} - -//---------------------------------------------------------------------- -// PRint Info [-Verbose] -//---------------------------------------------------------------------- - -GVCmdExecStatus -GVPrintInfoCmd ::exec(const string& option) { - gvMsg(GV_MSG_IFO) << "I am GVPrintInfoCmd" << endl; - - int numFF = 0, numPI = 0, numPO = 0, numPIO = 0, numConst = 0, numNet = 0; - int numMux = 0, numAnd = 0, numAdd = 0, numSub = 0, numMul = 0, numEq = 0, - numNot = 0, numLe = 0, numGe = 0; - bool verbose = false; - - // check options - vector options; - GVCmdExec::lexOptions(option, options); - size_t n = options.size(); - - // try to match options - for (size_t i = 0; i < n; ++i) { - const string& token = options[i]; - if (myStrNCmp("-Verbose", token, 2) == 0) { - verbose = true; - continue; - } else { - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); - } - } - - // print info - GVModEngine currEng = gvModMgr->getGVEngine(); - if (currEng == GV_MOD_ENGINE_YOSYS) { - gvMsg(GV_MSG_IFO) << "Modules in current design: "; - string moduleName = gvRTLDesign->getDesign()->top_module()->name.str(); - cout << moduleName << "(" - << GetSize(gvRTLDesign->getDesign()->top_module()->wires()) - << " wires, " - << GetSize(gvRTLDesign->getDesign()->top_module()->cells()) - << " cells)\n"; - for (auto wire : gvRTLDesign->getDesign()->top_module()->wires()) { - // string wire_name = log_id(wire->name); - if (wire->port_input) numPI++; - else if (wire->port_output) numPO++; - } - if (verbose) { - for (auto cell : gvRTLDesign->getDesign()->top_module()->cells()) { - if (cell->type.in(ID($mux))) numMux++; - else if (cell->type.in(ID($logic_and))) numAnd++; - else if (cell->type.in(ID($add))) numAdd++; - else if (cell->type.in(ID($sub))) numSub++; - else if (cell->type.in(ID($mul))) numMul++; - else if (cell->type.in(ID($eq))) numEq++; - else if (cell->type.in(ID($logic_not))) numNot++; - else if (cell->type.in(ID($lt))) numLe++; - else if (cell->type.in(ID($ge))) numGe++; - } - gvMsg(GV_MSG_IFO) - << "==================================================\n"; - gvMsg(GV_MSG_IFO) << " MUX" << setw(40) << numMux << "\n"; - gvMsg(GV_MSG_IFO) << " AND" << setw(40) << numAnd << "\n"; - gvMsg(GV_MSG_IFO) << " ADD" << setw(40) << numAdd << "\n"; - gvMsg(GV_MSG_IFO) << " SUB" << setw(40) << numSub << "\n"; - gvMsg(GV_MSG_IFO) << " MUL" << setw(40) << numMul << "\n"; - gvMsg(GV_MSG_IFO) << " EQ" << setw(41) << numEq << "\n"; - gvMsg(GV_MSG_IFO) << " NOT" << setw(40) << numNot << "\n"; - gvMsg(GV_MSG_IFO) << " LT" << setw(41) << numLe << "\n"; - gvMsg(GV_MSG_IFO) << " GE" << setw(41) << numGe << "\n"; - gvMsg(GV_MSG_IFO) - << "--------------------------------------------------\n"; - gvMsg(GV_MSG_IFO) << " PI" << setw(41) << numPI << "\n"; - gvMsg(GV_MSG_IFO) << " PO" << setw(41) << numPO << "\n"; - gvMsg(GV_MSG_IFO) - << "==================================================\n"; - } else - gvMsg(GV_MSG_IFO) << "#PI = " << numPI << ", #PO = " << numPO - << ", #PIO = " << numPIO << "\n"; - } else if (currEng == GV_MOD_ENGINE_ABC) { - (abcMgr->get_abcNtkMgr())->printSummary(); - return GV_CMD_EXEC_DONE; - } - return GV_CMD_EXEC_DONE; -} - -void -GVPrintInfoCmd ::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: PRint Info [-Verbose]" << endl; -} - -void -GVPrintInfoCmd ::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "PRint Info: " - << "Print circuit information extracted by our parser." - << endl; -} - -//------------------------------------------------------------------------------------------------------- -// FILE2 Aig < [-Verilog | -Blif] > -Input -TOP -// -Output .aig -//------------------------------------------------------------------------------------------------------- - -GVCmdExecStatus -GVFile2AigCmd ::exec(const string& option) { - gvMsg(GV_MSG_IFO) << "I am GVFile2AigCmd" << endl; - - string inname, topname, outname; - bool preInfile = false, preTop = false; - bool fileVerilog = false, fileBlif = false; - bool hasInfile = false, hasTop = false, hasOutfile = false; - - // filename exists - if (gvModMgr->getInputFileExist()) { - // input file - inname = gvModMgr->getInputFileName(); - preInfile = true; - hasInfile = true; - // top module - if (gvModMgr->getTopModuleName() != "") { - topname = gvModMgr->getTopModuleName(); - preTop = true; - hasTop = true; - } - } - - vector options; - GVCmdExec::lexOptions(option, options); - size_t n = options.size(); - - for (size_t i = 0; i < n; ++i) { - const string& token = options[i]; - if (myStrNCmp("-Verilog", token, 2) == 0) { - if (fileVerilog | fileBlif) { - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, token); - } - fileVerilog = true; - continue; - } else if (myStrNCmp("-Blif", token, 3) == 0) { - if (fileVerilog | fileBlif) { - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, token); - } - fileBlif = true; - continue; - } else if ((!preInfile) && (myStrNCmp("-Input", token, 2) == 0)) { - // if no specify filename - if ((i + 1) >= n) { - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, token); - } else { - inname = options[i + 1]; - ++i; - } - gvModMgr->setInputFileName(inname); - gvModMgr->setInputFileExist(true); - hasInfile = true; - continue; - } else if ((!preTop) && (myStrNCmp("-TOP", token, 4) == 0)) { - // if no specify top module - if ((i + 1) >= n) { - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, token); - } else { - topname = options[i + 1]; - ++i; - } - gvModMgr->setTopModuleName(topname); - hasTop = true; - continue; - } else if (myStrNCmp("-Output", token, 2) == 0) { - // if no specify filename - if ((i + 1) >= n) { - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, token); - } else if (strncmp(options[i + 1] - .substr(options[i + 1].length() - 4, - options[i + 1].length()) - .c_str(), - ".aig", 4)) { - cout << "[ERROR]: Please output an \"AIG\" file " - "(.aig) !" - << endl; - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); - } else { - outname = options[i + 1]; - ++i; - } - hasOutfile = true; - continue; - } - } - - // command - string readCmd, topCmd, outCmd; - - if (!fileVerilog && !fileBlif) { - cout << "[ERROR]: Please specify input file format (-Verilog | -Blif) !" - << endl; - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, "FILE2 Aig"); - } else if (!hasInfile || !hasOutfile) { - cout << "[ERROR]: Please specify the file options !" << endl; - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, "FILE2 Aig"); - } else if (fileVerilog) { - if (!hasTop) { - cout << "[ERROR]: Please specify the top module name options !" - << endl; - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, "FILE2 Aig"); - } - if (!preTop) { - readCmd = "read_verilog -sv " + inname; - } - } else if (fileBlif) { - readCmd = "read_blif " + inname; - } - topCmd = "synth -flatten -top " + topname; - outCmd = "write_aiger -symbols " + outname; - - run_pass(readCmd); - run_pass(topCmd); - run_pass("dffunmap"); - run_pass("abc -g AND"); - run_pass(outCmd); - - return GV_CMD_EXEC_DONE; -} - -void -GVFile2AigCmd ::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) - << "Usage: FILE2 Aig <[-Verilog|-Blif]> -Input -TOP " - " -Output .aig " - << endl; -} - -void -GVFile2AigCmd ::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "File2 Aig: " - << "Convert verilog file into AIG. " << endl; -} - -//---------------------------------------------------------------------- -// YOSYSCMD -//---------------------------------------------------------------------- - -GVCmdExecStatus -GVYosysOriginalCmd ::exec(const string& option) { - vector options; - GVCmdExec::lexOptions(option, options); - size_t n = options.size(); - string command; - for (size_t i = 0; i < n; ++i) { - command += options[i]; - if (i < n - 1) { - command += " "; - } - } - // calling Yosys's command - if ((yosys_design->top_module() == NULL) && - (myStrNCmp("READ", command, 4)) == 0) { - cout << "Error: Please read in a design first !" << endl; - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, command); - } - - run_pass(command); - return GV_CMD_EXEC_DONE; -} - -void -GVYosysOriginalCmd ::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: YOSYSCMD " << endl; -} - -void -GVYosysOriginalCmd ::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "YosysCMD: " - << "Directly call Yosys's command." << endl; -} - -//---------------------------------------------------------------------- -// FILE2 Blif -//---------------------------------------------------------------------- -GVCmdExecStatus -GVFile2BlifCmd::exec(const string& option) { - gvMsg(GV_MSG_IFO) << "Create Blif from RTL " << endl; - - // gvMsg(GV_MSG_IFO) << "I am GVFile2AigCmd" << endl; - vector options; - GVCmdExec::lexOptions(option, options); - size_t n = options.size(); - if (n != 2) cout << "wrong arg number\n"; - string top = options[0]; - string outputf = options[1]; - cout << "top = " << top << " outputf = " << outputf << endl; - string command; - command = "hierarchy -top "; - command += top; - run_pass(command); - command = "hierarchy -check"; - run_pass(command); - command = "proc"; - run_pass(command); - command = "opt"; - run_pass(command); - command = "opt_expr -mux_undef"; - run_pass(command); - command = "opt"; - run_pass(command); - command = "rename -hide"; - run_pass(command); - command = "opt"; - run_pass(command); - command = "memory_collect"; - run_pass(command); - command = "flatten"; - run_pass(command); - command = "memory_unpack"; - run_pass(command); - command = "splitnets -driver"; - run_pass(command); - command = "setundef -zero -undriven"; - run_pass(command); - command = "dffunmap"; - run_pass(command); - command = "opt -fast -noff"; - run_pass(command); - command = "write_blif "; - command += outputf; - run_pass(command); - - return GV_CMD_EXEC_DONE; -} - -void -GVFile2BlifCmd ::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) - << "Usage: FILE2 Blif " - << endl; -} - -void -GVFile2BlifCmd ::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "File2 Blif: " - << "Convert verilog file into blif. " << endl; -} - -//---------------------------------------------------------------------- -// Write Aig -//---------------------------------------------------------------------- -GVCmdExecStatus -GVWriteAigCmd::exec(const string& option) { - - if (!gvRTLDesign->getDesign() || - gvRTLDesign->getDesign()->top_module() == NULL) { - gvMsg(GV_MSG_ERR) << "Empty design. Try command \"FILE2 AIG\"." << endl; - return GV_CMD_EXEC_ERROR; - } - - vector options; - GVCmdExec::lexOptions(option, options); - - if (options.size() > 1) { - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[1]); - } - - if (options.size() == 0) { - if (gvModMgr->getAigFileName() == "") { - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, "AIG filename"); - } - } - - else { - gvModMgr->setAigFileName(options[0]); - } - - string filename = options[0]; - - run_pass("synth -flatten -top " + gvModMgr->getTopModuleName()); - run_pass("dffunmap"); - run_pass("abc -g AND"); - run_pass("write_aiger -symbols " + filename); - - return GV_CMD_EXEC_DONE; -} - -void -GVWriteAigCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: WRite Aig " << endl; - gvMsg(GV_MSG_IFO) - << "Param: <(string filename)> : Name of the output aig file." - << endl; - gvMsg(GV_MSG_IFO) << " It could be , " - "or it can be skipped if specified before." - << endl; -} - -void -GVWriteAigCmd::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "WRite aig: " - << "Write out the processing design into AIGER file" - << endl; -} - -//---------------------------------------------------------------------- -// BLAst NTK (convert network to AIG) -//---------------------------------------------------------------------- - -GVCmdExecStatus -GVBlastNtkCmd ::exec(const string& option) { - vector options; - GVCmdExec::lexOptions(option, options); - size_t n = options.size(); - char* pFileName = new char[50]; // the file name is within 50 characters - - if (n > 0) { - gvMsg(GV_MSG_ERR) << "Usage: BLAst NTK" << endl; - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, option); - } - // filename exists - if (gvModMgr->getInputFileExist()) { - strcpy(pFileName, gvModMgr->getInputFileName().c_str()); - } else { - gvMsg(GV_MSG_ERR) << "Error: Please read in a design first !" << endl; - return GV_CMD_EXEC_ERROR; - } - - // create the PI, PO and FF mapping - if(gvNtkMgr->getFileType() == GV_NTK_TYPE_V) { - run_pass("hierarchy -auto-top; flatten; proc; techmap; setundef -zero; " - "aigmap; write_aiger -map .map.txt ._temp_.aig"); - } - else if(gvNtkMgr->getFileType() == GV_NTK_TYPE_AIG) { - run_pass("read_aiger " + gvModMgr->getInputFileName() + "; flatten; proc; techmap; setundef -zero; " - "aigmap; write_aiger -map .map.txt ._temp_.aig"); - } - - // construct GV network - gvNtkMgr->createNetFromAbc(pFileName); - - return GV_CMD_EXEC_DONE; -} - -void -GVBlastNtkCmd ::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: BLAst NTK" << endl; -} - -void -GVBlastNtkCmd ::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "BLAst NTK: " - << "Convert network to AIG." << endl; -} - -//---------------------------------------------------------------------- -// PRInt Aig (print the aig information) -//---------------------------------------------------------------------- -GVCmdExecStatus -GVPrintAigCmd ::exec(const string& option) { - vector options; - GVCmdExec::lexOptions(option, options); - size_t n = options.size(); - bool printPi = false, printPo = false, printRi = false, - printSummary = false; - - if (gvNtkMgr->getInputSize() == 0) { - gvMsg(GV_MSG_ERR) << "Please BLAst NTK first !" << endl; - return GV_CMD_EXEC_ERROR; - } - - if (n == 0) { - gvMsg(GV_MSG_ERR) - << "Usage: PRInt Aig <-PI | -PO | -RI | -RO | -Summary>" << endl; - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, option); - } else { - for (size_t i = 0; i < n; ++i) { - const string& token = options[i]; - if (myStrNCmp("-PI", token, 3) == 0) { - printPi = true; - continue; - } else if (myStrNCmp("-PO", token, 3) == 0) { - printPo = true; - continue; - } else if (myStrNCmp("-RI", token, 3) == 0) { - printRi = true; - continue; - } else if (myStrNCmp("-Summary", token, 2) == 0) { - printSummary = true; - continue; - } else { - if (!printPi && !printPo && !printRi && !printSummary) - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); - } - } - } - - if (printPi) gvNtkMgr->printPi(); - if (printPo) gvNtkMgr->printPo(); - if (printRi) gvNtkMgr->printRi(); - if (printSummary) gvNtkMgr->printSummary(); - - return GV_CMD_EXEC_DONE; -} - -void -GVPrintAigCmd ::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: PRInt Aig <-PI | -PO | -RI | -RO | -Summary>" - << endl; -} - -void -GVPrintAigCmd ::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "PRInt Aig: " - << "Print the aig network information." << endl; -} - -#endif diff --git a/src/ntk/gvNtkCmd.h b/src/ntk/gvNtkCmd.h deleted file mode 100644 index 2edc57ea..00000000 --- a/src/ntk/gvNtkCmd.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef GV_NTK_CMD_H -#define GV_NTK_CMD_H - -#include "gvCmdMgr.h" - -GV_COMMAND(GVSetEngineCmd, GV_CMD_TYPE_NETWORK); -GV_COMMAND(GVReadDesignCmd, GV_CMD_TYPE_NETWORK); -GV_COMMAND(GVPrintInfoCmd, GV_CMD_TYPE_NETWORK); -GV_COMMAND(GVFile2AigCmd, GV_CMD_TYPE_NETWORK); -GV_COMMAND(GVYosysOriginalCmd, GV_CMD_TYPE_NETWORK); -GV_COMMAND(GVFile2BlifCmd, GV_CMD_TYPE_NETWORK); -GV_COMMAND(GVWriteAigCmd, GV_CMD_TYPE_NETWORK); -GV_COMMAND(GVBlastNtkCmd, GV_CMD_TYPE_NETWORK); -GV_COMMAND(GVPrintAigCmd, GV_CMD_TYPE_NETWORK); - -#endif \ No newline at end of file diff --git a/src/prove/proveBdd.cpp b/src/prove/proveBdd.cpp index a2adc6de..e6ffbef1 100644 --- a/src/prove/proveBdd.cpp +++ b/src/prove/proveBdd.cpp @@ -8,7 +8,7 @@ #include "bddMgrV.h" #include "gvMsg.h" -#include "gvNtk.h" +// #include "gvNtk.h" #include "cirMgr.h" #include "cirGate.h" #include "util.h" @@ -40,7 +40,6 @@ BddMgrV::buildPTransRelation() { // TODO : remember to set _tr, _tri BddNodeV delta, y; - GVNetId delta_net; // build _tri for (unsigned i = 0; i < cirMgr->getNumLATCHs(); ++i) { diff --git a/src/prove/proveCmd.cpp b/src/prove/proveCmd.cpp index 6c23e9ad..41ae5263 100644 --- a/src/prove/proveCmd.cpp +++ b/src/prove/proveCmd.cpp @@ -7,19 +7,20 @@ ****************************************************************************/ #include "proveCmd.h" -#include "bddMgrV.h" -#include "gvMsg.h" -#include "gvNtk.h" -#include "util.h" + #include #include -#include "cirMgr.h" + +#include "bddMgrV.h" #include "cirGate.h" +#include "cirMgr.h" +#include "gvMsg.h" +// #include "gvNtk.h" +#include "util.h" using namespace std; -bool -initProveCmd() { +bool initProveCmd() { return (gvCmdMgr->regCmd("PINITialstate", 5, new PInitialStateCmd) && gvCmdMgr->regCmd("PTRansrelation", 3, new PTransRelationCmd) && gvCmdMgr->regCmd("PIMAGe", 5, new PImageCmd) && @@ -56,13 +57,11 @@ PInitialStateCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -PInitialStateCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: PINITialstate [(string varName)]" << endl; +void PInitialStateCmd::usage(const bool& verbose) const { + cout << "Usage: PINITialstate [(string varName)]" << endl; } -void -PInitialStateCmd::help() const { +void PInitialStateCmd::help() const { cout << setw(20) << left << "PINITialstate: " << "Set initial state BDD" << endl; } @@ -72,7 +71,7 @@ PInitialStateCmd::help() const { //---------------------------------------------------------------------- GVCmdExecStatus PTransRelationCmd::exec(const string& option) { - size_t op = 0; + size_t op = 0; vector options; GVCmdExec::lexOptions(option, options); if (options.size() > 2) @@ -106,14 +105,12 @@ PTransRelationCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -PTransRelationCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) +void PTransRelationCmd::usage(const bool& verbose) const { + cout << "Usage: PTRansrelation [(string triName)] [(stirng trName)]" << endl; } -void -PTransRelationCmd::help() const { +void PTransRelationCmd::help() const { cout << setw(20) << left << "PTRansrelation: " << "build the transition relationship in BDDs" << endl; } @@ -133,8 +130,8 @@ PImageCmd::exec(const string& option) { return GV_CMD_EXEC_ERROR; } - int level = 1; - string name; + int level = 1; + string name; vector options; GVCmdExec::lexOptions(option, options); @@ -158,15 +155,13 @@ PImageCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -PImageCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) +void PImageCmd::usage(const bool& verbose) const { + cout << "Usage: PIMAGe [-Next <(int numTimeframes)>] [(string varName)]" << endl; } -void -PImageCmd::help() const { +void PImageCmd::help() const { cout << setw(20) << left << "PIMAGe: " << "build the next state images in BDDs" << endl; } @@ -196,8 +191,7 @@ PCheckPropertyCmd::exec(const string& option) { else if (!myStrNCmp("-Output", options[0], 2)) isNet = false; else return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); - int num = 0; - GVNetId netId; + int num = 0; if (!myStr2Int(options[1], num) || (num < 0)) return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[1]); if (isNet) { @@ -226,15 +220,13 @@ PCheckPropertyCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -PCheckPropertyCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) +void PCheckPropertyCmd::usage(const bool& verbose) const { + cout << "Usage: PCHECKProperty < -Netid | -Output >" << endl; } -void -PCheckPropertyCmd::help() const { +void PCheckPropertyCmd::help() const { cout << setw(20) << left << "PCHECKProperty:" << "check the monitor by BDDs" << endl; } diff --git a/src/sim/gvSimCmd.cpp b/src/sim/gvSimCmd.cpp index c2aff854..087ae399 100644 --- a/src/sim/gvSimCmd.cpp +++ b/src/sim/gvSimCmd.cpp @@ -2,16 +2,18 @@ #define GV_SIM_CMD_C #include "gvSimCmd.h" + +#include +#include + #include "gvAbcMgr.h" #include "gvModMgr.h" #include "gvMsg.h" #include "util.h" -#include -#include +#include "kernel/yosys.h" +USING_YOSYS_NAMESPACE -#include "gvNtk.h" -bool -initSimCmd() { +bool initSimCmd() { return (gvCmdMgr->regCmd("RAndom Sim", 2, 1, new GVRandomSimCmd) && gvCmdMgr->regCmd("SEt SAfe", 2, 2, new GVRandomSetSafe) && gvCmdMgr->regCmd("SHow", 2, new GVShowCmd)); @@ -22,7 +24,7 @@ initSimCmd() { //---------------------------------------------------------------------- GVCmdExecStatus GVRandomSimCmd ::exec(const string& option) { - gvMsg(GV_MSG_IFO) << "I am GVRandomSimCmd " << endl; + cout << "I am GVRandomSimCmd " << endl; vector options; GVCmdExec::lexOptions(option, options); size_t n = options.size(); @@ -113,20 +115,18 @@ GVRandomSimCmd ::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -GVRandomSimCmd ::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) +void GVRandomSimCmd ::usage(const bool& verbose) const { + cout << "Usage: RAndom Sim <-input file_name.v> [sim_cycle num_cycle_sim] " "[-rst rst_name] [-rst_n rst_n_name] [-clk clk_name] " "[-output out_file_name] [-v verbose print result] [-file stimulus]" << endl; } -void -GVRandomSimCmd ::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "RAndom Sim: " - << "Conduct random simulation and print the results." - << endl; +void GVRandomSimCmd ::help() const { + cout << setw(20) << left << "RAndom Sim: " + << "Conduct random simulation and print the results." + << endl; } //---------------------------------------------------------------------- @@ -135,28 +135,26 @@ GVRandomSimCmd ::help() const { GVCmdExecStatus GVRandomSetSafe::exec(const string& option) { - gvMsg(GV_MSG_IFO) << "I am GVRandomSetSafe " << endl; + cout << "I am GVRandomSetSafe " << endl; vector options; GVCmdExec::lexOptions(option, options); if (options.size() != 1) { - gvMsg(GV_MSG_IFO) << "Please enter a valid value!" << endl; + cout << "Please enter a valid value!" << endl; return GV_CMD_EXEC_DONE; } gvModMgr->setSafe(stoi(options[0])); return GV_CMD_EXEC_DONE; } -void -GVRandomSetSafe::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: SEt SAfe <#PO>" << endl; +void GVRandomSetSafe::usage(const bool& verbose) const { + cout << "Usage: SEt SAfe <#PO>" << endl; } -void -GVRandomSetSafe::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "SEt SAfe: " - << "Set safe property for random simulation." << endl; +void GVRandomSetSafe::help() const { + cout << setw(20) << left << "SEt SAfe: " + << "Set safe property for random simulation." << endl; } //---------------------------------------------------------------------- @@ -164,12 +162,12 @@ GVRandomSetSafe::help() const { //---------------------------------------------------------------------- GVCmdExecStatus GVShowCmd::exec(const string& option) { - gvMsg(GV_MSG_IFO) << "I am GVSHowVCDCmd " << endl; + cout << "I am GVSHowVCDCmd " << endl; vector options; GVCmdExec::lexOptions(option, options); - size_t n = options.size(); - bool inputFile = false, vcd = false, schematic = false; + size_t n = options.size(); + bool inputFile = false, vcd = false, schematic = false; string vcd_file_name = ""; for (size_t i = 0; i < n; ++i) { @@ -195,7 +193,7 @@ GVShowCmd::exec(const string& option) { ifstream infile; infile.open(vcd_file_name); if (!infile.is_open()) { - gvMsg(GV_MSG_IFO) << "[ERROR]: Please input the VCD file name !!\n"; + cout << "[ERROR]: Please input the VCD file name !!\n"; return GV_CMD_EXEC_NOP; } else run_command("gtkwave " + vcd_file_name + " &"); @@ -203,12 +201,15 @@ GVShowCmd::exec(const string& option) { } else if (schematic) { // Problem!! --- (2) if (!gvModMgr->getInputFileExist()) { - gvMsg(GV_MSG_IFO) << "[ERROR]: Please use command \"READ DESIGN\" " - "to read the file first !!\n "; + cout << "[ERROR]: Please use command \"READ DESIGN\" " + "to read the file first !!\n "; return GV_CMD_EXEC_NOP; } + // string top_module_name = + // gvRTLDesign->getDesign()->top_module()->name.str().substr( + // 1, strlen(yosys_design->top_module()->name.c_str()) - 1); string top_module_name = - gvRTLDesign->getDesign()->top_module()->name.str().substr( + yosys_design->top_module()->name.str().substr( 1, strlen(yosys_design->top_module()->name.c_str()) - 1); run_pass("hierarchy -top " + top_module_name); @@ -219,16 +220,14 @@ GVShowCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -GVShowCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) +void GVShowCmd::usage(const bool& verbose) const { + cout << "Usage: SHow < -Vcd | -SCHematic >" << endl; } -void -GVShowCmd::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "SHow : " - << "Show the waveform or schematic." << endl; +void GVShowCmd::help() const { + cout << setw(20) << left << "SHow : " + << "Show the waveform or schematic." << endl; } #endif diff --git a/src/util/gvUsage.h b/src/util/gvUsage.h index 498e7f62..e1353e26 100644 --- a/src/util/gvUsage.h +++ b/src/util/gvUsage.h @@ -1,144 +1,175 @@ #ifndef GV_USAGE_H #define GV_USAGE_H -#include "gvMsg.h" -#include "gvIntType.h" +#include +#include +#include -#include #include #include #include +#include #include -#include -#include -#include +#include "gvIntType.h" +#include "gvMsg.h" -#undef MYCLK_TCK -#define MYCLK_TCK sysconf(_SC_CLK_TCK) + +#undef MYCLK_TCK +#define MYCLK_TCK sysconf(_SC_CLK_TCK) class GVUsage; class GVStat; extern GVUsage gvUsage; -class GVUsage -{ - public: - GVUsage() { - reset(); - } - void reset() { - _initMem = checkMem(); _peakMem = _totalMem = _currentMem = 0; - _currentTick = checkTick(); _periodUsedTime = _totalUsedTime = 0.0; - } - void report(const bool& repTime, const bool& repMem) { - if (repTime) { +class GVUsage { +public: + GVUsage() { + reset(); + } + void reset() { + _initMem = checkMem(); + _peakMem = _totalMem = _currentMem = 0; + _currentTick = checkTick(); + _periodUsedTime = _totalUsedTime = 0.0; + } + void report(const bool& repTime, const bool& repMem) { + if (repTime) { setTimeUsage(); - gvMsg(GV_MSG_IFO) << "Period time used : " << setprecision(4) << _periodUsedTime << " seconds" << endl; - gvMsg(GV_MSG_IFO) << "Total time used : " << setprecision(4) << _totalUsedTime << " seconds" << endl; - } - if (repMem) { + cout << "Period time used : " << setprecision(4) << _periodUsedTime << " seconds" << endl; + cout << "Total time used : " << setprecision(4) << _totalUsedTime << " seconds" << endl; + } + if (repMem) { setMemUsage(); - gvMsg(GV_MSG_IFO) << "Peak memory used : " << setprecision(4) << _peakMem << " M Bytes" << endl; - gvMsg(GV_MSG_IFO) << "Total memory used : " << setprecision(4) << _totalMem << " M Bytes" << endl; - gvMsg(GV_MSG_IFO) << "Current memory used: " << setprecision(4) << _currentMem << " M Bytes" << endl; - } - } - const double getMemUsage() { setMemUsage(); return _currentMem; } - private: - // Private Functions - const double checkMem() const { + cout << "Peak memory used : " << setprecision(4) << _peakMem << " M Bytes" << endl; + cout << "Total memory used : " << setprecision(4) << _totalMem << " M Bytes" << endl; + cout << "Current memory used: " << setprecision(4) << _currentMem << " M Bytes" << endl; + } + } + const double getMemUsage() { + setMemUsage(); + return _currentMem; + } + +private: + // Private Functions + const double checkMem() const { #if defined __linux__ - ifstream inf("/proc/self/status"); - if (!inf) { gvMsg(GV_MSG_ERR) << "Cannot get memory usage" << endl; return 0.0; } - const size_t bufSize = 128; - char bufStr[bufSize]; - while (!inf.eof()) { + ifstream inf("/proc/self/status"); + if (!inf) { + gvMsg(GV_MSG_ERR) << "Cannot get memory usage" << endl; + return 0.0; + } + const size_t bufSize = 128; + char bufStr[bufSize]; + while (!inf.eof()) { inf.getline(bufStr, bufSize); if (strncmp(bufStr, "VmSize", 6) == 0) { - long memSizeLong = atol(strchr(bufStr, ' ')); - return ((double)memSizeLong / 1024.0); + long memSizeLong = atol(strchr(bufStr, ' ')); + return ((double)memSizeLong / 1024.0); } - } + } #endif - return 0.0; - } - const double checkTick() const { - tms tBuffer; times(&tBuffer); - return tBuffer.tms_utime; - } - void setMemUsage() { - // Total Memory Usage - _totalMem = checkMem() - _initMem; _currentMem = 0; - // Peak Memory Usage - struct rusage rusage; getrusage(RUSAGE_SELF, &rusage); - _peakMem = (size_t)(rusage.ru_maxrss * 1024L) / 1048576.0; - // Current Memory Usage - unsigned long vsize; long rss; string ignore; - ifstream input("/proc/self/stat"); - input >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore - >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore - >> ignore >> ignore >> vsize >> rss; input.close(); - _currentMem = vsize / 1048576.0; //resident_set = rss * page_size_kb; - /* - FILE* file = fopen("/proc/self/statm", "r"); - if (file) { - long memory = 0; - if (1 == fscanf(file, "%*s%ld", &memory)) - _currentMem = (memory * sysconf(_SC_PAGESIZE)) / 1048576.0; - fclose(file); - } - */ - } - void setTimeUsage() { - double thisTick = checkTick(); - _periodUsedTime = (thisTick - _currentTick) / double(MYCLK_TCK); - _totalUsedTime += _periodUsedTime; _currentTick = thisTick; - } - // Memory usage - double _initMem; - double _peakMem; - double _totalMem; - double _currentMem; - // CPU time usage - double _currentTick; - double _periodUsedTime; - double _totalUsedTime; + return 0.0; + } + const double checkTick() const { + tms tBuffer; + times(&tBuffer); + return tBuffer.tms_utime; + } + void setMemUsage() { + // Total Memory Usage + _totalMem = checkMem() - _initMem; + _currentMem = 0; + // Peak Memory Usage + struct rusage rusage; + getrusage(RUSAGE_SELF, &rusage); + _peakMem = (size_t)(rusage.ru_maxrss * 1024L) / 1048576.0; + // Current Memory Usage + unsigned long vsize; + long rss; + string ignore; + ifstream input("/proc/self/stat"); + input >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> vsize >> rss; + input.close(); + _currentMem = vsize / 1048576.0; // resident_set = rss * page_size_kb; + /* + FILE* file = fopen("/proc/self/statm", "r"); + if (file) { + long memory = 0; + if (1 == fscanf(file, "%*s%ld", &memory)) + _currentMem = (memory * sysconf(_SC_PAGESIZE)) / 1048576.0; + fclose(file); + } + */ + } + void setTimeUsage() { + double thisTick = checkTick(); + _periodUsedTime = (thisTick - _currentTick) / double(MYCLK_TCK); + _totalUsedTime += _periodUsedTime; + _currentTick = thisTick; + } + // Memory usage + double _initMem; + double _peakMem; + double _totalMem; + double _currentMem; + // CPU time usage + double _currentTick; + double _periodUsedTime; + double _totalUsedTime; }; -class GVStat -{ - public : - // Constructor and Destructor - GVStat(const string& name, GVStat* const ref = 0) : _statName(name), _refStat(ref) { - _timeAccum = 0; _isStarted = 0; _numCalled = 0; - } - ~GVStat() {} - // Inline Member Functions - inline void start() { assert (!_isStarted); _startTime = clock(); ++_numCalled; _isStarted = 1; } - inline void end() { assert (_isStarted); _timeAccum += (clock() - _startTime) / CLOCKS_PER_SEC; _isStarted = 0; } - inline const uint32_t getNumCalled() const { assert (!_isStarted); return _numCalled; } - inline const double getAccumTime() const { assert (!_isStarted); return _timeAccum; } - inline const double getAvgTime() const { return getAccumTime() / (double)(getNumCalled()); } - inline const double getAccumToRef() const { return _refStat ? getAccumTime() / _refStat->getAccumTime() : 0; } - // Operator Overloads - friend ostream& operator << (ostream& os, const GVStat& stat) { - os << left << fixed << setw(20) << stat._statName << "[" - << "Avg Time = " << setprecision(5) << stat.getAvgTime() << "; " - << "Total Called = " << setprecision(8) << stat.getNumCalled() << ", " - << "Time = " << setprecision(6) << stat.getAccumTime(); - if (stat._refStat) os << " (" << setprecision(5) << (100.00 * stat.getAccumToRef()) << " %)"; - os << "]"; return os; - } - private : - // Private Members - const string _statName; - GVStat* const _refStat; - double _timeAccum; - double _startTime; - uint32_t _isStarted : 1; - uint32_t _numCalled : 31; +class GVStat { +public: + // Constructor and Destructor + GVStat(const string& name, GVStat* const ref = 0) : _statName(name), _refStat(ref) { + _timeAccum = 0; + _isStarted = 0; + _numCalled = 0; + } + ~GVStat() {} + // Inline Member Functions + inline void start() { + assert(!_isStarted); + _startTime = clock(); + ++_numCalled; + _isStarted = 1; + } + inline void end() { + assert(_isStarted); + _timeAccum += (clock() - _startTime) / CLOCKS_PER_SEC; + _isStarted = 0; + } + inline const uint32_t getNumCalled() const { + assert(!_isStarted); + return _numCalled; + } + inline const double getAccumTime() const { + assert(!_isStarted); + return _timeAccum; + } + inline const double getAvgTime() const { return getAccumTime() / (double)(getNumCalled()); } + inline const double getAccumToRef() const { return _refStat ? getAccumTime() / _refStat->getAccumTime() : 0; } + // Operator Overloads + friend ostream& operator<<(ostream& os, const GVStat& stat) { + os << left << fixed << setw(20) << stat._statName << "[" + << "Avg Time = " << setprecision(5) << stat.getAvgTime() << "; " + << "Total Called = " << setprecision(8) << stat.getNumCalled() << ", " + << "Time = " << setprecision(6) << stat.getAccumTime(); + if (stat._refStat) os << " (" << setprecision(5) << (100.00 * stat.getAccumToRef()) << " %)"; + os << "]"; + return os; + } + +private: + // Private Members + const string _statName; + GVStat* const _refStat; + double _timeAccum; + double _startTime; + uint32_t _isStarted : 1; + uint32_t _numCalled : 31; }; #endif - diff --git a/src/vrf/gvVrfCmd.cpp b/src/vrf/gvVrfCmd.cpp index c1175461..72bd703a 100644 --- a/src/vrf/gvVrfCmd.cpp +++ b/src/vrf/gvVrfCmd.cpp @@ -2,20 +2,23 @@ #define GV_VRF_CMD_C #include "gvVrfCmd.h" + +#include + +#include +#include +#include + #include "gvAbcMgr.h" +#include "gvModMgr.h" #include "gvMsg.h" #include "gvUsage.h" -#include "gvModMgr.h" #include "util.h" -#include -#include -#include -#include + using namespace std; -bool -initVrfCmd() { +bool initVrfCmd() { return (gvCmdMgr->regCmd("Formal Verify", 1, 1, new GVFormalVerifyCmd)); } @@ -25,29 +28,29 @@ initVrfCmd() { GVCmdExecStatus GVFormalVerifyCmd ::exec(const string& option) { - gvMsg(GV_MSG_IFO) << "I am GVFormalVerifyCmd " << endl; + cout << "I am GVFormalVerifyCmd " << endl; if (gvModMgr->getAigFileName() == "") { - gvMsg(GV_MSG_IFO) << "[ERROR]: Please use command \"READ DESIGN\" or \"VErilog2 Aig\" to read/make the aig file first !!\n"; + cout << "[ERROR]: Please use command \"READ DESIGN\" or \"VErilog2 Aig\" to read/make the aig file first !!\n"; return GV_CMD_EXEC_NOP; } bool bmc = false, pdr = false, itp = false, ind = false; // bmc - int bmc_depth, bmc_S, bmc_T, bmc_H, bmc_G, bmc_C, bmc_D, bmc_J, bmc_I, bmc_P, bmc_Q, bmc_R; + int bmc_depth, bmc_S, bmc_T, bmc_H, bmc_G, bmc_C, bmc_D, bmc_J, bmc_I, bmc_P, bmc_Q, bmc_R; string bmc_option, bmc_L, bmc_W; // k-induction - int PO_idx; - int ind_F, ind_P, ind_C, ind_M, ind_L, ind_N, ind_B; + int PO_idx; + int ind_F, ind_P, ind_C, ind_M, ind_L, ind_N, ind_B; string ind_option; // pdr - int pdr_M, pdr_F, pdr_C, pdr_D, pdr_Q, pdr_T, pdr_H, pdr_G, pdr_S; + int pdr_M, pdr_F, pdr_C, pdr_D, pdr_Q, pdr_T, pdr_H, pdr_G, pdr_S; string pdr_option, pdr_L, pdr_I; // itp - int itp_C, itp_F, itp_T, itp_K; + int itp_C, itp_F, itp_T, itp_K; string itp_option, itp_L, itp_I; - char fname[128]; + char fname[128]; vector options; GVCmdExec::lexOptions(option, options); @@ -464,7 +467,7 @@ GVFormalVerifyCmd ::exec(const string& option) { } // command - char Command[1024], inname[128], formal_option[1024]; + char Command[1024], inname[128], formal_option[1024]; string cmd = ""; string aigFileName = gvModMgr->getAigFileName(); strcpy(inname, aigFileName.c_str()); @@ -515,127 +518,123 @@ GVFormalVerifyCmd ::exec(const string& option) { return GV_CMD_EXEC_DONE; } -void -GVFormalVerifyCmd ::usage(const bool& verbose) const { +void GVFormalVerifyCmd ::usage(const bool& verbose) const { // ------------------------------------------------------------------------------------------------------------------------ // // BMC // ------------------------------------------------------------------------------------------------------------------------ // - gvMsg(GV_MSG_IFO) << "Usage: Formal Verify -bmc [-STHGCDJIPQR ] [-LW ] [-axdursgvz]" << endl; - gvMsg(GV_MSG_IFO) << "\t performs bounded model checking with dynamic unrolling" << endl; - gvMsg(GV_MSG_IFO) << "\t-S : the starting time frame" << endl; - gvMsg(GV_MSG_IFO) << "\t-T : runtime limit, in seconds" << endl; - gvMsg(GV_MSG_IFO) << "\t-H : runtime limit per output, in miliseconds (with \"-a\")" << endl; - gvMsg(GV_MSG_IFO) << "\t-G : runtime gap since the last CEX, in seconds" << endl; - gvMsg(GV_MSG_IFO) << "\t-C : max conflicts at an output" << endl; - gvMsg(GV_MSG_IFO) << "\t-D : max conflicts after jumping (0 = infinity)" << endl; - gvMsg(GV_MSG_IFO) << "\t-J : the number of timeframes to jump (0 = not used)" << endl; - gvMsg(GV_MSG_IFO) << "\t-I : the number of PIs to abstract" << endl; - gvMsg(GV_MSG_IFO) << "\t-P : the max number of learned clauses to keep (0=unused)" << endl; - gvMsg(GV_MSG_IFO) << "\t-Q : delta value for learned clause removal" << endl; - gvMsg(GV_MSG_IFO) << "\t-R : percentage to keep for learned clause removal" << endl; - gvMsg(GV_MSG_IFO) << "\t-L : the log file name" << endl; - gvMsg(GV_MSG_IFO) << "\t-W : the log file name with per-output details" << endl; - gvMsg(GV_MSG_IFO) << "\t-a : solve all outputs (do not stop when one is SAT)" << endl; - gvMsg(GV_MSG_IFO) << "\t-x : toggle storing CEXes when solving all outputs" << endl; - gvMsg(GV_MSG_IFO) << "\t-d : toggle dropping (replacing by 0) SAT outputs" << endl; - gvMsg(GV_MSG_IFO) << "\t-u : toggle performing structural OR-decomposition" << endl; - gvMsg(GV_MSG_IFO) << "\t-r : toggle disabling periodic restarts" << endl; - gvMsg(GV_MSG_IFO) << "\t-s : toggle using Satoko by Bruno Schmitt" << endl; - gvMsg(GV_MSG_IFO) << "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon" << endl; - gvMsg(GV_MSG_IFO) << "\t-v : toggle verbose output" << endl; - gvMsg(GV_MSG_IFO) << "\t-z : toggle suppressing report about solved outputs" << endl; + cout << "Usage: Formal Verify -bmc [-STHGCDJIPQR ] [-LW ] [-axdursgvz]" << endl; + cout << "\t performs bounded model checking with dynamic unrolling" << endl; + cout << "\t-S : the starting time frame" << endl; + cout << "\t-T : runtime limit, in seconds" << endl; + cout << "\t-H : runtime limit per output, in miliseconds (with \"-a\")" << endl; + cout << "\t-G : runtime gap since the last CEX, in seconds" << endl; + cout << "\t-C : max conflicts at an output" << endl; + cout << "\t-D : max conflicts after jumping (0 = infinity)" << endl; + cout << "\t-J : the number of timeframes to jump (0 = not used)" << endl; + cout << "\t-I : the number of PIs to abstract" << endl; + cout << "\t-P : the max number of learned clauses to keep (0=unused)" << endl; + cout << "\t-Q : delta value for learned clause removal" << endl; + cout << "\t-R : percentage to keep for learned clause removal" << endl; + cout << "\t-L : the log file name" << endl; + cout << "\t-W : the log file name with per-output details" << endl; + cout << "\t-a : solve all outputs (do not stop when one is SAT)" << endl; + cout << "\t-x : toggle storing CEXes when solving all outputs" << endl; + cout << "\t-d : toggle dropping (replacing by 0) SAT outputs" << endl; + cout << "\t-u : toggle performing structural OR-decomposition" << endl; + cout << "\t-r : toggle disabling periodic restarts" << endl; + cout << "\t-s : toggle using Satoko by Bruno Schmitt" << endl; + cout << "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon" << endl; + cout << "\t-v : toggle verbose output" << endl; + cout << "\t-z : toggle suppressing report about solved outputs" << endl; // ------------------------------------------------------------------------------------------------------------------------ // // k-induction // ------------------------------------------------------------------------------------------------------------------------ // - gvMsg(GV_MSG_IFO) << "\nUsage: Formal Verify -ind [-FPCMLNB num] [-sbrtv]" << endl; - gvMsg(GV_MSG_IFO) << "\t : K-step induction strengthened with cut properties to prove the property" << endl; - gvMsg(GV_MSG_IFO) << "\t : the order of specified PO (idx starts from 0)" << endl; - gvMsg(GV_MSG_IFO) << "\t-F num : number of time frames for induction (1=simple)" << endl; - gvMsg(GV_MSG_IFO) << "\t-P num : number of time frames in the prefix (0=no prefix)" << endl; - gvMsg(GV_MSG_IFO) << "\t-C num : the max number of clauses to use for strengthening" << endl; - gvMsg(GV_MSG_IFO) << "\t-M num : the cut size (2 <= M <= 12)" << endl; - gvMsg(GV_MSG_IFO) << "\t-L num : the max number of levels for cut computation" << endl; - gvMsg(GV_MSG_IFO) << "\t-N num : the max number of cuts to compute at a node" << endl; - gvMsg(GV_MSG_IFO) << "\t-B num : the max number of invariant batches to try" << endl; - gvMsg(GV_MSG_IFO) << "\t-s : toggle increment cut size in each batch" << endl; - gvMsg(GV_MSG_IFO) << "\t-b : toggle enabling BMC check" << endl; - gvMsg(GV_MSG_IFO) << "\t-r : toggle enabling register clauses" << endl; - gvMsg(GV_MSG_IFO) << "\t-t : toggle proving target / computing don't-cares" << endl; - gvMsg(GV_MSG_IFO) << "\t-v : toggle printing verbose information" << endl; + cout << "\nUsage: Formal Verify -ind [-FPCMLNB num] [-sbrtv]" << endl; + cout << "\t : K-step induction strengthened with cut properties to prove the property" << endl; + cout << "\t : the order of specified PO (idx starts from 0)" << endl; + cout << "\t-F num : number of time frames for induction (1=simple)" << endl; + cout << "\t-P num : number of time frames in the prefix (0=no prefix)" << endl; + cout << "\t-C num : the max number of clauses to use for strengthening" << endl; + cout << "\t-M num : the cut size (2 <= M <= 12)" << endl; + cout << "\t-L num : the max number of levels for cut computation" << endl; + cout << "\t-N num : the max number of cuts to compute at a node" << endl; + cout << "\t-B num : the max number of invariant batches to try" << endl; + cout << "\t-s : toggle increment cut size in each batch" << endl; + cout << "\t-b : toggle enabling BMC check" << endl; + cout << "\t-r : toggle enabling register clauses" << endl; + cout << "\t-t : toggle proving target / computing don't-cares" << endl; + cout << "\t-v : toggle printing verbose information" << endl; // ------------------------------------------------------------------------------------------------------------------------ // // PDR // ------------------------------------------------------------------------------------------------------------------------ // - gvMsg(GV_MSG_IFO) << "\nUsage: Formal Verify -pdr [-MFCDQTHGS ] [-LI ] [-axrmuyfqipdegjonctkvwz]" << endl; - gvMsg(GV_MSG_IFO) << "\t model checking using property directed reachability (aka IC3)" << endl; - gvMsg(GV_MSG_IFO) << "\t-M : limit on unused vars to trigger SAT solver recycling" << endl; - gvMsg(GV_MSG_IFO) << "\t-F : limit on timeframes explored to stop computation" << endl; - gvMsg(GV_MSG_IFO) << "\t-C : limit on conflicts in one SAT call (0 = no limit)" << endl; - gvMsg(GV_MSG_IFO) << "\t-D : limit on conflicts during ind-generalization (0 = no limit)" << endl; - gvMsg(GV_MSG_IFO) << "\t-Q : limit on proof obligations before a restart (0 = no limit)" << endl; - gvMsg(GV_MSG_IFO) << "\t-T : runtime limit, in seconds (0 = no limit)" << endl; - gvMsg(GV_MSG_IFO) << "\t-H : runtime limit per output, in miliseconds (with \"-a\")" << endl; - gvMsg(GV_MSG_IFO) << "\t-G : runtime gap since the last CEX (0 = no limit)" << endl; - gvMsg(GV_MSG_IFO) << "\t-S : * value to seed the SAT solver with" << endl; - gvMsg(GV_MSG_IFO) << "\t-L : the log file name" << endl; - gvMsg(GV_MSG_IFO) << "\t-I : the invariant file name" << endl; - gvMsg(GV_MSG_IFO) << "\t-a : toggle solving all outputs even if one of them is SAT" << endl; - gvMsg(GV_MSG_IFO) << "\t-x : toggle storing CEXes when solving all outputs" << endl; - gvMsg(GV_MSG_IFO) << "\t-r : toggle using more effort in generalization" << endl; - gvMsg(GV_MSG_IFO) << "\t-m : toggle using monolythic CNF computation" << endl; - gvMsg(GV_MSG_IFO) << "\t-u : toggle updated X-valued simulation" << endl; - gvMsg(GV_MSG_IFO) << "\t-y : toggle using structural flop priorities" << endl; - gvMsg(GV_MSG_IFO) << "\t-f : toggle ordering flops by cost before generalization" << endl; - gvMsg(GV_MSG_IFO) << "\t-q : toggle creating only shortest counter-examples" << endl; - gvMsg(GV_MSG_IFO) << "\t-i : toggle clause pushing from an intermediate timeframe" << endl; - gvMsg(GV_MSG_IFO) << "\t-p : toggle reusing proof-obligations in the last timeframe" << endl; - gvMsg(GV_MSG_IFO) << "\t-d : toggle dumping invariant (valid if init state is all-0)" << endl; - gvMsg(GV_MSG_IFO) << "\t-e : toggle using only support variables in the invariant" << endl; - gvMsg(GV_MSG_IFO) << "\t-g : toggle skipping expensive generalization step" << endl; - gvMsg(GV_MSG_IFO) << "\t-j : toggle using simplified generalization step" << endl; - gvMsg(GV_MSG_IFO) << "\t-o : toggle using property output as inductive hypothesis" << endl; - gvMsg(GV_MSG_IFO) << "\t-n : * toggle skipping \'down\' in generalization" << endl; - gvMsg(GV_MSG_IFO) << "\t-c : * toggle handling CTGs in \'down\'" << endl; - gvMsg(GV_MSG_IFO) << "\t-t : toggle using abstraction" << endl; - gvMsg(GV_MSG_IFO) << "\t-k : toggle using simplified refinement" << endl; - gvMsg(GV_MSG_IFO) << "\t-v : toggle printing optimization summary" << endl; - gvMsg(GV_MSG_IFO) << "\t-w : toggle printing detailed stats" << endl; - gvMsg(GV_MSG_IFO) << "\t-z : toggle suppressing report about solved outputs" << endl; + cout << "\nUsage: Formal Verify -pdr [-MFCDQTHGS ] [-LI ] [-axrmuyfqipdegjonctkvwz]" << endl; + cout << "\t model checking using property directed reachability (aka IC3)" << endl; + cout << "\t-M : limit on unused vars to trigger SAT solver recycling" << endl; + cout << "\t-F : limit on timeframes explored to stop computation" << endl; + cout << "\t-C : limit on conflicts in one SAT call (0 = no limit)" << endl; + cout << "\t-D : limit on conflicts during ind-generalization (0 = no limit)" << endl; + cout << "\t-Q : limit on proof obligations before a restart (0 = no limit)" << endl; + cout << "\t-T : runtime limit, in seconds (0 = no limit)" << endl; + cout << "\t-H : runtime limit per output, in miliseconds (with \"-a\")" << endl; + cout << "\t-G : runtime gap since the last CEX (0 = no limit)" << endl; + cout << "\t-S : * value to seed the SAT solver with" << endl; + cout << "\t-L : the log file name" << endl; + cout << "\t-I : the invariant file name" << endl; + cout << "\t-a : toggle solving all outputs even if one of them is SAT" << endl; + cout << "\t-x : toggle storing CEXes when solving all outputs" << endl; + cout << "\t-r : toggle using more effort in generalization" << endl; + cout << "\t-m : toggle using monolythic CNF computation" << endl; + cout << "\t-u : toggle updated X-valued simulation" << endl; + cout << "\t-y : toggle using structural flop priorities" << endl; + cout << "\t-f : toggle ordering flops by cost before generalization" << endl; + cout << "\t-q : toggle creating only shortest counter-examples" << endl; + cout << "\t-i : toggle clause pushing from an intermediate timeframe" << endl; + cout << "\t-p : toggle reusing proof-obligations in the last timeframe" << endl; + cout << "\t-d : toggle dumping invariant (valid if init state is all-0)" << endl; + cout << "\t-e : toggle using only support variables in the invariant" << endl; + cout << "\t-g : toggle skipping expensive generalization step" << endl; + cout << "\t-j : toggle using simplified generalization step" << endl; + cout << "\t-o : toggle using property output as inductive hypothesis" << endl; + cout << "\t-n : * toggle skipping \'down\' in generalization" << endl; + cout << "\t-c : * toggle handling CTGs in \'down\'" << endl; + cout << "\t-t : toggle using abstraction" << endl; + cout << "\t-k : toggle using simplified refinement" << endl; + cout << "\t-v : toggle printing optimization summary" << endl; + cout << "\t-w : toggle printing detailed stats" << endl; + cout << "\t-z : toggle suppressing report about solved outputs" << endl; // ------------------------------------------------------------------------------------------------------------------------ // // ITP // ------------------------------------------------------------------------------------------------------------------------ // - gvMsg(GV_MSG_IFO) << "\nUsage: Formal Verify -itp [-CFTK ] [-LI ] [-irtpomcgbqkdv]" << endl; - gvMsg(GV_MSG_IFO) << "\t uses interpolation to prove the property" << endl; - gvMsg(GV_MSG_IFO) << "\t-C : the limit on conflicts for one SAT run" << endl; - gvMsg(GV_MSG_IFO) << "\t-F : the limit on number of frames to unroll" << endl; - gvMsg(GV_MSG_IFO) << "\t-T : the limit on runtime per output in seconds" << endl; - gvMsg(GV_MSG_IFO) << "\t-K : the number of steps in inductive checking" << endl; - gvMsg(GV_MSG_IFO) << "\t (K = 1 works in all cases; K > 1 works without -t and -b)" << endl; - gvMsg(GV_MSG_IFO) << "\t-L : the log file name" << endl; - gvMsg(GV_MSG_IFO) << "\t-I : the file name for dumping interpolant" << endl; - gvMsg(GV_MSG_IFO) << "\t-i : toggle dumping interpolant/invariant into a file" << endl; - gvMsg(GV_MSG_IFO) << "\t-r : toggle rewriting of the unrolled timeframes" << endl; - gvMsg(GV_MSG_IFO) << "\t-t : toggle adding transition into the initial state" << endl; - gvMsg(GV_MSG_IFO) << "\t-p : toggle using original Pudlak's interpolation procedure" << endl; - gvMsg(GV_MSG_IFO) << "\t-o : toggle using optimized Pudlak's interpolation procedure" << endl; - gvMsg(GV_MSG_IFO) << "\t-m : toggle using MiniSat-1.14p (now, Windows-only)" << endl; - gvMsg(GV_MSG_IFO) << "\t-c : toggle using inductive containment check" << endl; - gvMsg(GV_MSG_IFO) << "\t-g : toggle using bias for global variables using SAT" << endl; - gvMsg(GV_MSG_IFO) << "\t-b : toggle using backward interpolation (works with -t)" << endl; - gvMsg(GV_MSG_IFO) << "\t-q : toggle using property in two last timeframes" << endl; - gvMsg(GV_MSG_IFO) << "\t-k : toggle solving each output separately" << endl; - gvMsg(GV_MSG_IFO) << "\t-d : toggle dropping (replacing by 0) SAT outputs (with -k is used)" << endl; - gvMsg(GV_MSG_IFO) << "\t-v : toggle verbose output" << endl; + cout << "\nUsage: Formal Verify -itp [-CFTK ] [-LI ] [-irtpomcgbqkdv]" << endl; + cout << "\t uses interpolation to prove the property" << endl; + cout << "\t-C : the limit on conflicts for one SAT run" << endl; + cout << "\t-F : the limit on number of frames to unroll" << endl; + cout << "\t-T : the limit on runtime per output in seconds" << endl; + cout << "\t-K : the number of steps in inductive checking" << endl; + cout << "\t (K = 1 works in all cases; K > 1 works without -t and -b)" << endl; + cout << "\t-L : the log file name" << endl; + cout << "\t-I : the file name for dumping interpolant" << endl; + cout << "\t-i : toggle dumping interpolant/invariant into a file" << endl; + cout << "\t-r : toggle rewriting of the unrolled timeframes" << endl; + cout << "\t-t : toggle adding transition into the initial state" << endl; + cout << "\t-p : toggle using original Pudlak's interpolation procedure" << endl; + cout << "\t-o : toggle using optimized Pudlak's interpolation procedure" << endl; + cout << "\t-m : toggle using MiniSat-1.14p (now, Windows-only)" << endl; + cout << "\t-c : toggle using inductive containment check" << endl; + cout << "\t-g : toggle using bias for global variables using SAT" << endl; + cout << "\t-b : toggle using backward interpolation (works with -t)" << endl; + cout << "\t-q : toggle using property in two last timeframes" << endl; + cout << "\t-k : toggle solving each output separately" << endl; + cout << "\t-d : toggle dropping (replacing by 0) SAT outputs (with -k is used)" << endl; + cout << "\t-v : toggle verbose output" << endl; } -void -GVFormalVerifyCmd ::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "Formal Verify: " - << "Use options to execute specific formal engine." << endl; +void GVFormalVerifyCmd ::help() const { + cout << setw(20) << left << "Formal Verify: " + << "Use options to execute specific formal engine." << endl; } - - #endif \ No newline at end of file diff --git a/src/yosys/gvYosysCmd.cpp b/src/yosys/gvYosysCmd.cpp index ff4ea6ee..510fb8d4 100644 --- a/src/yosys/gvYosysCmd.cpp +++ b/src/yosys/gvYosysCmd.cpp @@ -13,7 +13,8 @@ bool initYosysCmd() { if (yosysMgr) delete yosysMgr; - yosysMgr = new YosysMgr; yosysMgr->init(); + yosysMgr = new YosysMgr; + yosysMgr->init(); return (gvCmdMgr->regCmd("YSYSet", 4, new YosysSetCmd)); } @@ -30,7 +31,7 @@ GVCmdExecStatus YosysSetCmd::exec(const string& option) { bool doLog = false, isValid = false; int enable = 0; - size_t n = options.size(); + size_t n = options.size(); if (myStrNCmp("-LOG", options[0], 4) == 0) doLog = true; else @@ -48,12 +49,12 @@ GVCmdExecStatus YosysSetCmd::exec(const string& option) { } void YosysSetCmd::usage(const bool& verbose) const { - gvMsg(GV_MSG_IFO) << "Usage: YSYSet <-log (int enable)>" << endl; + cout << "Usage: YSYSet <-log (int enable)>" << endl; } void YosysSetCmd::help() const { - gvMsg(GV_MSG_IFO) << setw(20) << left << "YSYSet: " - << "Set the option of Yosys." << endl; + cout << setw(20) << left << "YSYSet: " + << "Set the option of Yosys." << endl; } #endif \ No newline at end of file diff --git a/src/yosys/gvYosysMgr.cpp b/src/yosys/gvYosysMgr.cpp index 1d425ddc..6ba83c09 100644 --- a/src/yosys/gvYosysMgr.cpp +++ b/src/yosys/gvYosysMgr.cpp @@ -20,12 +20,12 @@ void YosysMgr::setLogging(const bool& enable) { log_streams.pop_back(); } -void YosysMgr::buildMapping(const string& fileName) { - string yosys = "yosys -qp "; - string readVerilog = "read_verilog " + fileName + "; "; - string topModule = "hierarchy -auto-top; "; - string preProcess = "flatten; proc; techmap; setundef -zero; aigmap; "; +void YosysMgr::createMapping(const string& fileName) { + string yosys = "yosys -qp "; + string readVerilog = "read_verilog " + fileName + "; "; + string topModule = "hierarchy -auto-top; "; + string preProcess = "flatten; proc; techmap; setundef -zero; aigmap; "; string writeAigMapping = "write_aiger -map .map.txt ._temp_.aig"; - string command = yosys + "\"" + readVerilog + topModule + preProcess + writeAigMapping + "\""; + string command = yosys + "\"" + readVerilog + topModule + preProcess + writeAigMapping + "\""; system(command.c_str()); } diff --git a/src/yosys/gvYosysMgr.h b/src/yosys/gvYosysMgr.h index 26dd332a..cf5c9f54 100644 --- a/src/yosys/gvYosysMgr.h +++ b/src/yosys/gvYosysMgr.h @@ -18,7 +18,7 @@ class YosysMgr { void reset(); void setLogging(const bool& = false); - void buildMapping(const string& fileName); + void createMapping(const string& fileName); private: }; From ad32609b60d2aa72a1e984d3d1db8cf5646b0220 Mon Sep 17 00:00:00 2001 From: hchchiu Date: Tue, 12 Dec 2023 16:14:09 +0800 Subject: [PATCH 019/307] Move abc functions to abc manager --- .clang-format | 4 +- Makefile | 4 +- src/abc/.depend.mak | 52 ++--- src/abc/.extheader.mak | 17 +- src/abc/Makefile | 4 +- src/abc/abcCmd.cpp | 117 ++++++++++ src/abc/{gvAbcCmd.h => abcCmd.h} | 4 +- src/abc/{gvAbcMgr.cpp => abcMgr.cpp} | 115 +++++----- src/abc/{gvAbcMgr.h => abcMgr.h} | 16 +- src/abc/gvAbcCmd.cpp | 121 ---------- src/abc/gvAbcNtk.cpp | 202 ----------------- src/abc/gvAbcNtk.h | 39 ---- src/bdd/.depend.mak | 23 +- src/cir/.depend.mak | 182 ++++----------- src/cir/cirAig.cpp | 188 +++++----------- src/cir/cirMgr.h | 316 ++++++++++++++------------- src/cmd/.depend.mak | 2 +- src/gvsat/.depend.mak | 22 +- src/itp/.depend.mak | 62 ++---- src/main/.depend.mak | 2 +- src/mod/.depend.mak | 24 +- src/mod/gvModCmd.cpp | 2 +- src/prove/.depend.mak | 66 ++---- src/sim/.depend.mak | 26 ++- src/sim/gvSimCmd.cpp | 5 +- src/vrf/.depend.mak | 13 +- src/vrf/gvVrfCmd.cpp | 3 +- 27 files changed, 563 insertions(+), 1068 deletions(-) create mode 100644 src/abc/abcCmd.cpp rename src/abc/{gvAbcCmd.h => abcCmd.h} (52%) rename src/abc/{gvAbcMgr.cpp => abcMgr.cpp} (60%) rename src/abc/{gvAbcMgr.h => abcMgr.h} (66%) delete mode 100644 src/abc/gvAbcCmd.cpp delete mode 100644 src/abc/gvAbcNtk.cpp delete mode 100644 src/abc/gvAbcNtk.h diff --git a/.clang-format b/.clang-format index ae89c096..b8dfeb27 100644 --- a/.clang-format +++ b/.clang-format @@ -61,4 +61,6 @@ AlignConsecutiveShortCaseStatements: Enabled: true # Bin Pack # BinPackArguments: true -# BinPackParameters: true \ No newline at end of file +# BinPackParameters: true + +PackConstructorInitializers: BinPack diff --git a/Makefile b/Makefile index 533e04a0..956039fc 100755 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -SRCPKGS = util cmd mod abc yosys bdd itp cir sim vrf ext prove gvsat -LIBPKGS = util cmd mod abc yosys bdd itp cir sim vrf prove gvsat +SRCPKGS = util cmd abc mod yosys bdd itp cir sim vrf ext prove gvsat +LIBPKGS = util cmd abc mod yosys bdd itp cir sim vrf prove gvsat MAIN = main diff --git a/src/abc/.depend.mak b/src/abc/.depend.mak index 3db860d4..b6aa2c7f 100644 --- a/src/abc/.depend.mak +++ b/src/abc/.depend.mak @@ -1,4 +1,4 @@ -gvAbcCmd.o: gvAbcCmd.cpp gvAbcCmd.h ../../include/gvCmdMgr.h gvAbcMgr.h \ +abcCmd.o: abcCmd.cpp abcCmd.h ../../include/gvCmdMgr.h abcMgr.h \ ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ @@ -22,10 +22,15 @@ gvAbcCmd.o: gvAbcCmd.cpp gvAbcCmd.h ../../include/gvCmdMgr.h gvAbcMgr.h \ ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - gvAbcNtk.h ../../include/gvModMgr.h ../../include/gvCmdMgr.h \ - ../../include/gvMsg.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h -gvAbcMgr.o: gvAbcMgr.cpp gvAbcMgr.h ../../include/base/abc/abc.h \ + ../../include/cirGate.h ../../include/cirDef.h ../../include/myHash.h \ + ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirMgr.h \ + ../../include/base/abc/abc.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h ../../include/cirMgr.h ../../include/util.h \ + ../../include/rnGen.h ../../include/myUsage.h +abcMgr.o: abcMgr.cpp abcMgr.h ../../include/base/abc/abc.h \ ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ @@ -48,31 +53,14 @@ gvAbcMgr.o: gvAbcMgr.cpp gvAbcMgr.h ../../include/base/abc/abc.h \ ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - gvAbcNtk.h ../../include/bdd/cudd/cudd.h ../../include/bdd/mtr/mtr.h \ + ../../include/cirGate.h ../../include/cirDef.h ../../include/myHash.h \ + ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirMgr.h \ + ../../include/base/abc/abc.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h ../../include/cirMgr.h \ + ../../include/bdd/cudd/cudd.h ../../include/bdd/mtr/mtr.h \ ../../include/bdd/epd/epd.h ../../include/sat/cnf/cnf.h \ - ../../include/opt/dar/darInt.h ../../include/opt/dar/dar.h -gvAbcNtk.o: gvAbcNtk.cpp gvAbcNtk.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - ../../include/sat/cnf/cnf.h ../../include/opt/dar/darInt.h \ - ../../include/opt/dar/dar.h gvAbcMgr.h + ../../include/opt/dar/darInt.h ../../include/opt/dar/dar.h \ + ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/abc/.extheader.mak b/src/abc/.extheader.mak index dce52d3e..bd2e8c73 100644 --- a/src/abc/.extheader.mak +++ b/src/abc/.extheader.mak @@ -1,10 +1,7 @@ -abc.d: ../../include/gvAbcCmd.h ../../include/gvAbcMgr.h ../../include/gvAbcNtk.h -../../include/gvAbcCmd.h: gvAbcCmd.h - @rm -f ../../include/gvAbcCmd.h - @ln -fs ../src/abc/gvAbcCmd.h ../../include/gvAbcCmd.h -../../include/gvAbcMgr.h: gvAbcMgr.h - @rm -f ../../include/gvAbcMgr.h - @ln -fs ../src/abc/gvAbcMgr.h ../../include/gvAbcMgr.h -../../include/gvAbcNtk.h: gvAbcNtk.h - @rm -f ../../include/gvAbcNtk.h - @ln -fs ../src/abc/gvAbcNtk.h ../../include/gvAbcNtk.h +abc.d: ../../include/abcCmd.h ../../include/abcMgr.h +../../include/abcCmd.h: abcCmd.h + @rm -f ../../include/abcCmd.h + @ln -fs ../src/abc/abcCmd.h ../../include/abcCmd.h +../../include/abcMgr.h: abcMgr.h + @rm -f ../../include/abcMgr.h + @ln -fs ../src/abc/abcMgr.h ../../include/abcMgr.h diff --git a/src/abc/Makefile b/src/abc/Makefile index 2b09cdfe..5fe734df 100644 --- a/src/abc/Makefile +++ b/src/abc/Makefile @@ -1,5 +1,5 @@ PKGFLAG = $(DEBUG_FLAG) -EXTHDRS = gvAbcCmd.h gvAbcMgr.h gvAbcNtk.h +EXTHDRS = abcCmd.h abcMgr.h include ../Makefile.in -include ../Makefile.lib \ No newline at end of file +include ../Makefile.lib diff --git a/src/abc/abcCmd.cpp b/src/abc/abcCmd.cpp new file mode 100644 index 00000000..fac66a29 --- /dev/null +++ b/src/abc/abcCmd.cpp @@ -0,0 +1,117 @@ +#ifndef GV_ABC_CMD_C +#define GV_ABC_CMD_C + +#include "abcCmd.h" + +#include + +#include + +#include "abcMgr.h" +#include "util.h" + +bool initAbcCmd() { + if (abcMgr) delete abcMgr; + abcMgr = new AbcMgr; + return (gvCmdMgr->regCmd("ABCCMD", 6, new GVABCOriginalCmd)); +} + +//---------------------------------------------------------------------- +// ABCRead <(string filename)> +//---------------------------------------------------------------------- + +// GVCmdExecStatus +// GVABCReadCmd::exec(const string& option) { +// vector options; +// string fileName = ""; +// GVCmdExec::lexOptions(option, options); +// size_t n = options.size(); +// for (size_t i = 0; i < n; ++i) { +// const string& token = options[i]; +// if (fileName == "") +// fileName = options[i]; +// else +// return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); +// } +// if (fileName == "") +// return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, +// "<(string fileName)>"); +// abcMgr->abcReadDesign(fileName); +// return GV_CMD_EXEC_DONE; +// } +// +// void GVABCReadCmd::usage(const bool& verbose) const { +// cout << "Usage: ABCRead " << endl; +// } +// +// void GVABCReadCmd::help() const { +// cout << setw(20) << left << "ABCRead: " +// << "Read netlist by ABC." << endl; +// } + +//---------------------------------------------------------------------- +// ABCPrint [-Verbose] +//---------------------------------------------------------------------- + +// GVCmdExecStatus +// GVABCPrintCmd::exec(const string& option) { +// vector options; +// GVCmdExec::lexOptions(option, options); +// bool basic = false, verbose = false; +// size_t n = options.size(); +// +// if (options.size() > 1) +// return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[1]); +// else if (options.size()) { +// if (myStrNCmp("-Verbose", options[0], 2) == 0) +// verbose = true; +// else +// return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); +// } +// (abcMgr->get_abcNtkMgr())->printSummary(); +// return GV_CMD_EXEC_DONE; +// } +// +// void GVABCPrintCmd::usage(const bool& verbose) const { +// cout << "Usage: ABCPrint " << endl; +// } +// +// void GVABCPrintCmd::help() const { +// cout << setw(20) << left << "ABCPrint: " +// << "Print netlist information." << endl; +// } + +//---------------------------------------------------------------------- +// ABCCMD +//---------------------------------------------------------------------- + +GVCmdExecStatus +GVABCOriginalCmd::exec(const string& option) { + vector options; + GVCmdExec::lexOptions(option, options); + size_t n = options.size(); + string command; + for (size_t i = 0; i < n; ++i) { + command += options[i]; + if (i < n - 1) { + command += " "; + } + } + + // calling abc's command + char Command[1024], abcCmd[128]; + strcpy(abcCmd, command.c_str()); + sprintf(Command, "%s", abcCmd); + Cmd_CommandExecute(abcMgr->get_Abc_Frame_t(), Command); +} + +void GVABCOriginalCmd::usage(const bool& verbose) const { + cout << "Usage: ABCCMD " << endl; +} + +void GVABCOriginalCmd::help() const { + cout << setw(20) << left << "ABCCMD: " + << "Directly call ABC's command." << endl; +} + +#endif diff --git a/src/abc/gvAbcCmd.h b/src/abc/abcCmd.h similarity index 52% rename from src/abc/gvAbcCmd.h rename to src/abc/abcCmd.h index 68371f65..6efabb14 100644 --- a/src/abc/gvAbcCmd.h +++ b/src/abc/abcCmd.h @@ -3,8 +3,6 @@ #include "gvCmdMgr.h" -GV_COMMAND(GVABCReadCmd, GV_CMD_TYPE_ABC); -GV_COMMAND(GVABCPrintCmd, GV_CMD_TYPE_ABC); GV_COMMAND(GVABCOriginalCmd, GV_CMD_TYPE_ABC); -#endif \ No newline at end of file +#endif diff --git a/src/abc/gvAbcMgr.cpp b/src/abc/abcMgr.cpp similarity index 60% rename from src/abc/gvAbcMgr.cpp rename to src/abc/abcMgr.cpp index 8d8efd91..60f08860 100644 --- a/src/abc/gvAbcMgr.cpp +++ b/src/abc/abcMgr.cpp @@ -1,4 +1,4 @@ -#include "gvAbcMgr.h" +#include "abcMgr.h" #include #include @@ -8,9 +8,10 @@ #include "base/abc/abc.h" #include "bdd/cudd/cudd.h" -#include "cirMgr.h" #include "cirGate.h" -#include "gvAbcNtk.h" + +// #include "cirMgr.h" +#include "cirMgr.h" #include "sat/cnf/cnf.h" #include "util.h" @@ -20,6 +21,10 @@ AbcMgr::AbcMgr() : pGia(NULL) { init(); } +AbcMgr::~AbcMgr() { + reset(); +} + void AbcMgr::init() { Abc_Start(); pAbc = Abc_FrameGetGlobalFrame(); @@ -29,24 +34,13 @@ void AbcMgr::reset() { delete pAbc; } -void AbcMgr::abcReadDesign(string& fileName) { - char pFileName[128]; - strcpy(pFileName, fileName.c_str()); - char Command[1000]; - sprintf(Command, "read %s", pFileName); - Cmd_CommandExecute(pAbc, Command); - pNtkMgr = new abcNtkMgr(pAbc->pNtkCur); -} - void AbcMgr::readVerilog(const ABCParam& opt) { char* pFileName = opt.pFileName; char* pTopModule = opt.pTopModule; char* pDefines = opt.pDefines; - int fBlast = opt.fBlast; int fInvert = opt.fInvert; int fTechMap = opt.fTechMap; int fSkipStrash = opt.fSkipStrash; - int fCollapse = opt.fCollapse; int fVerbose = opt.fVerbose; pGia = Wln_BlastSystemVerilog(pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fVerbose); } @@ -72,13 +66,13 @@ void AbcMgr::buildAigName(map& id2Name) { mapFile.open(".map.txt"); assert(mapFile.is_open()); - while (mapFile) { - if (!(mapFile >> type)) break; - mapFile >> buffer; // idx + + while (mapFile >> type) { + mapFile >> buffer; myStr2Int(buffer, idx); - mapFile >> buffer; // bit + mapFile >> buffer; myStr2Int(buffer, bit); - mapFile >> buffer; // name + mapFile >> buffer; name = buffer; if (type == "input") id2Name[Gia_ObjId(pGia, Gia_ManPi(pGia, idx))] = gateName(name, bit); else if (type == "output") id2Name[Gia_ObjId(pGia, Gia_ManPo(pGia, idx))] = gateName(name, bit); @@ -101,8 +95,7 @@ void AbcMgr::travPreprocess() { Gia_ObjSetTravIdCurrent(pGia, Gia_ManConst0(pGia)); } -void AbcMgr::travAllObj(vector& piList, vector& poList, vector& roList, vector& riList, - vector& totGateList, map& id2Name, const CirFileType& fileType) { +void AbcMgr::travAllObj(CirMgr* _cirMgr, const CirFileType& fileType, map id2Name) { Gia_Obj_t *pObj, *pObjRi, *pObjRo; // the obj element of gia size_t i, iPi = 0, iPpi = 0, iPo = 0, iRi = 0, iRo = 0; map PPI2RO; @@ -110,14 +103,14 @@ void AbcMgr::travAllObj(vector& piList, vector& poList, Gia_ManForEachObj(pGia, pObj, i) { if (Gia_ObjIsPi(pGia, pObj)) { int gateId = Gia_ObjId(pGia, pObj); - if (gateId <= piList.size()) { - CirPiGate* gate = new CirPiGate(Gia_ObjId(pGia, pObj), 0); - piList[iPi++] = gate; - totGateList[gateId] = gate; + if (gateId <= _cirMgr->_piList.size()) { + CirPiGate* gate = new CirPiGate(Gia_ObjId(pGia, pObj), 0); + _cirMgr->_piList[iPi++] = gate; + _cirMgr->_totGateList[gateId] = gate; } else { - CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); - roList[iRo++] = gate; - totGateList[gateId] = gate; + CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); + _cirMgr->_roList[iRo++] = gate; + _cirMgr->_totGateList[gateId] = gate; } } else if (Gia_ObjIsPo(pGia, pObj)) { string poName = ""; @@ -126,28 +119,29 @@ void AbcMgr::travAllObj(vector& piList, vector& poList, char* n = new char[poName.size() + 1]; strcpy(n, poName.c_str()); gate->setName(n); - gate->setIn0(cirMgr->getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); - poList[iPo++] = gate; - totGateList[Gia_ObjId(pGia, pObj)] = gate; + gate->setIn0(_cirMgr->getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); + _cirMgr->_poList[iPo++] = gate; + _cirMgr->_totGateList[Gia_ObjId(pGia, pObj)] = gate; } else if (Gia_ObjIsAnd(pObj)) { CirAigGate* gate = new CirAigGate(Gia_ObjId(pGia, pObj), 0); int fanin0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); int fanin1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); if (PPI2RO.count(fanin0)) fanin0 = PPI2RO[fanin0]; if (PPI2RO.count(fanin1)) fanin1 = PPI2RO[fanin1]; - gate->setIn0(cirMgr->getGate(fanin0), Gia_ObjFaninC0(pObj)); - gate->setIn1(cirMgr->getGate(fanin1), Gia_ObjFaninC1(pObj)); - totGateList[Gia_ObjId(pGia, pObj)] = gate; + gate->setIn0(_cirMgr->getGate(fanin0), Gia_ObjFaninC0(pObj)); + gate->setIn1(_cirMgr->getGate(fanin1), Gia_ObjFaninC1(pObj)); + _cirMgr->_totGateList[Gia_ObjId(pGia, pObj)] = gate; } else if (Gia_ObjIsRo(pGia, pObj)) { int gateId = Gia_ObjId(pGia, pObj); if (fileType == VERILOG) { PPI2RO[gateId] = 0; - if (iPpi < iRo) PPI2RO[gateId] = roList[iPpi]->getGid(); + if (iPpi < iRo) PPI2RO[gateId] = _cirMgr->_roList[iPpi]->getGid(); iPpi++; } else if (fileType == AIGER) { - CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); - roList[iRo++] = gate; - totGateList[gateId] = gate; + CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); + + _cirMgr->_roList[iRo++] = gate; + _cirMgr->_totGateList[gateId] = gate; } } else if (Gia_ObjIsRi(pGia, pObj)) { CirRiGate* gate = new CirRiGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); @@ -156,11 +150,11 @@ void AbcMgr::travAllObj(vector& piList, vector& poList, char* n = new char[str.size() + 1]; strcpy(n, str.c_str()); gate->setName(n); - gate->setIn0(cirMgr->getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); - riList[iRi++] = gate; - totGateList[Gia_ObjId(pGia, pObj)] = gate; + gate->setIn0(_cirMgr->getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); + _cirMgr->_riList[iRi++] = gate; + _cirMgr->_totGateList[Gia_ObjId(pGia, pObj)] = gate; } else if (Gia_ObjIsConst0(pObj)) { - totGateList[0] = CirMgr::_const0; + _cirMgr->_totGateList[0] = CirMgr::_const0; } else { cout << "not defined gate type" << endl; assert(true); @@ -168,15 +162,38 @@ void AbcMgr::travAllObj(vector& piList, vector& poList, } Gia_ManForEachRiRo(pGia, pObjRi, pObjRo, i) { - if (i == cirMgr->getNumLATCHs()) break; - + if (i == _cirMgr->getNumLATCHs()) break; int riGid = Gia_ObjId(pGia, pObjRi), roGid = 0; - // int roGid = PPI2RO[Gia_ObjId(pGia,pObjRo)]; - // int roGid = Gia_ObjId(pGia,pObjRo); if (fileType == VERILOG) roGid = PPI2RO[Gia_ObjId(pGia, pObjRo)]; else if (fileType == AIGER) roGid = Gia_ObjId(pGia, pObjRo); - CirGate* riGate = cirMgr->getGate(riGid); - CirRoGate* roGate = static_cast(cirMgr->getGate(roGid)); + CirGate* riGate = _cirMgr->getGate(riGid); + CirRoGate* roGate = static_cast(_cirMgr->getGate(roGid)); roGate->setIn0(riGate, false); } -} \ No newline at end of file + + // CONST1 Gate + _cirMgr->_const1 = new CirAigGate(_cirMgr->getNumTots(), 0); + _cirMgr->addTotGate(_cirMgr->_const1); + _cirMgr->_const1->setIn0(_cirMgr->_const0, true); + _cirMgr->_const1->setIn1(_cirMgr->_const0, true); +} + +void AbcMgr::initCir(CirMgr* _cirMgr, const CirFileType& fileType) { + // Create lists + int piNum = 0, regNum = 0, poNum = 0, totNum = 0; + if (fileType == VERILOG) { + piNum = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; + regNum = Gia_ManRegNum(pGia) - 1; + } else if (fileType == AIGER) { + piNum = Gia_ManPiNum(pGia); + regNum = Gia_ManRegNum(pGia); + } + poNum = Gia_ManPoNum(pGia); + totNum = Gia_ManObjNum(pGia); + + _cirMgr->_piList.resize(piNum); + _cirMgr->_riList.resize(regNum); + _cirMgr->_roList.resize(regNum); + _cirMgr->_poList.resize(poNum); + _cirMgr->_totGateList.resize(totNum); +} diff --git a/src/abc/gvAbcMgr.h b/src/abc/abcMgr.h similarity index 66% rename from src/abc/gvAbcMgr.h rename to src/abc/abcMgr.h index ffbf0037..7b378d22 100644 --- a/src/abc/gvAbcMgr.h +++ b/src/abc/abcMgr.h @@ -9,7 +9,7 @@ #include "base/main/main.h" #include "base/main/mainInt.h" #include "cirGate.h" -#include "gvAbcNtk.h" +#include "cirMgr.h" using namespace std; @@ -30,17 +30,16 @@ extern "C" } struct ABCParam { - ABCParam() : fBlast(0), fInvert(0), fTechMap(0), fSkipStrash(0), fCollapse(0), fVerbose(0), fGiaSimple(0), fCheck(0), pTopModule(NULL), pDefines(NULL) { + ABCParam() : fInvert(0), fTechMap(0), fSkipStrash(0), fVerbose(0), + fGiaSimple(0), fCheck(0), pTopModule(NULL), pDefines(NULL) { pFileName = new char[100]; }; char* pFileName; char* pTopModule; char* pDefines; - int fBlast; int fInvert; int fTechMap; int fSkipStrash; - int fCollapse; int fVerbose; int fGiaSimple; int fCheck; @@ -49,25 +48,22 @@ struct ABCParam { class AbcMgr { public: AbcMgr(); - ~AbcMgr() { reset(); } + ~AbcMgr(); void init(); void reset(); - void abcReadDesign(string&); void readAig(const ABCParam&); void readVerilog(const ABCParam&); void buildAigName(map&); void travPreprocess(); - void travAllObj(vector& piList, vector& poList, vector& roList, vector& riList, - vector& totGateList, map& id2Name, const CirFileType& fileType); + void travAllObj(CirMgr*, const CirFileType&, map); + void initCir(CirMgr*, const CirFileType&); Abc_Frame_t* get_Abc_Frame_t() { return pAbc; } - abcNtkMgr* get_abcNtkMgr() { return pNtkMgr; } Gia_Man_t* pGia; private: Abc_Frame_t* pAbc; - abcNtkMgr* pNtkMgr; }; #endif diff --git a/src/abc/gvAbcCmd.cpp b/src/abc/gvAbcCmd.cpp deleted file mode 100644 index 8dcc3349..00000000 --- a/src/abc/gvAbcCmd.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef GV_ABC_CMD_C -#define GV_ABC_CMD_C - -#include "gvAbcCmd.h" - -#include - -#include - -#include "gvAbcMgr.h" -#include "gvModMgr.h" -#include "gvMsg.h" -#include "util.h" - -bool initAbcCmd() { - if (abcMgr) delete abcMgr; - abcMgr = new AbcMgr; - return (gvCmdMgr->regCmd("ABCRead", 4, new GVABCReadCmd), - gvCmdMgr->regCmd("ABCPrint", 4, new GVABCPrintCmd), - gvCmdMgr->regCmd("ABCCMD", 6, new GVABCOriginalCmd)); -} - -//---------------------------------------------------------------------- -// ABCRead <(string filename)> -//---------------------------------------------------------------------- - -GVCmdExecStatus -GVABCReadCmd::exec(const string& option) { - vector options; - string fileName = ""; - GVCmdExec::lexOptions(option, options); - size_t n = options.size(); - for (size_t i = 0; i < n; ++i) { - const string& token = options[i]; - if (fileName == "") - fileName = options[i]; - else - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, token); - } - if (fileName == "") - return GVCmdExec::errorOption(GV_CMD_OPT_MISSING, - "<(string fileName)>"); - abcMgr->abcReadDesign(fileName); - return GV_CMD_EXEC_DONE; -} - -void GVABCReadCmd::usage(const bool& verbose) const { - cout << "Usage: ABCRead " << endl; -} - -void GVABCReadCmd::help() const { - cout << setw(20) << left << "ABCRead: " - << "Read netlist by ABC." << endl; -} - -//---------------------------------------------------------------------- -// ABCPrint [-Verbose] -//---------------------------------------------------------------------- - -GVCmdExecStatus -GVABCPrintCmd::exec(const string& option) { - vector options; - GVCmdExec::lexOptions(option, options); - bool basic = false, verbose = false; - size_t n = options.size(); - - if (options.size() > 1) - return GVCmdExec::errorOption(GV_CMD_OPT_EXTRA, options[1]); - else if (options.size()) { - if (myStrNCmp("-Verbose", options[0], 2) == 0) - verbose = true; - else - return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, options[0]); - } - (abcMgr->get_abcNtkMgr())->printSummary(); - return GV_CMD_EXEC_DONE; -} - -void GVABCPrintCmd::usage(const bool& verbose) const { - cout << "Usage: ABCPrint " << endl; -} - -void GVABCPrintCmd::help() const { - cout << setw(20) << left << "ABCPrint: " - << "Print netlist information." << endl; -} - -//---------------------------------------------------------------------- -// ABCCMD -//---------------------------------------------------------------------- - -GVCmdExecStatus -GVABCOriginalCmd::exec(const string& option) { - vector options; - GVCmdExec::lexOptions(option, options); - size_t n = options.size(); - string command; - for (size_t i = 0; i < n; ++i) { - command += options[i]; - if (i < n - 1) { - command += " "; - } - } - - // calling abc's command - char Command[1024], abcCmd[128]; - strcpy(abcCmd, command.c_str()); - sprintf(Command, "%s", abcCmd); - Cmd_CommandExecute(abcMgr->get_Abc_Frame_t(), Command); -} - -void GVABCOriginalCmd::usage(const bool& verbose) const { - cout << "Usage: ABCCMD " << endl; -} - -void GVABCOriginalCmd::help() const { - cout << setw(20) << left << "ABCCMD: " - << "Directly call ABC's command." << endl; -} - -#endif \ No newline at end of file diff --git a/src/abc/gvAbcNtk.cpp b/src/abc/gvAbcNtk.cpp deleted file mode 100644 index 6a56b6ed..00000000 --- a/src/abc/gvAbcNtk.cpp +++ /dev/null @@ -1,202 +0,0 @@ -#ifndef GV_ABC_NTK_C -#define GV_ABC_NTK_C - -#include "gvAbcNtk.h" -#include "base/abc/abc.h" -#include "base/main/main.h" -#include "base/main/mainInt.h" -#include "sat/cnf/cnf.h" -#include "gvAbcMgr.h" -#include -#include - -extern "C" -{ - int Abc_NtkDSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fAlignPol, int fAndOuts, int fNewSolver, int fVerbose ); -} - -AbcMgr* abcNtkMgr::_AbcMgr = 0; - -void -abcNtkMgr::init() { - Total_num = Abc_NtkObjNum(pNtk); - PI_num = Abc_NtkCiNum(pNtk); - PO_num = Abc_NtkCoNum(pNtk); - Node_num = Abc_NtkNodeNum(pNtk); -} - -void -abcNtkMgr::printSummary() const { - cout << endl; - cout << "Circuit Statistics" << endl; - cout << "==================" << endl; - cout << " PI " << setw(10) << right << PI_num << endl; - cout << " PO " << setw(10) << right << PO_num << endl; - cout << " Node " << setw(10) << right << Node_num << endl; - cout << "------------------" << endl; - cout << " Total" << setw(10) << right << PI_num + PO_num + Node_num << endl; -} - -void -abcNtkMgr::sweep(bool verbose) { - if (!Abc_NtkIsLogic(pNtk)) { - cout << "The classical (SIS-like) sweep can only be performed on a logic network.\n" << endl; - return; - } - Abc_NtkSweep(pNtk, verbose); -} - -void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ) -{ - int * pModel; - pModel = pNtk->pModel; - for (int i = 0; i < Abc_NtkPiNum(pNtk); i++ ) - Vec_IntWriteEntry( vPiValues, i, pModel[i] ); -} - -void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars ) -{ - for (int i = 0; i < nPars; i++ ) - Vec_IntWriteEntry( vPiValues, i, -1 ); -} - -void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ) -{ - for (int i = nPars; i < Abc_NtkPiNum(pNtk); i++ ) - Vec_IntWriteEntry( vPiValues, i, -1 ); -} - -void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars ) -{ - for (int i = 0; i < nPars; i++ ) - printf( "%d", Vec_IntEntry(vPiValues,i) ); -} - -void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ) -{ - for (int i = nPars; i < Abc_NtkPiNum(pNtk); i++ ) - printf( "%d", Vec_IntEntry(vPiValues,i) ); -} - -void -abcNtkMgr::abcQBF(int nPars, int nIters, bool fVerbose) -{ - if ( !Abc_NtkIsStrash(pNtk) ) { - pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); - } - - Abc_Ntk_t * pNtkVer, * pNtkSyn, * pNtkSyn2, * pNtkTemp; - Vec_Int_t * vPiValues; - abctime clkTotal = Abc_Clock(), clkS, clkV; - int nInputs, RetValue, fFound = 0, nItersMax=10000; - - 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) ); - - // create random init value - { - int i; - srand( time(NULL) ); - for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ ) - Vec_IntWriteEntry( vPiValues, i, rand() & 1 ); - } - - 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 < nItersMax; nIters++ ) - { - // solve the synthesis instance - clkS = Abc_Clock(); - // RetValue = Abc_NtkMiterSat( pNtkSyn, 0, 0, 0, NULL, NULL ); - RetValue = Abc_NtkDSat( pNtkSyn, (ABC_INT64_T)0, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 ); - clkS = Abc_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 = Abc_Clock(); - RetValue = Abc_NtkMiterSat( pNtkVer, 0, 0, 0, NULL, NULL ); - clkV = Abc_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( " " ); - ABC_PRT( "Syn", clkS ); - } - } - Abc_NtkDelete( pNtkSyn ); - // report the results - if ( fFound ) - { - int nZeros = Vec_IntCountZero( vPiValues ); - printf( "Parameters: " ); - Abc_NtkVectorPrintPars( vPiValues, nPars ); - printf( " Statistics: 0=%d 1=%d\n", nZeros, Vec_IntSize(vPiValues) - nZeros ); - printf( "Solved after %d iterations. ", nIters ); - } - else if ( nIters == nItersMax ) - printf( "Quit after %d iterations. ", nItersMax ); - else - printf( "Implementation does not exist. " ); - ABC_PRT( "Total runtime", Abc_Clock() - clkTotal ); - Vec_IntFree( vPiValues ); -} - -#endif \ No newline at end of file diff --git a/src/abc/gvAbcNtk.h b/src/abc/gvAbcNtk.h deleted file mode 100644 index 3cb1ece3..00000000 --- a/src/abc/gvAbcNtk.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef GV_ABC_NTK_H -#define GV_ABC_NTK_H - -#include -using namespace std; - -class AbcMgr; -class abcNtkMgr; -typedef struct Abc_Frame_t_ Abc_Frame_t; -typedef struct Abc_Ntk_t_ Abc_Ntk_t; -typedef struct Abc_Obj_t_ Abc_Obj_t; - -class abcNtkMgr -{ - public: - abcNtkMgr(Abc_Ntk_t* ntk) : pNtk(ntk) { init(); } - ~abcNtkMgr() {} - - void init(); - - void sweep(bool); - - void printSummary() const; - Abc_Ntk_t* getNtk() { return pNtk; } - void abcQBF(int, int, bool); - - private: - Abc_Ntk_t* pNtk; - static AbcMgr* _AbcMgr; - - vector PI_List; - vector PO_List; - vector DFS_List; - unsigned Total_num; - unsigned PI_num; - unsigned PO_num; - unsigned Node_num; -}; -#endif \ No newline at end of file diff --git a/src/bdd/.depend.mak b/src/bdd/.depend.mak index f1435642..faf517e0 100644 --- a/src/bdd/.depend.mak +++ b/src/bdd/.depend.mak @@ -16,27 +16,8 @@ bddCmd.o: bddCmd.cpp bddCmd.h ../../include/gvCmdMgr.h bddMgrV.h myHash.h \ ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/gvBitVec.h ../../include/gvIntType.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/main/main.h \ - ../../include/base/abc/abc.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - ../../include/gvAbcNtk.h ../../include/kernel/sigtools.h \ - ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ - /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ - ../../include/kernel/hashlib.h ../../include/kernel/log.h \ - ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ - ../../include/kernel/register.h ../../include/kernel/utils.h \ - ../../include/kernel/yosys.h ../../include/cirMgr.h \ - ../../include/gvMsg.h ../../include/gvNtk.h ../../include/util.h \ + ../../include/gvBitVec.h ../../include/gvIntType.h \ + ../../include/cirMgr.h ../../include/gvMsg.h ../../include/util.h \ ../../include/rnGen.h ../../include/myUsage.h bddMgrV.o: bddMgrV.cpp bddMgrV.h myHash.h bddNodeV.h ../../include/util.h \ ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/cir/.depend.mak b/src/cir/.depend.mak index afa47b1c..1cd8017d 100644 --- a/src/cir/.depend.mak +++ b/src/cir/.depend.mak @@ -2,7 +2,7 @@ cirAig.o: cirAig.cpp cirGate.h cirDef.h ../../include/myHash.h \ ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ ../../include/SolverTypesV.h ../../include/GlobalV.h \ ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ - ../../include/cirGate.h ../../include/cirMgr.h ../../include/cirDef.h \ + ../../include/cirGate.h ../../include/cirMgr.h \ ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ @@ -15,37 +15,34 @@ cirAig.o: cirAig.cpp cirGate.h cirDef.h ../../include/myHash.h \ ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/gvBitVec.h ../../include/gvIntType.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/main/main.h \ - ../../include/base/abc/abc.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - ../../include/gvAbcNtk.h ../../include/kernel/sigtools.h \ + ../../include/cirDef.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h cirMgr.h ../../include/abcMgr.h \ + ../../include/base/main/main.h ../../include/base/abc/abc.h \ + ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ + ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ + ../../include/base/main/mainInt.h ../../include/base/main/main.h \ + ../../include/misc/tim/tim.h ../../include/map/if/if.h \ + ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ + ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ + ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ + ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ + ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ + ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ + ../../include/aig/ioa/ioa.h ../../include/gvYosysMgr.h \ ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ ../../include/kernel/hashlib.h ../../include/kernel/log.h \ - ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ - ../../include/kernel/register.h ../../include/kernel/utils.h \ - ../../include/kernel/yosys.h cirMgr.h ../../include/gvAbcMgr.h \ - ../../include/gvModMgr.h ../../include/gvCmdMgr.h \ - ../../include/gvYosysMgr.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h + ../../include/kernel/yosys.h ../../include/kernel/rtlil.h \ + ../../include/kernel/constids.inc ../../include/kernel/register.h \ + ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h cirBdd.o: cirBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ ../../include/bddNodeV.h ../../include/bddNodeV.h cirGate.h cirDef.h \ ../../include/myHash.h ../../include/gvSat.h ../../include/SolverV.h \ ../../include/ProofV.h ../../include/SolverTypesV.h \ ../../include/GlobalV.h ../../include/FileV.h ../../include/VarOrderV.h \ ../../include/HeapV.h ../../include/cirGate.h ../../include/cirMgr.h \ - ../../include/cirDef.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ @@ -56,34 +53,16 @@ cirBdd.o: cirBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/gvBitVec.h ../../include/gvIntType.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/main/main.h \ - ../../include/base/abc/abc.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - ../../include/gvAbcNtk.h ../../include/kernel/sigtools.h \ - ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ - /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ - ../../include/kernel/hashlib.h ../../include/kernel/log.h \ - ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ - ../../include/kernel/register.h ../../include/kernel/utils.h \ - ../../include/kernel/yosys.h cirMgr.h ../../include/gvMsg.h \ + ../../include/cirDef.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h cirMgr.h ../../include/gvMsg.h \ ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h cirCmd.o: cirCmd.cpp cirCmd.h ../../include/gvCmdMgr.h cirGate.h cirDef.h \ ../../include/myHash.h ../../include/gvSat.h ../../include/SolverV.h \ ../../include/ProofV.h ../../include/SolverTypesV.h \ ../../include/GlobalV.h ../../include/FileV.h ../../include/VarOrderV.h \ ../../include/HeapV.h ../../include/cirGate.h ../../include/cirMgr.h \ - ../../include/cirDef.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ @@ -94,26 +73,8 @@ cirCmd.o: cirCmd.cpp cirCmd.h ../../include/gvCmdMgr.h cirGate.h cirDef.h \ ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/gvBitVec.h ../../include/gvIntType.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/main/main.h \ - ../../include/base/abc/abc.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - ../../include/gvAbcNtk.h ../../include/kernel/sigtools.h \ - ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ - /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ - ../../include/kernel/hashlib.h ../../include/kernel/log.h \ - ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ - ../../include/kernel/register.h ../../include/kernel/utils.h \ - ../../include/kernel/yosys.h cirMgr.h ../../include/gvModMgr.h \ + ../../include/cirDef.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h cirMgr.h ../../include/gvModMgr.h \ ../../include/gvCmdMgr.h ../../include/gvMsg.h ../../include/util.h \ ../../include/rnGen.h ../../include/myUsage.h cirFraig.o: cirFraig.cpp @@ -121,7 +82,7 @@ cirGate.o: cirGate.cpp cirGate.h cirDef.h ../../include/myHash.h \ ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ ../../include/SolverTypesV.h ../../include/GlobalV.h \ ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ - ../../include/cirGate.h ../../include/cirMgr.h ../../include/cirDef.h \ + ../../include/cirGate.h ../../include/cirMgr.h \ ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ @@ -134,30 +95,12 @@ cirGate.o: cirGate.cpp cirGate.h cirDef.h ../../include/myHash.h \ ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/gvBitVec.h ../../include/gvIntType.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/main/main.h \ - ../../include/base/abc/abc.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - ../../include/gvAbcNtk.h ../../include/kernel/sigtools.h \ - ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ - /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ - ../../include/kernel/hashlib.h ../../include/kernel/log.h \ - ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ - ../../include/kernel/register.h ../../include/kernel/utils.h \ - ../../include/kernel/yosys.h cirMgr.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -cirMgr.o: cirMgr.cpp cirMgr.h cirDef.h ../../include/myHash.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ + ../../include/cirDef.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h cirMgr.h ../../include/util.h \ + ../../include/rnGen.h ../../include/myUsage.h \ + ../../include/base/abc/abc.h +cirMgr.o: cirMgr.cpp cirMgr.h ../../include/base/abc/abc.h \ + ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ @@ -167,34 +110,16 @@ cirMgr.o: cirMgr.cpp cirMgr.h cirDef.h ../../include/myHash.h \ ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirGate.h \ - ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirDef.h \ + ../../include/myHash.h cirGate.h ../../include/gvSat.h \ + ../../include/SolverV.h ../../include/ProofV.h \ ../../include/SolverTypesV.h ../../include/GlobalV.h \ ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ ../../include/cirGate.h ../../include/cirMgr.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h ../../include/gvNtk.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/base/main/main.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h -cirOpt.o: cirOpt.cpp cirMgr.h cirDef.h ../../include/myHash.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ + ../../include/gvIntType.h ../../include/util.h ../../include/rnGen.h \ + ../../include/myUsage.h +cirOpt.o: cirOpt.cpp cirMgr.h ../../include/base/abc/abc.h \ + ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ @@ -204,29 +129,12 @@ cirOpt.o: cirOpt.cpp cirMgr.h cirDef.h ../../include/myHash.h \ ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirGate.h \ - ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirDef.h \ + ../../include/myHash.h cirGate.h ../../include/gvSat.h \ + ../../include/SolverV.h ../../include/ProofV.h \ ../../include/SolverTypesV.h ../../include/GlobalV.h \ ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ ../../include/cirGate.h ../../include/cirMgr.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h ../../include/gvNtk.h ../../include/gvAbcMgr.h \ - ../../include/base/abc/abc.h ../../include/base/main/main.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h + ../../include/gvIntType.h ../../include/util.h ../../include/rnGen.h \ + ../../include/myUsage.h cirSim.o: cirSim.cpp diff --git a/src/cir/cirAig.cpp b/src/cir/cirAig.cpp index 2e37d3cd..59b56500 100644 --- a/src/cir/cirAig.cpp +++ b/src/cir/cirAig.cpp @@ -10,163 +10,58 @@ #include -#include "gvAbcMgr.h" -#include "gvAbcNtk.h" +#include "abcMgr.h" #include "gvYosysMgr.h" #include "util.h" +/** + * Reads a circuit from the ABC Gia. + * + * This function reads a circuit from the specified file using the ABC. + * + * @param fileName The name of the file containing the circuit. + * @param fileType The type of file (AIGER or VERILOG) to be read. + * @return Returns true if the circuit is successfully read; otherwise, false. + */ const bool CirMgr::readCirFromAbc(string fileName, CirFileType fileType) { - Gia_Man_t* pGia = NULL; // the gia pointer of abc - map id2Name; ABCParam param; + map id2Name; + + ifstream cirin(fileName); + if (!cirin) { + cerr << "Cannot open design \"" << fileName << "\"!!" << endl; + return false; + } + strcpy(param.pFileName, fileName.c_str()); cout << "filename = " << fileName << endl; if (fileType == AIGER) { abcMgr->readAig(param); - pGia = abcMgr->pGia; } else if (fileType == VERILOG) { - param.fBlast = 1; param.fTechMap = 1; abcMgr->readVerilog(param); - pGia = abcMgr->pGia; - } - - if (!pGia) { - cerr << "Cannot open design \"" << fileName << "\"!!" << endl; - return false; - } - - if (fileType == VERILOG) { yosysMgr->createMapping(fileName); abcMgr->buildAigName(id2Name); } // initialize the size of the containers - initCir(pGia, fileType); + abcMgr->initCir(this, fileType); abcMgr->travPreprocess(); - abcMgr->travAllObj(_piList, _poList, _roList, _riList, _totGateList, id2Name, fileType); - - // traverse the obj's in topological order - // int i; - // Gia_ManForEachObj(pGia, pObj, i) { - // if (Gia_ObjIsPi(pGia, pObj)) { - // int gateId = Gia_ObjId(pGia, pObj); - // if (gateId <= _piList.size()) { - // CirPiGate* gate = new CirPiGate(Gia_ObjId(pGia, pObj), 0); - // _piList[iPi++] = gate; - // _totGateList[gateId] = gate; - // } else { - // CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); - // _roList[iRo++] = gate; - // _totGateList[gateId] = gate; - // } - // } else if (Gia_ObjIsPo(pGia, pObj)) { - // string poName = ""; - // CirPoGate* gate = new CirPoGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); - // poName = (id2Name.count(gate->getGid())) ? id2Name[gate->getGid()] : to_string(Gia_ObjId(pGia, pObj)); - // char* n = new char[poName.size() + 1]; - // strcpy(n, poName.c_str()); - // gate->setName(n); - // gate->setIn0(getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); - // _poList[iPo++] = gate; - // _totGateList[Gia_ObjId(pGia, pObj)] = gate; - // } else if (Gia_ObjIsAnd(pObj)) { - // CirAigGate* gate = new CirAigGate(Gia_ObjId(pGia, pObj), 0); - // int fanin0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); - // int fanin1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); - // if (PPI2RO.count(fanin0)) fanin0 = PPI2RO[fanin0]; - // if (PPI2RO.count(fanin1)) fanin1 = PPI2RO[fanin1]; - // gate->setIn0(getGate(fanin0), Gia_ObjFaninC0(pObj)); - // gate->setIn1(getGate(fanin1), Gia_ObjFaninC1(pObj)); - // _totGateList[Gia_ObjId(pGia, pObj)] = gate; - // } else if (Gia_ObjIsRo(pGia, pObj)) { - // int gateId = Gia_ObjId(pGia, pObj); - // if (fileType == VERILOG) { - // PPI2RO[gateId] = 0; - // if (iPpi < iRo) PPI2RO[gateId] = _roList[iPpi]->getGid(); - // iPpi++; - // } else if (fileType == AIGER) { - // CirRoGate* gate = new CirRoGate(Gia_ObjId(pGia, pObj), 0); - // _roList[iRo++] = gate; - // _totGateList[gateId] = gate; - // } - // } else if (Gia_ObjIsRi(pGia, pObj)) { - // CirRiGate* gate = new CirRiGate(Gia_ObjId(pGia, pObj), 0, Gia_ObjId(pGia, Gia_ObjFanin0(pObj))); - // string str = to_string(Gia_ObjId(pGia, pObj)); - // str = str + "_ns"; - // char* n = new char[str.size() + 1]; - // strcpy(n, str.c_str()); - // gate->setName(n); - // gate->setIn0(getGate(Gia_ObjId(pGia, Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj)); - // _riList[iRi++] = gate; - // _totGateList[Gia_ObjId(pGia, pObj)] = gate; - // } else if (Gia_ObjIsConst0(pObj)) { - // _totGateList[0] = CirMgr::_const0; - // } else { - // cout << "not defined gate type" << endl; - // assert(true); - // } - // } - - // Gia_ManForEachRiRo(pGia, pObjRi, pObjRo, i) { - // if (i == getNumLATCHs()) break; - - // int riGid = Gia_ObjId(pGia, pObjRi), roGid = 0; - // // int roGid = PPI2RO[Gia_ObjId(pGia,pObjRo)]; - // // int roGid = Gia_ObjId(pGia,pObjRo); - // if (fileType == VERILOG) roGid = PPI2RO[Gia_ObjId(pGia, pObjRo)]; - // else if (fileType == AIGER) roGid = Gia_ObjId(pGia, pObjRo); - // CirGate* riGate = getGate(riGid); - // CirRoGate* roGate = static_cast(getGate(roGid)); - // roGate->setIn0(riGate, false); - // } - // CONST1 Gate - _const1 = new CirAigGate(getNumTots(), 0); - addTotGate(_const1); - _const1->setIn0(_const0, true); - _const1->setIn1(_const0, true); + abcMgr->travAllObj(this, fileType, id2Name); genDfsList(); return true; } -void CirMgr::initCir(Gia_Man_t* pGia, const CirFileType& fileType) { - // Create lists - int piNum = 0, regNum = 0, poNum = 0, totNum = 0; - if (fileType == VERILOG) { - piNum = Gia_ManPiNum(pGia) - Gia_ManRegNum(pGia) + 1; - regNum = Gia_ManRegNum(pGia) - 1; - } else if (fileType == AIGER) { - piNum = Gia_ManPiNum(pGia); - regNum = Gia_ManRegNum(pGia); - } - poNum = Gia_ManPoNum(pGia); - totNum = Gia_ManObjNum(pGia); - - _piList.resize(piNum); - _riList.resize(regNum); - _roList.resize(regNum); - _poList.resize(poNum); - _totGateList.resize(totNum); -} - -// CirGate* -// CirMgr::createGate(const GateType& type){ -// // CirGate* gate = _totGateList[id]; -// CirGate* gate; -// unsigned l = 0, id = getNumTots(); -// cirMgr->addTotGate(gate); -// switch (type) { -// case PI_GATE: gate = new CirPiGate(id, l); break; -// case AIG_GATE: gate = new CirAigGate(id, l); break; -// //case LATCH: gate = new CirRoGate(litId/2, lineNo+1); break; -// default: cerr << "Error: Unknown gate type (" << type << ")!!\n"; -// exit(-1); -// } -// return gate; -// } - +/** + * Creates a NOT gate in the circuit. + * + * This function creates a NOT gate in the circuit. + * + * @param in0 The input gate for the NOT gate. + * @return Returns a pointer to the created NOT gate. + */ CirGate* CirMgr::createNotGate(CirGate* in0) { CirGate* notGate = new CirAigGate(getNumTots(), 0); addTotGate(notGate); @@ -175,6 +70,15 @@ CirGate* CirMgr::createNotGate(CirGate* in0) { return notGate; } +/** + * Creates an AND gate in the circuit. + * + * This function creates an AND gate in the circuit. + * + * @param in0 The first input gate for the AND gate. + * @param in1 The second input gate for the AND gate. + * @return Returns a pointer to the created AND gate. + */ CirGate* CirMgr::createAndGate(CirGate* in0, CirGate* in1) { CirGate* andGate = new CirAigGate(getNumTots(), 0); addTotGate(andGate); @@ -183,6 +87,15 @@ CirGate* CirMgr::createAndGate(CirGate* in0, CirGate* in1) { return andGate; } +/** + * Creates an OR gate in the circuit. + * + * This function creates an OR gate in the circuit. + * + * @param in0 The first input gate for the OR gate. + * @param in1 The second input gate for the OR gate. + * @return Returns a pointer to the created OR gate. + */ CirGate* CirMgr::createOrGate(CirGate* in0, CirGate* in1) { CirGate* tmpGate = new CirAigGate(getNumTots(), 0); addTotGate(tmpGate); @@ -191,6 +104,15 @@ CirGate* CirMgr::createOrGate(CirGate* in0, CirGate* in1) { return createNotGate(tmpGate); } +/** + * Creates an XOR gate in the circuit. + * + * This function creates an XOR gate in the circuit. + * + * @param in0 The first input gate for the XOR gate. + * @param in1 The second input gate for the XOR gate. + * @return Returns a pointer to the created XOR gate. + */ CirGate* CirMgr::createXorGate(CirGate* in0, CirGate* in1) { CirGate* tmpGate0 = new CirAigGate(getNumTots(), 0); addTotGate(tmpGate0); diff --git a/src/cir/cirMgr.h b/src/cir/cirMgr.h index 0aa4e37a..3691acc4 100644 --- a/src/cir/cirMgr.h +++ b/src/cir/cirMgr.h @@ -9,175 +9,181 @@ #ifndef CIR_MGR_H #define CIR_MGR_H -#include -#include -#include #include #include +#include +#include using namespace std; // TODO: Feel free to define your own classes, variables, or functions. -#include "cirDef.h" #include "base/abc/abc.h" +#include "cirDef.h" +extern CirMgr* cirMgr; -extern CirMgr *cirMgr; - - enum CirFileType - { - VERILOG, - AIGER - }; +enum CirFileType { + VERILOG, + AIGER +}; -class CirMgr -{ - enum CirMgrFlag { NO_FEC = 0x1 }; - enum ParsePorts { VARS = 0, PI, LATCH, PO, AIG, TOT_PARSE_PORTS }; +class AbcMgr; +class CirMgr { + enum CirMgrFlag { NO_FEC = 0x1 }; + enum ParsePorts { VARS = 0, + PI, + LATCH, + PO, + AIG, + TOT_PARSE_PORTS }; public: - CirMgr(): _flag(0), _piList(0), _poList(0), _totGateList(0), - _fanoutInfo(0), _simLog(0) { } - ~CirMgr() { deleteCircuit(); } - - // Access functions - CirGate* operator [](unsigned gid) const { return _totGateList[gid]; } - // return '0' if "gid" corresponds to an undefined gate. - CirGate* getGate(unsigned gid) const { - if (gid >= getNumTots()) { return 0; } return _totGateList[gid]; } - CirGate* litId2Gate(unsigned litId) const { return getGate(litId/2); } - CirGateV litId2GateV(unsigned litId) const; - bool isFlag(CirMgrFlag f) const { return _flag & f; } - void setFlag(CirMgrFlag f) const { _flag |= f; } - void unsetFlag(CirMgrFlag f) const { _flag &= ~f; } - void resetFlag() const { _flag = 0; } - // unsigned getNumPIs() const { return _numDecl[PI]; } - // unsigned getNumPOs() const { return _numDecl[PO]; } - unsigned getNumPIs() const { return _piList.size(); } - unsigned getNumPOs() const { return _poList.size(); } - unsigned getNumLATCHs() const { return _riList.size(); } - unsigned getNumTots() const { return _totGateList.size(); } - // unsigned getNumLATCHs() const { return _numDecl[LATCH]; } - // unsigned getNumTots() const { return _numDecl[VARS] + _numDecl[PO] + 1; } - CirPiGate* getPi(unsigned i) const { return _piList[i]; } - CirPoGate* getPo(unsigned i) const { return _poList[i]; } - CirRiGate* getRi(unsigned i) const { return _riList[i]; } - CirRoGate* getRo(unsigned i) const { return _roList[i]; } - GateList& getFanouts(unsigned i) const { return _fanoutInfo[i]; } - - // Member functions about circuit construction - bool readCircuit(const string&); - void deleteCircuit(); - void genConnections(); - void genDfsList(); - void updateUndefList(); - void checkFloatList(); - void checkUnusedList(); - size_t checkConnectedGate(size_t); - - // Member functions about circuit optimization - void sweep(); - void optimize(); - bool checkAigOptimize(CirGate*, const CirGateV&, const CirGateV&, - CirGateV&) const; - void deleteAigGate(CirGate *); - void deleteUndefGate(CirGate *); - - // Member functions about simulation - void randomSim(); - void fileSim(ifstream&); - void setSimLog(ofstream *logFile) { _simLog = logFile; } - - // Member functions about fraig - void strash(); - IdList* getFECGrps(size_t i) const { return _fecGrps[i]; } - void printFEC() const; - void fraig(); - - // Member functions about circuit reporting - void printSummary() const; - void printNetlist() const; - void printPIs() const; - void printPOs() const; - void printFloatGates() const; - void printFECPairs() const; - void writeAag(ostream&) const; - void writeGate(ostream&, CirGate*) const; - - // Member functions about flags - // for hidden command - bool createMiter(CirMgr*, CirMgr*); - - static CirGate *_const0; - // MODIFICATION FOR SOCV HOMEWORK - void initCir(Gia_Man_t* pGia, const CirFileType& type); - void buildBdd(CirGate* gate); - void buildNtkBdd(); - void addTotGate(CirGate* gate){_totGateList.push_back(gate);}; - const bool readCirFromAbc(string fileName, CirFileType fileType); - const bool setBddOrder(const bool& file); - // CirGate* createGate(const GateType& type); - CirGate* createNotGate(CirGate* in0); - CirGate* createAndGate(CirGate* in0, CirGate* in1); - CirGate* createOrGate(CirGate* in0, CirGate* in1); - CirGate* createXorGate(CirGate* in0, CirGate* in1); - CirGate* _const1; + CirMgr() : _flag(0), _piList(0), _poList(0), _totGateList(0), _fanoutInfo(0), _simLog(0) {} + ~CirMgr() { deleteCircuit(); } + + // Abc Interface + friend class AbcMgr; + + // Access functions + CirGate* operator[](unsigned gid) const { return _totGateList[gid]; } + // return '0' if "gid" corresponds to an undefined gate. + CirGate* getGate(unsigned gid) const { + if (gid >= getNumTots()) { + return 0; + } + return _totGateList[gid]; + } + CirGate* litId2Gate(unsigned litId) const { return getGate(litId / 2); } + CirGateV litId2GateV(unsigned litId) const; + bool isFlag(CirMgrFlag f) const { return _flag & f; } + void setFlag(CirMgrFlag f) const { _flag |= f; } + void unsetFlag(CirMgrFlag f) const { _flag &= ~f; } + void resetFlag() const { _flag = 0; } + // unsigned getNumPIs() const { return _numDecl[PI]; } + // unsigned getNumPOs() const { return _numDecl[PO]; } + unsigned getNumPIs() const { return _piList.size(); } + unsigned getNumPOs() const { return _poList.size(); } + unsigned getNumLATCHs() const { return _riList.size(); } + unsigned getNumTots() const { return _totGateList.size(); } + // unsigned getNumLATCHs() const { return _numDecl[LATCH]; } + // unsigned getNumTots() const { return _numDecl[VARS] + _numDecl[PO] + 1; } + CirPiGate* getPi(unsigned i) const { return _piList[i]; } + CirPoGate* getPo(unsigned i) const { return _poList[i]; } + CirRiGate* getRi(unsigned i) const { return _riList[i]; } + CirRoGate* getRo(unsigned i) const { return _roList[i]; } + GateList& getFanouts(unsigned i) const { return _fanoutInfo[i]; } + + // Member functions about circuit construction + bool readCircuit(const string&); + void deleteCircuit(); + void genConnections(); + void genDfsList(); + void updateUndefList(); + void checkFloatList(); + void checkUnusedList(); + size_t checkConnectedGate(size_t); + + // Member functions about circuit optimization + void sweep(); + void optimize(); + bool checkAigOptimize(CirGate*, const CirGateV&, const CirGateV&, CirGateV&) const; + void deleteAigGate(CirGate*); + void deleteUndefGate(CirGate*); + + // Member functions about simulation + void randomSim(); + void fileSim(ifstream&); + void setSimLog(ofstream* logFile) { _simLog = logFile; } + + // Member functions about fraig + void strash(); + IdList* getFECGrps(size_t i) const { return _fecGrps[i]; } + void printFEC() const; + void fraig(); + + // Member functions about circuit reporting + void printSummary() const; + void printNetlist() const; + void printPIs() const; + void printPOs() const; + void printFloatGates() const; + void printFECPairs() const; + void writeAag(ostream&) const; + void writeGate(ostream&, CirGate*) const; + + // Member functions about flags + // for hidden command + bool createMiter(CirMgr*, CirMgr*); + static CirGate* _const0; + // MODIFICATION FOR SOCV HOMEWORK + void initCir(Gia_Man_t* pGia, const CirFileType& type); + void buildBdd(CirGate* gate); + void buildNtkBdd(); + void addTotGate(CirGate* gate) { _totGateList.push_back(gate); }; + const bool readCirFromAbc(string fileName, CirFileType fileType); + const bool setBddOrder(const bool& file); + // CirGate* createGate(const GateType& type); + CirGate* createNotGate(CirGate* in0); + CirGate* createAndGate(CirGate* in0, CirGate* in1); + CirGate* createOrGate(CirGate* in0, CirGate* in1); + CirGate* createXorGate(CirGate* in0, CirGate* in1); + CirGate* _const1; private: - unsigned _numDecl[TOT_PARSE_PORTS]; - mutable unsigned _flag; - PiArray _piList; - PoArray _poList; - RiArray _riList; - RoArray _roList; - // IDs in _undefList are NOT sorted!! - IdList _undefList; - // Make sure the IDs of the following lists are sorted!! - IdList _floatList; // gates with fanin(s) undefined - IdList _unusedList; // gates defined but not used - GateArray _totGateList; - GateList _dfsList; - GateList *_fanoutInfo; - vector _fecGrps; // store litId; FECHash - SimVector _fecVector; - ofstream *_simLog; - - // private member functions for circuit parsing - bool parseHeader(ifstream&); - bool parseInput(ifstream&); - bool parseLatch(ifstream&); - bool parseOutput(ifstream&); - bool parseAig(ifstream&); - bool parseSymbol(ifstream&); - bool parseComment(ifstream&); - bool checkId(unsigned&, const string&); - CirGate* checkGate(unsigned&, ParsePorts, const string&); - - // private member functions for circuit optimization - CirGateV constSimplify(CirGate *, const CirGateV&, const CirGateV&) const; - - // private member functions about simulation - void setRandPPattern() const; - void setPPattern(SimPattern const patterns) const; - unsigned gatherPatterns(ifstream&, SimPattern, size_t); - void pSim1Pattern() const; - void outputSimLog(size_t nPatterns = 64); - - // private member functions about FRAIG - bool simAndCheckFEC(); - bool initFEC(); - bool checkFEC(); - bool checkFECRecur(const IdList&, vector&); - void finalizeFEC(); - void simplifyFECGrps(); - void clearFECGrps(); - void initProofModel(SatSolver&, const GateList&); - bool satCheckConst(SatSolver&, CirGate *, bool, SimPattern); - bool satCheckFEC(SatSolver&, CirGate *, CirGate *, bool, SimPattern); - void getSatAssignment(SatSolver&, SimPattern) const; - void simplifyByEQ(); - void updateFECbySatPattern(SimPattern); + unsigned _numDecl[TOT_PARSE_PORTS]; + mutable unsigned _flag; + PiArray _piList; + PoArray _poList; + RiArray _riList; + RoArray _roList; + // IDs in _undefList are NOT sorted!! + IdList _undefList; + // Make sure the IDs of the following lists are sorted!! + IdList _floatList; // gates with fanin(s) undefined + IdList _unusedList; // gates defined but not used + GateArray _totGateList; + GateList _dfsList; + GateList* _fanoutInfo; + vector _fecGrps; // store litId; FECHash + SimVector _fecVector; + ofstream* _simLog; + + // private member functions for circuit parsing + bool parseHeader(ifstream&); + bool parseInput(ifstream&); + bool parseLatch(ifstream&); + bool parseOutput(ifstream&); + bool parseAig(ifstream&); + bool parseSymbol(ifstream&); + bool parseComment(ifstream&); + bool checkId(unsigned&, const string&); + CirGate* checkGate(unsigned&, ParsePorts, const string&); + + // private member functions for circuit optimization + CirGateV constSimplify(CirGate*, const CirGateV&, const CirGateV&) const; + + // private member functions about simulation + void setRandPPattern() const; + void setPPattern(SimPattern const patterns) const; + unsigned gatherPatterns(ifstream&, SimPattern, size_t); + void pSim1Pattern() const; + void outputSimLog(size_t nPatterns = 64); + + // private member functions about FRAIG + bool simAndCheckFEC(); + bool initFEC(); + bool checkFEC(); + bool checkFECRecur(const IdList&, vector&); + void finalizeFEC(); + void simplifyFECGrps(); + void clearFECGrps(); + void initProofModel(SatSolver&, const GateList&); + bool satCheckConst(SatSolver&, CirGate*, bool, SimPattern); + bool satCheckFEC(SatSolver&, CirGate*, CirGate*, bool, SimPattern); + void getSatAssignment(SatSolver&, SimPattern) const; + void simplifyByEQ(); + void updateFECbySatPattern(SimPattern); }; -#endif // CIR_MGR_H +#endif // CIR_MGR_H diff --git a/src/cmd/.depend.mak b/src/cmd/.depend.mak index fc75d675..897d154b 100644 --- a/src/cmd/.depend.mak +++ b/src/cmd/.depend.mak @@ -1,5 +1,5 @@ gvCmdComm.o: gvCmdComm.cpp gvCmdComm.h gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/gvUsage.h ../../include/gvMsg.h ../../include/gvIntType.h \ + ../../include/gvUsage.h ../../include/gvIntType.h ../../include/gvMsg.h \ ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h gvCmdMgr.o: gvCmdMgr.cpp gvCmdMgr.h ../../include/gvMsg.h \ ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/gvsat/.depend.mak b/src/gvsat/.depend.mak index c2afad89..23f83f37 100644 --- a/src/gvsat/.depend.mak +++ b/src/gvsat/.depend.mak @@ -2,7 +2,7 @@ FileV.o: FileV.cpp FileV.h GlobalV.h gvBitVec.o: gvBitVec.cpp gvBitVec.h ../../include/gvIntType.h gvSat.o: gvSat.cpp gvSat.h SolverV.h ProofV.h SolverTypesV.h GlobalV.h \ FileV.h VarOrderV.h HeapV.h ../../include/cirGate.h \ - ../../include/cirDef.h ../../include/myHash.h ../../include/gvSat.h \ + ../../include/cirDef.h ../../include/myHash.h gvSat.h \ ../../include/cirMgr.h ../../include/base/abc/abc.h \ ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ @@ -15,25 +15,7 @@ gvSat.o: gvSat.cpp gvSat.h SolverV.h ProofV.h SolverTypesV.h GlobalV.h \ ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h gvBitVec.h \ - ../../include/gvIntType.h ../../include/gvNtk.h ../../include/gvAbcMgr.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h + ../../include/gvIntType.h ProofV.o: ProofV.cpp ProofV.h SolverTypesV.h GlobalV.h FileV.h SortV.h reader.o: reader.cpp reader.h SolverV.o: SolverV.cpp SolverV.h ProofV.h SolverTypesV.h GlobalV.h \ diff --git a/src/itp/.depend.mak b/src/itp/.depend.mak index cb19a6ff..12f177ff 100644 --- a/src/itp/.depend.mak +++ b/src/itp/.depend.mak @@ -16,32 +16,18 @@ gvSatCmd.o: gvSatCmd.cpp gvSatCmd.h ../../include/gvCmdMgr.h \ ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/gvBitVec.h ../../include/gvIntType.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/main/main.h \ - ../../include/base/abc/abc.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - ../../include/gvAbcNtk.h ../../include/kernel/sigtools.h \ - ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ - /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ - ../../include/kernel/hashlib.h ../../include/kernel/log.h \ - ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ - ../../include/kernel/register.h ../../include/kernel/utils.h \ - ../../include/kernel/yosys.h ../../include/cirMgr.h \ - ../../include/gvMsg.h gvSatMgr.h ../../include/gvNtk.h \ + ../../include/gvBitVec.h ../../include/gvIntType.h \ + ../../include/cirMgr.h ../../include/gvMsg.h gvSatMgr.h \ ../../include/gvSat.h ../../include/reader.h ../../include/util.h \ ../../include/rnGen.h ../../include/myUsage.h -gvSatMgr.o: gvSatMgr.cpp gvSatMgr.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ +gvSatMgr.o: gvSatMgr.cpp gvSatMgr.h ../../include/gvSat.h \ + ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirDef.h ../../include/myHash.h \ + ../../include/gvSat.h ../../include/cirMgr.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ @@ -52,28 +38,6 @@ gvSatMgr.o: gvSatMgr.cpp gvSatMgr.h ../../include/gvNtk.h \ ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h \ - ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ - ../../include/SolverTypesV.h ../../include/GlobalV.h \ - ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ - ../../include/cirGate.h ../../include/cirDef.h ../../include/myHash.h \ - ../../include/gvSat.h ../../include/cirMgr.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h ../../include/gvNtk.h ../../include/cirGate.h \ - ../../include/cirMgr.h ../../include/reader.h ../../include/gvMsg.h + ../../include/gvBitVec.h ../../include/gvIntType.h \ + ../../include/cirGate.h ../../include/cirMgr.h ../../include/reader.h \ + ../../include/gvMsg.h diff --git a/src/main/.depend.mak b/src/main/.depend.mak index b96a8e22..7935149b 100644 --- a/src/main/.depend.mak +++ b/src/main/.depend.mak @@ -1,5 +1,5 @@ main.o: main.cpp ../../include/gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/gvUsage.h ../../include/gvMsg.h ../../include/gvIntType.h \ + ../../include/gvUsage.h ../../include/gvIntType.h ../../include/gvMsg.h \ ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ ../../include/kernel/hashlib.h ../../include/kernel/log.h \ diff --git a/src/mod/.depend.mak b/src/mod/.depend.mak index 787aa841..b81aab87 100644 --- a/src/mod/.depend.mak +++ b/src/mod/.depend.mak @@ -1,5 +1,5 @@ -gvModCmd.o: gvModCmd.cpp gvModCmd.h ../../include/gvCmdMgr.h gvModMgr.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ +gvModCmd.o: gvModCmd.cpp gvModCmd.h ../../include/gvCmdMgr.h \ + ../../include/abcMgr.h ../../include/base/abc/abc.h \ ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ @@ -22,11 +22,17 @@ gvModCmd.o: gvModCmd.cpp gvModCmd.h ../../include/gvCmdMgr.h gvModMgr.h \ ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/gvMsg.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h + ../../include/aig/ioa/ioa.h ../../include/cirGate.h \ + ../../include/cirDef.h ../../include/myHash.h ../../include/gvSat.h \ + ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirMgr.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h gvModMgr.h ../../include/gvMsg.h \ + ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ + /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ + ../../include/kernel/hashlib.h ../../include/kernel/log.h \ + ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ + ../../include/kernel/register.h ../../include/util.h \ + ../../include/rnGen.h ../../include/myUsage.h gvModMgr.o: gvModMgr.cpp gvModMgr.h ../../include/gvCmdMgr.h diff --git a/src/mod/gvModCmd.cpp b/src/mod/gvModCmd.cpp index 5c684926..15df0416 100644 --- a/src/mod/gvModCmd.cpp +++ b/src/mod/gvModCmd.cpp @@ -8,7 +8,7 @@ #include #include -#include "gvAbcMgr.h" +#include "abcMgr.h" #include "gvModMgr.h" #include "gvMsg.h" #include "kernel/yosys.h" diff --git a/src/prove/.depend.mak b/src/prove/.depend.mak index d0c660b0..62dc22c8 100644 --- a/src/prove/.depend.mak +++ b/src/prove/.depend.mak @@ -1,7 +1,7 @@ proveBdd.o: proveBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ - ../../include/bddNodeV.h ../../include/gvMsg.h ../../include/gvNtk.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ + ../../include/bddNodeV.h ../../include/gvMsg.h ../../include/cirMgr.h \ + ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ + ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ @@ -12,34 +12,20 @@ proveBdd.o: proveBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h \ - ../../include/cirMgr.h ../../include/cirDef.h ../../include/cirGate.h \ - ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/cirDef.h ../../include/cirGate.h ../../include/gvSat.h \ + ../../include/SolverV.h ../../include/ProofV.h \ ../../include/SolverTypesV.h ../../include/GlobalV.h \ ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ ../../include/cirGate.h ../../include/cirMgr.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h ../../include/gvNtk.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h + ../../include/gvIntType.h ../../include/util.h ../../include/rnGen.h \ + ../../include/myUsage.h proveCmd.o: proveCmd.cpp proveCmd.h ../../include/gvCmdMgr.h \ ../../include/bddMgrV.h ../../include/myHash.h ../../include/bddNodeV.h \ - ../../include/gvMsg.h ../../include/gvNtk.h ../../include/gvAbcMgr.h \ + ../../include/cirGate.h ../../include/cirDef.h ../../include/gvSat.h \ + ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirGate.h ../../include/cirMgr.h \ ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ @@ -52,28 +38,6 @@ proveCmd.o: proveCmd.cpp proveCmd.h ../../include/gvCmdMgr.h \ ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h \ - ../../include/cirMgr.h ../../include/cirDef.h ../../include/cirGate.h \ - ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ - ../../include/SolverTypesV.h ../../include/GlobalV.h \ - ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ - ../../include/cirGate.h ../../include/cirMgr.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h ../../include/gvNtk.h + ../../include/gvBitVec.h ../../include/gvIntType.h \ + ../../include/cirMgr.h ../../include/gvMsg.h ../../include/util.h \ + ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/sim/.depend.mak b/src/sim/.depend.mak index 4299e5d4..eae53eae 100644 --- a/src/sim/.depend.mak +++ b/src/sim/.depend.mak @@ -1,5 +1,5 @@ gvSimCmd.o: gvSimCmd.cpp gvSimCmd.h ../../include/gvCmdMgr.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ + ../../include/abcMgr.h ../../include/base/abc/abc.h \ ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ @@ -22,13 +22,17 @@ gvSimCmd.o: gvSimCmd.cpp gvSimCmd.h ../../include/gvCmdMgr.h \ ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/gvModMgr.h ../../include/gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h \ - ../../include/gvNtk.h ../../include/gvAbcMgr.h \ - ../../include/kernel/sigtools.h ../../include/kernel/yosys.h \ - /usr/include/tcl8.6/tcl.h /usr/include/tcl8.6/tclDecls.h \ - /usr/include/tcl8.6/tclPlatDecls.h ../../include/kernel/hashlib.h \ - ../../include/kernel/log.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/kernel/utils.h ../../include/kernel/yosys.h + ../../include/aig/ioa/ioa.h ../../include/cirGate.h \ + ../../include/cirDef.h ../../include/myHash.h ../../include/gvSat.h \ + ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirMgr.h ../../include/gvBitVec.h \ + ../../include/gvIntType.h ../../include/gvModMgr.h \ + ../../include/gvCmdMgr.h ../../include/gvMsg.h \ + ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ + /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ + ../../include/kernel/hashlib.h ../../include/kernel/log.h \ + ../../include/kernel/rtlil.h ../../include/kernel/constids.inc \ + ../../include/kernel/register.h ../../include/util.h \ + ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/sim/gvSimCmd.cpp b/src/sim/gvSimCmd.cpp index 087ae399..032ae5c9 100644 --- a/src/sim/gvSimCmd.cpp +++ b/src/sim/gvSimCmd.cpp @@ -6,11 +6,12 @@ #include #include -#include "gvAbcMgr.h" +#include "abcMgr.h" #include "gvModMgr.h" #include "gvMsg.h" -#include "util.h" #include "kernel/yosys.h" +#include "util.h" + USING_YOSYS_NAMESPACE bool initSimCmd() { diff --git a/src/vrf/.depend.mak b/src/vrf/.depend.mak index ed12a040..dddf2a32 100644 --- a/src/vrf/.depend.mak +++ b/src/vrf/.depend.mak @@ -1,5 +1,5 @@ gvVrfCmd.o: gvVrfCmd.cpp gvVrfCmd.h ../../include/gvCmdMgr.h \ - ../../include/gvAbcMgr.h ../../include/base/abc/abc.h \ + ../../include/abcMgr.h ../../include/base/abc/abc.h \ ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ @@ -22,8 +22,13 @@ gvVrfCmd.o: gvVrfCmd.cpp gvVrfCmd.h ../../include/gvCmdMgr.h \ ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvAbcNtk.h \ - ../../include/gvMsg.h ../../include/gvUsage.h ../../include/gvMsg.h \ + ../../include/aig/ioa/ioa.h ../../include/cirGate.h \ + ../../include/cirDef.h ../../include/myHash.h ../../include/gvSat.h \ + ../../include/SolverV.h ../../include/ProofV.h \ + ../../include/SolverTypesV.h ../../include/GlobalV.h \ + ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ + ../../include/cirMgr.h ../../include/gvBitVec.h \ ../../include/gvIntType.h ../../include/gvModMgr.h \ - ../../include/gvCmdMgr.h ../../include/util.h ../../include/rnGen.h \ + ../../include/gvCmdMgr.h ../../include/gvMsg.h ../../include/gvUsage.h \ + ../../include/gvMsg.h ../../include/util.h ../../include/rnGen.h \ ../../include/myUsage.h diff --git a/src/vrf/gvVrfCmd.cpp b/src/vrf/gvVrfCmd.cpp index 72bd703a..672936c3 100644 --- a/src/vrf/gvVrfCmd.cpp +++ b/src/vrf/gvVrfCmd.cpp @@ -9,13 +9,12 @@ #include #include -#include "gvAbcMgr.h" +#include "abcMgr.h" #include "gvModMgr.h" #include "gvMsg.h" #include "gvUsage.h" #include "util.h" - using namespace std; bool initVrfCmd() { From d9a1b484c160a414a925377f5bc80a94da13101a Mon Sep 17 00:00:00 2001 From: hchchiu Date: Tue, 12 Dec 2023 16:32:09 +0800 Subject: [PATCH 020/307] Update sim extension and sim command --- src/ext/sim.cc | 16 +++++++++++++--- src/sim/gvSimCmd.cpp | 34 ++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/ext/sim.cc b/src/ext/sim.cc index 4d67f499..8c91b7d4 100644 --- a/src/ext/sim.cc +++ b/src/ext/sim.cc @@ -232,10 +232,20 @@ struct randomSim : public Pass { { if (!stimulus) // if no stimulus is given, we generate a random one { - ofs << "upper_bound = pow(2, " << wire->width << ");\n"; - ofs << "random_value = rand() % upper_bound;\n"; - ofs << "top.p_" << wire_name << ".set(random_value)" + // (1) If there's a large-bits wire (e.g. 256-bits memory) that exceed "unsigned range (0 ~ 65535)", + // please slice it to smaller wires, otherwise will cause error in Yosys + // (2) Also, if assigns a wrong size value to wires (e.g. assign "pow(2, 2)" to "256-bits memory"), it will violate Yosys assertion + // TODO: preprocess the large-bits wire with ".slice()" and ".concat()" to assign value + if (wire->width > 16) { + log_error("There's a large-bits wire that exceed \"unsigned range (0 ~ 65535)\", please slice it to smaller wires all within 16 bits\n"); + } + else { + // randomly assign value + ofs << "upper_bound = pow(2, " << wire->width << ");\n"; + ofs << "random_value = rand() % upper_bound;\n"; + ofs << "top.p_" << wire_name << ".set(random_value)" << ";\n"; + } } else { ofs << "top.p_" << wire_name << ".set(stimulus_signal[cycle][idx])" << ";\n"; diff --git a/src/sim/gvSimCmd.cpp b/src/sim/gvSimCmd.cpp index 032ae5c9..dcd69b96 100644 --- a/src/sim/gvSimCmd.cpp +++ b/src/sim/gvSimCmd.cpp @@ -47,14 +47,20 @@ GVRandomSimCmd ::exec(const string& option) { command += " -v "; continue; } - if (myStrNCmp("-rst", token, 3) == 0) { + if (myStrNCmp("-reset", token, 3) == 0) { rst_set = true; ++i; rst = options[i]; + // error handling: Yosys will rename "_" to "__", so please don't name the reset signal with underline, e.g. "i_rst" + // TODO: fix the renaming rule in Yosys + if (find(rst.begin(), rst.end(), '_') != rst.end()) { + cout << "Please avoid naming the reset signal with underline, e.g. \"i_rst\" is illegal but \"rst\" is okay " << endl; + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, rst); + } command += " -reset " + rst; continue; } - if (myStrNCmp("-rst_n", token, 4) == 0) { + if (myStrNCmp("-n_reset", token, 3) == 0) { rst_n_set = true; ++i; rst_n = options[i]; @@ -65,6 +71,12 @@ GVRandomSimCmd ::exec(const string& option) { clk_set = true; ++i; clk = options[i]; + // error handling: Yosys will rename "_" to "__", so please don't name the clock signal with underline, e.g. "i_clk" + // TODO: fix the renaming rule in Yosys + if (find(clk.begin(), clk.end(), '_') != clk.end()) { + cout << "Please avoid naming the clock signal with underline, e.g. \"i_clk\" is illegal but \"clk\" is okay " << endl; + return GVCmdExec::errorOption(GV_CMD_OPT_ILLEGAL, clk); + } command += " -clk " + clk; continue; } @@ -117,11 +129,10 @@ GVRandomSimCmd ::exec(const string& option) { } void GVRandomSimCmd ::usage(const bool& verbose) const { - cout - << "Usage: RAndom Sim <-input file_name.v> [sim_cycle num_cycle_sim] " - "[-rst rst_name] [-rst_n rst_n_name] [-clk clk_name] " - "[-output out_file_name] [-v verbose print result] [-file stimulus]" - << endl; + cout << "Usage: RAndom Sim <-input file_name.v> [sim_cycle num_cycle_sim] " + "[-reset rst_name] [-n_reset rst_n_name] [-clk clk_name] " + "[-output out_file_name] [-v verbose print result] [-file stimulus]" + << endl; } void GVRandomSimCmd ::help() const { @@ -206,12 +217,8 @@ GVShowCmd::exec(const string& option) { "to read the file first !!\n "; return GV_CMD_EXEC_NOP; } - // string top_module_name = - // gvRTLDesign->getDesign()->top_module()->name.str().substr( - // 1, strlen(yosys_design->top_module()->name.c_str()) - 1); string top_module_name = - yosys_design->top_module()->name.str().substr( - 1, strlen(yosys_design->top_module()->name.c_str()) - 1); + yosys_design->top_module()->name.str().substr(1, strlen(yosys_design->top_module()->name.c_str()) - 1); run_pass("hierarchy -top " + top_module_name); run_pass("proc"); @@ -222,8 +229,7 @@ GVShowCmd::exec(const string& option) { return GV_CMD_EXEC_DONE; } void GVShowCmd::usage(const bool& verbose) const { - cout - << "Usage: SHow < -Vcd | -SCHematic >" << endl; + cout << "Usage: SHow < -Vcd | -SCHematic >" << endl; } void GVShowCmd::help() const { From ed18d88ed4e3be54ee80602440d434746cc7a3d0 Mon Sep 17 00:00:00 2001 From: hchchiu Date: Wed, 13 Dec 2023 05:12:51 +0800 Subject: [PATCH 021/307] Organzie the code and yosys script --- Makefile | 4 +- engine/yosys.script | 2 +- include/Alg.h | 1 - include/Alloc.h | 1 - include/Dimacs.h | 1 - include/File.h | 1 - include/Global.h | 1 - include/IntMap.h | 1 - include/IntTypes.h | 1 - include/Makefile | 1 - include/Map.h | 1 - include/Options.h | 1 - include/ParseUtils.h | 1 - include/Proof.h | 1 - include/Queue.h | 1 - include/Rnd.h | 1 - include/System.h | 1 - include/VarOrder.h | 1 - include/Vec.h | 1 - include/XAlloc.h | 1 - include/binding.h | 1 - include/bitpattern.h | 1 - include/boolector.h | 1 - include/cellaigs.h | 1 - include/celledges.h | 1 - include/celltypes.h | 1 - include/cmdCharDef.h | 1 - include/cmdParser.h | 1 - include/consteval.h | 1 - include/constids.inc | 1 - include/cost.h | 1 - include/ezminisat.h | 1 - include/ff.h | 1 - include/ffinit.h | 1 - include/ffmerge.h | 1 - include/fstdata.h | 1 - include/gmp.h | 2336 ------------ include/gmpxx.h | 3703 -------------------- include/gvAbcCmd.h | 1 - include/gvAbcMgr.h | 1 - include/gvAbcNtk.h | 1 - include/gvCmdComm.h | 1 - include/gvCmdMgr.h | 1 - include/gvIntType.h | 1 - include/gvModCmd.h | 1 - include/gvModMgr.h | 1 - include/gvMsg.h | 1 - include/gvNtkCmd.h | 1 - include/gvSimCmd.h | 1 - include/gvUsage.h | 1 - include/gvVrfCmd.h | 1 - include/hashlib.h | 1 - include/libyosys.so | 1 - include/log.h | 1 - include/macc.h | 1 - include/mem.h | 1 - include/modtools.h | 1 - include/myHashMap.h | 1 - include/myUsage.h | 1 - include/preproc.h | 1 - include/qcsat.h | 1 - include/quteRTL.h | 1 - include/register.h | 1 - include/rnGen.h | 1 - include/rtlil.h | 1 - include/sat.h | 1 - include/satgen.h | 1 - include/sigtools.h | 1 - include/timinginfo.h | 1 - include/util.h | 1 - include/utils.h | 1 - include/yosys.h | 1 - lib/lib.d | 0 src/abc/.depend.mak | 66 - src/abc/.extheader.mak | 7 - src/bdd/.depend.mak | 24 - src/bdd/.extheader.mak | 13 - src/cad/Makefile | 5 + src/cad/cadAlg.cpp | 4 + src/cad/cadAlg.h | 11 + src/cir/.depend.mak | 140 - src/cir/.extheader.mak | 16 - src/cir/cirAig.cpp | 2 +- src/cmd/.depend.mak | 5 - src/cmd/.extheader.mak | 7 - src/ext/sim.so | Bin 817840 -> 817896 bytes src/gvsat/.depend.mak | 22 - src/gvsat/.extheader.mak | 4 - src/itp/.depend.mak | 43 - src/itp/.extheader.mak | 7 - src/itp/gvSatMgr.cpp | 4 +- src/main/.depend.mak | 8 - src/main/.extheader.mak | 1 - src/mod/.depend.mak | 38 - src/mod/.extheader.mak | 7 - src/prove/.depend.mak | 43 - src/prove/.extheader.mak | 1 - src/sim/.depend.mak | 38 - src/sim/.extheader.mak | 4 - src/util/.depend.mak | 3 - src/util/.extheader.mak | 25 - src/vrf/.depend.mak | 34 - src/vrf/.extheader.mak | 4 - src/yosys/.depend.mak | 12 - src/yosys/.extheader.mak | 7 - src/yosys/Makefile | 2 +- src/yosys/{gvYosysCmd.cpp => yosysCmd.cpp} | 4 +- src/yosys/{gvYosysCmd.h => yosysCmd.h} | 0 src/yosys/{gvYosysMgr.cpp => yosysMgr.cpp} | 2 +- src/yosys/{gvYosysMgr.h => yosysMgr.h} | 0 110 files changed, 30 insertions(+), 6696 deletions(-) delete mode 120000 include/Alg.h delete mode 120000 include/Alloc.h delete mode 120000 include/Dimacs.h delete mode 120000 include/File.h delete mode 120000 include/Global.h delete mode 120000 include/IntMap.h delete mode 120000 include/IntTypes.h delete mode 120000 include/Makefile delete mode 120000 include/Map.h delete mode 120000 include/Options.h delete mode 120000 include/ParseUtils.h delete mode 120000 include/Proof.h delete mode 120000 include/Queue.h delete mode 120000 include/Rnd.h delete mode 120000 include/System.h delete mode 120000 include/VarOrder.h delete mode 120000 include/Vec.h delete mode 120000 include/XAlloc.h delete mode 120000 include/binding.h delete mode 120000 include/bitpattern.h delete mode 120000 include/boolector.h delete mode 120000 include/cellaigs.h delete mode 120000 include/celledges.h delete mode 120000 include/celltypes.h delete mode 120000 include/cmdCharDef.h delete mode 120000 include/cmdParser.h delete mode 120000 include/consteval.h delete mode 120000 include/constids.inc delete mode 120000 include/cost.h delete mode 120000 include/ezminisat.h delete mode 120000 include/ff.h delete mode 120000 include/ffinit.h delete mode 120000 include/ffmerge.h delete mode 120000 include/fstdata.h delete mode 100644 include/gmp.h delete mode 100644 include/gmpxx.h delete mode 120000 include/gvAbcCmd.h delete mode 120000 include/gvAbcMgr.h delete mode 120000 include/gvAbcNtk.h delete mode 120000 include/gvCmdComm.h delete mode 120000 include/gvCmdMgr.h delete mode 120000 include/gvIntType.h delete mode 120000 include/gvModCmd.h delete mode 120000 include/gvModMgr.h delete mode 120000 include/gvMsg.h delete mode 120000 include/gvNtkCmd.h delete mode 120000 include/gvSimCmd.h delete mode 120000 include/gvUsage.h delete mode 120000 include/gvVrfCmd.h delete mode 120000 include/hashlib.h delete mode 120000 include/libyosys.so delete mode 120000 include/log.h delete mode 120000 include/macc.h delete mode 120000 include/mem.h delete mode 120000 include/modtools.h delete mode 120000 include/myHashMap.h delete mode 120000 include/myUsage.h delete mode 120000 include/preproc.h delete mode 120000 include/qcsat.h delete mode 120000 include/quteRTL.h delete mode 120000 include/register.h delete mode 120000 include/rnGen.h delete mode 120000 include/rtlil.h delete mode 120000 include/sat.h delete mode 120000 include/satgen.h delete mode 120000 include/sigtools.h delete mode 120000 include/timinginfo.h delete mode 120000 include/util.h delete mode 120000 include/utils.h delete mode 120000 include/yosys.h delete mode 100644 lib/lib.d delete mode 100644 src/abc/.depend.mak delete mode 100644 src/abc/.extheader.mak delete mode 100644 src/bdd/.depend.mak delete mode 100644 src/bdd/.extheader.mak create mode 100644 src/cad/Makefile create mode 100644 src/cad/cadAlg.cpp create mode 100644 src/cad/cadAlg.h delete mode 100644 src/cir/.depend.mak delete mode 100644 src/cir/.extheader.mak delete mode 100644 src/cmd/.depend.mak delete mode 100644 src/cmd/.extheader.mak delete mode 100644 src/gvsat/.depend.mak delete mode 100644 src/gvsat/.extheader.mak delete mode 100644 src/itp/.depend.mak delete mode 100644 src/itp/.extheader.mak delete mode 100644 src/main/.depend.mak delete mode 100644 src/main/.extheader.mak delete mode 100644 src/mod/.depend.mak delete mode 100644 src/mod/.extheader.mak delete mode 100644 src/prove/.depend.mak delete mode 100644 src/prove/.extheader.mak delete mode 100644 src/sim/.depend.mak delete mode 100644 src/sim/.extheader.mak delete mode 100644 src/util/.depend.mak delete mode 100644 src/util/.extheader.mak delete mode 100644 src/vrf/.depend.mak delete mode 100644 src/vrf/.extheader.mak delete mode 100644 src/yosys/.depend.mak delete mode 100644 src/yosys/.extheader.mak rename src/yosys/{gvYosysCmd.cpp => yosysCmd.cpp} (93%) rename src/yosys/{gvYosysCmd.h => yosysCmd.h} (100%) rename src/yosys/{gvYosysMgr.cpp => yosysMgr.cpp} (94%) rename src/yosys/{gvYosysMgr.h => yosysMgr.h} (100%) diff --git a/Makefile b/Makefile index 956039fc..7b5d711e 100755 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -SRCPKGS = util cmd abc mod yosys bdd itp cir sim vrf ext prove gvsat -LIBPKGS = util cmd abc mod yosys bdd itp cir sim vrf prove gvsat +SRCPKGS = util cmd abc mod yosys bdd itp cir sim vrf ext prove gvsat cad +LIBPKGS = util cmd abc mod yosys bdd itp cir sim vrf prove gvsat cad MAIN = main diff --git a/engine/yosys.script b/engine/yosys.script index aa041166..d69c5736 100755 --- a/engine/yosys.script +++ b/engine/yosys.script @@ -10,7 +10,7 @@ git checkout yosys-0.35 # enable the libyosys.so flag sed -i -e "s/ENABLE_LIBYOSYS := 0/ENABLE_LIBYOSYS := 1/g" Makefile; # modify the libyosys.so path -sed -i -e "s/-install_name,\$(LIBDIR)\/libyosys.so/-install_name,\@rpath\/libyosys.so/g" Makefile; +sed -i -e "s/-install_name,\$(LIBDIR)\/libyosys.so/-install_name,\@rpath\/libyosyss.so/g" Makefile; sed -i -e "s/-Wl,-soname,\$(LIBDIR)\/libyosys.so//g" Makefile; # make "yosys" shared library diff --git a/include/Alg.h b/include/Alg.h deleted file mode 120000 index 76b58a6e..00000000 --- a/include/Alg.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/Alg.h \ No newline at end of file diff --git a/include/Alloc.h b/include/Alloc.h deleted file mode 120000 index 361a0e07..00000000 --- a/include/Alloc.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/Alloc.h \ No newline at end of file diff --git a/include/Dimacs.h b/include/Dimacs.h deleted file mode 120000 index a6a4b291..00000000 --- a/include/Dimacs.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/Dimacs.h \ No newline at end of file diff --git a/include/File.h b/include/File.h deleted file mode 120000 index a8557d15..00000000 --- a/include/File.h +++ /dev/null @@ -1 +0,0 @@ -../src/sat/File.h \ No newline at end of file diff --git a/include/Global.h b/include/Global.h deleted file mode 120000 index 42433d70..00000000 --- a/include/Global.h +++ /dev/null @@ -1 +0,0 @@ -../src/sat/Global.h \ No newline at end of file diff --git a/include/IntMap.h b/include/IntMap.h deleted file mode 120000 index da9f0009..00000000 --- a/include/IntMap.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/IntMap.h \ No newline at end of file diff --git a/include/IntTypes.h b/include/IntTypes.h deleted file mode 120000 index 39ccc3da..00000000 --- a/include/IntTypes.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/IntTypes.h \ No newline at end of file diff --git a/include/Makefile b/include/Makefile deleted file mode 120000 index f38fb1e2..00000000 --- a/include/Makefile +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/Makefile \ No newline at end of file diff --git a/include/Map.h b/include/Map.h deleted file mode 120000 index cb858141..00000000 --- a/include/Map.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/Map.h \ No newline at end of file diff --git a/include/Options.h b/include/Options.h deleted file mode 120000 index 71f48f65..00000000 --- a/include/Options.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/Options.h \ No newline at end of file diff --git a/include/ParseUtils.h b/include/ParseUtils.h deleted file mode 120000 index 2237bdc8..00000000 --- a/include/ParseUtils.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/ParseUtils.h \ No newline at end of file diff --git a/include/Proof.h b/include/Proof.h deleted file mode 120000 index 85617511..00000000 --- a/include/Proof.h +++ /dev/null @@ -1 +0,0 @@ -../src/sat/Proof.h \ No newline at end of file diff --git a/include/Queue.h b/include/Queue.h deleted file mode 120000 index 771c6be4..00000000 --- a/include/Queue.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/Queue.h \ No newline at end of file diff --git a/include/Rnd.h b/include/Rnd.h deleted file mode 120000 index 6bd8969d..00000000 --- a/include/Rnd.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/Rnd.h \ No newline at end of file diff --git a/include/System.h b/include/System.h deleted file mode 120000 index 5270c7d0..00000000 --- a/include/System.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/System.h \ No newline at end of file diff --git a/include/VarOrder.h b/include/VarOrder.h deleted file mode 120000 index a4921241..00000000 --- a/include/VarOrder.h +++ /dev/null @@ -1 +0,0 @@ -../src/sat/VarOrder.h \ No newline at end of file diff --git a/include/Vec.h b/include/Vec.h deleted file mode 120000 index 03ffe03a..00000000 --- a/include/Vec.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/Vec.h \ No newline at end of file diff --git a/include/XAlloc.h b/include/XAlloc.h deleted file mode 120000 index b0d84152..00000000 --- a/include/XAlloc.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/minisat/XAlloc.h \ No newline at end of file diff --git a/include/binding.h b/include/binding.h deleted file mode 120000 index fc86922b..00000000 --- a/include/binding.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/binding.h \ No newline at end of file diff --git a/include/bitpattern.h b/include/bitpattern.h deleted file mode 120000 index dee0d984..00000000 --- a/include/bitpattern.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/bitpattern.h \ No newline at end of file diff --git a/include/boolector.h b/include/boolector.h deleted file mode 120000 index f6fa9c0d..00000000 --- a/include/boolector.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/boolector/boolector.h \ No newline at end of file diff --git a/include/cellaigs.h b/include/cellaigs.h deleted file mode 120000 index 76dcb57e..00000000 --- a/include/cellaigs.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/cellaigs.h \ No newline at end of file diff --git a/include/celledges.h b/include/celledges.h deleted file mode 120000 index 45b37afc..00000000 --- a/include/celledges.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/celledges.h \ No newline at end of file diff --git a/include/celltypes.h b/include/celltypes.h deleted file mode 120000 index 7512b6b9..00000000 --- a/include/celltypes.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/celltypes.h \ No newline at end of file diff --git a/include/cmdCharDef.h b/include/cmdCharDef.h deleted file mode 120000 index e5242f07..00000000 --- a/include/cmdCharDef.h +++ /dev/null @@ -1 +0,0 @@ -../src/cmd/cmdCharDef.h \ No newline at end of file diff --git a/include/cmdParser.h b/include/cmdParser.h deleted file mode 120000 index a1136fdf..00000000 --- a/include/cmdParser.h +++ /dev/null @@ -1 +0,0 @@ -../src/cmd/cmdParser.h \ No newline at end of file diff --git a/include/consteval.h b/include/consteval.h deleted file mode 120000 index 7de04432..00000000 --- a/include/consteval.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/consteval.h \ No newline at end of file diff --git a/include/constids.inc b/include/constids.inc deleted file mode 120000 index d9fd3dab..00000000 --- a/include/constids.inc +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/constids.inc \ No newline at end of file diff --git a/include/cost.h b/include/cost.h deleted file mode 120000 index 766db1d9..00000000 --- a/include/cost.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/cost.h \ No newline at end of file diff --git a/include/ezminisat.h b/include/ezminisat.h deleted file mode 120000 index 0d881f1e..00000000 --- a/include/ezminisat.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/ezminisat.h \ No newline at end of file diff --git a/include/ff.h b/include/ff.h deleted file mode 120000 index 4386000e..00000000 --- a/include/ff.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/ff.h \ No newline at end of file diff --git a/include/ffinit.h b/include/ffinit.h deleted file mode 120000 index 7a0a3673..00000000 --- a/include/ffinit.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/ffinit.h \ No newline at end of file diff --git a/include/ffmerge.h b/include/ffmerge.h deleted file mode 120000 index df9ef56a..00000000 --- a/include/ffmerge.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/ffmerge.h \ No newline at end of file diff --git a/include/fstdata.h b/include/fstdata.h deleted file mode 120000 index b075442e..00000000 --- a/include/fstdata.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/fstdata.h \ No newline at end of file diff --git a/include/gmp.h b/include/gmp.h deleted file mode 100644 index c5258d47..00000000 --- a/include/gmp.h +++ /dev/null @@ -1,2336 +0,0 @@ -/* Definitions for GNU multiple precision functions. -*- mode: c -*- - -Copyright 1991, 1993-1997, 1999-2016, 2020 Free Software Foundation, Inc. - -This file is part of the GNU MP Library. - -The GNU MP Library is free software; you can redistribute it and/or modify -it under the terms of either: - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at your - option) any later version. - -or - - * the GNU General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - -or both in parallel, as here. - -The GNU MP Library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received copies of the GNU General Public License and the -GNU Lesser General Public License along with the GNU MP Library. If not, -see https://www.gnu.org/licenses/. */ - -#ifndef __GMP_H__ - -#if defined (__cplusplus) -#include /* for std::istream, std::ostream, std::string */ -#include -#endif - - -/* Instantiated by configure. */ -#if ! defined (__GMP_WITHIN_CONFIGURE) -#define __GMP_HAVE_HOST_CPU_FAMILY_power 0 -#define __GMP_HAVE_HOST_CPU_FAMILY_powerpc 0 -#define GMP_LIMB_BITS 64 -#define GMP_NAIL_BITS 0 -#endif -#define GMP_NUMB_BITS (GMP_LIMB_BITS - GMP_NAIL_BITS) -#define GMP_NUMB_MASK ((~ __GMP_CAST (mp_limb_t, 0)) >> GMP_NAIL_BITS) -#define GMP_NUMB_MAX GMP_NUMB_MASK -#define GMP_NAIL_MASK (~ GMP_NUMB_MASK) - - -#ifndef __GNU_MP__ -#define __GNU_MP__ 6 - -#include /* for size_t */ -#include - -/* Instantiated by configure. */ -#if ! defined (__GMP_WITHIN_CONFIGURE) -/* #undef _LONG_LONG_LIMB */ -#define __GMP_LIBGMP_DLL 0 -#endif - - -/* __GMP_DECLSPEC supports Windows DLL versions of libgmp, and is empty in - all other circumstances. - - When compiling objects for libgmp, __GMP_DECLSPEC is an export directive, - or when compiling for an application it's an import directive. The two - cases are differentiated by __GMP_WITHIN_GMP defined by the GMP Makefiles - (and not defined from an application). - - __GMP_DECLSPEC_XX is similarly used for libgmpxx. __GMP_WITHIN_GMPXX - indicates when building libgmpxx, and in that case libgmpxx functions are - exports, but libgmp functions which might get called are imports. - - Libtool DLL_EXPORT define is not used. - - There's no attempt to support GMP built both static and DLL. Doing so - would mean applications would have to tell us which of the two is going - to be used when linking, and that seems very tedious and error prone if - using GMP by hand, and equally tedious from a package since autoconf and - automake don't give much help. - - __GMP_DECLSPEC is required on all documented global functions and - variables, the various internals in gmp-impl.h etc can be left unadorned. - But internals used by the test programs or speed measuring programs - should have __GMP_DECLSPEC, and certainly constants or variables must - have it or the wrong address will be resolved. - - In gcc __declspec can go at either the start or end of a prototype. - - In Microsoft C __declspec must go at the start, or after the type like - void __declspec(...) *foo()". There's no __dllexport or anything to - guard against someone foolish #defining dllexport. _export used to be - available, but no longer. - - In Borland C _export still exists, but needs to go after the type, like - "void _export foo();". Would have to change the __GMP_DECLSPEC syntax to - make use of that. Probably more trouble than it's worth. */ - -#if defined (__GNUC__) -#define __GMP_DECLSPEC_EXPORT __declspec(__dllexport__) -#define __GMP_DECLSPEC_IMPORT __declspec(__dllimport__) -#endif -#if defined (_MSC_VER) || defined (__BORLANDC__) -#define __GMP_DECLSPEC_EXPORT __declspec(dllexport) -#define __GMP_DECLSPEC_IMPORT __declspec(dllimport) -#endif -#ifdef __WATCOMC__ -#define __GMP_DECLSPEC_EXPORT __export -#define __GMP_DECLSPEC_IMPORT __import -#endif -#ifdef __IBMC__ -#define __GMP_DECLSPEC_EXPORT _Export -#define __GMP_DECLSPEC_IMPORT _Import -#endif - -#if __GMP_LIBGMP_DLL -#ifdef __GMP_WITHIN_GMP -/* compiling to go into a DLL libgmp */ -#define __GMP_DECLSPEC __GMP_DECLSPEC_EXPORT -#else -/* compiling to go into an application which will link to a DLL libgmp */ -#define __GMP_DECLSPEC __GMP_DECLSPEC_IMPORT -#endif -#else -/* all other cases */ -#define __GMP_DECLSPEC -#endif - - -#ifdef __GMP_SHORT_LIMB -typedef unsigned int mp_limb_t; -typedef int mp_limb_signed_t; -#else -#ifdef _LONG_LONG_LIMB -typedef unsigned long long int mp_limb_t; -typedef long long int mp_limb_signed_t; -#else -typedef unsigned long int mp_limb_t; -typedef long int mp_limb_signed_t; -#endif -#endif -typedef unsigned long int mp_bitcnt_t; - -/* For reference, note that the name __mpz_struct gets into C++ mangled - function names, which means although the "__" suggests an internal, we - must leave this name for binary compatibility. */ -typedef struct -{ - int _mp_alloc; /* Number of *limbs* allocated and pointed - to by the _mp_d field. */ - int _mp_size; /* abs(_mp_size) is the number of limbs the - last field points to. If _mp_size is - negative this is a negative number. */ - mp_limb_t *_mp_d; /* Pointer to the limbs. */ -} __mpz_struct; - -#endif /* __GNU_MP__ */ - - -typedef __mpz_struct MP_INT; /* gmp 1 source compatibility */ -typedef __mpz_struct mpz_t[1]; - -typedef mp_limb_t * mp_ptr; -typedef const mp_limb_t * mp_srcptr; -#if defined (_CRAY) && ! defined (_CRAYMPP) -/* plain `int' is much faster (48 bits) */ -#define __GMP_MP_SIZE_T_INT 1 -typedef int mp_size_t; -typedef int mp_exp_t; -#else -#define __GMP_MP_SIZE_T_INT 0 -typedef long int mp_size_t; -typedef long int mp_exp_t; -#endif - -typedef struct -{ - __mpz_struct _mp_num; - __mpz_struct _mp_den; -} __mpq_struct; - -typedef __mpq_struct MP_RAT; /* gmp 1 source compatibility */ -typedef __mpq_struct mpq_t[1]; - -typedef struct -{ - int _mp_prec; /* Max precision, in number of `mp_limb_t's. - Set by mpf_init and modified by - mpf_set_prec. The area pointed to by the - _mp_d field contains `prec' + 1 limbs. */ - int _mp_size; /* abs(_mp_size) is the number of limbs the - last field points to. If _mp_size is - negative this is a negative number. */ - mp_exp_t _mp_exp; /* Exponent, in the base of `mp_limb_t'. */ - mp_limb_t *_mp_d; /* Pointer to the limbs. */ -} __mpf_struct; - -/* typedef __mpf_struct MP_FLOAT; */ -typedef __mpf_struct mpf_t[1]; - -/* Available random number generation algorithms. */ -typedef enum -{ - GMP_RAND_ALG_DEFAULT = 0, - GMP_RAND_ALG_LC = GMP_RAND_ALG_DEFAULT /* Linear congruential. */ -} gmp_randalg_t; - -/* Random state struct. */ -typedef struct -{ - mpz_t _mp_seed; /* _mp_d member points to state of the generator. */ - gmp_randalg_t _mp_alg; /* Currently unused. */ - union { - void *_mp_lc; /* Pointer to function pointers structure. */ - } _mp_algdata; -} __gmp_randstate_struct; -typedef __gmp_randstate_struct gmp_randstate_t[1]; - -/* Types for function declarations in gmp files. */ -/* ??? Should not pollute user name space with these ??? */ -typedef const __mpz_struct *mpz_srcptr; -typedef __mpz_struct *mpz_ptr; -typedef const __mpf_struct *mpf_srcptr; -typedef __mpf_struct *mpf_ptr; -typedef const __mpq_struct *mpq_srcptr; -typedef __mpq_struct *mpq_ptr; - - -#if __GMP_LIBGMP_DLL -#ifdef __GMP_WITHIN_GMPXX -/* compiling to go into a DLL libgmpxx */ -#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_EXPORT -#else -/* compiling to go into a application which will link to a DLL libgmpxx */ -#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_IMPORT -#endif -#else -/* all other cases */ -#define __GMP_DECLSPEC_XX -#endif - - -#ifndef __MPN -#define __MPN(x) __gmpn_##x -#endif - -/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4, - defines EOF but not FILE. */ -#if defined (FILE) \ - || defined (H_STDIO) \ - || defined (_H_STDIO) /* AIX */ \ - || defined (_STDIO_H) /* glibc, Sun, SCO */ \ - || defined (_STDIO_H_) /* BSD, OSF */ \ - || defined (__STDIO_H) /* Borland */ \ - || defined (__STDIO_H__) /* IRIX */ \ - || defined (_STDIO_INCLUDED) /* HPUX */ \ - || defined (__dj_include_stdio_h_) /* DJGPP */ \ - || defined (_FILE_DEFINED) /* Microsoft */ \ - || defined (__STDIO__) /* Apple MPW MrC */ \ - || defined (_MSL_STDIO_H) /* Metrowerks */ \ - || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ - || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \ - || defined (__STDIO_LOADED) /* VMS */ \ - || defined (__DEFINED_FILE) /* musl */ -#define _GMP_H_HAVE_FILE 1 -#endif - -/* In ISO C, if a prototype involving "struct obstack *" is given without - that structure defined, then the struct is scoped down to just the - prototype, causing a conflict if it's subsequently defined for real. So - only give prototypes if we've got obstack.h. */ -#if defined (_OBSTACK_H) /* glibc */ -#define _GMP_H_HAVE_OBSTACK 1 -#endif - -/* The prototypes for gmp_vprintf etc are provided only if va_list is defined, - via an application having included . Usually va_list is a typedef - so can't be tested directly, but C99 specifies that va_start is a macro. - - will define some sort of va_list for vprintf and vfprintf, but - let's not bother trying to use that since it's not standard and since - application uses for gmp_vprintf etc will almost certainly require the - whole anyway. */ - -#ifdef va_start -#define _GMP_H_HAVE_VA_LIST 1 -#endif - -/* Test for gcc >= maj.min, as per __GNUC_PREREQ in glibc */ -#if defined (__GNUC__) && defined (__GNUC_MINOR__) -#define __GMP_GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -#else -#define __GMP_GNUC_PREREQ(maj, min) 0 -#endif - -/* "pure" is in gcc 2.96 and up, see "(gcc)Function Attributes". Basically - it means a function does nothing but examine its arguments and memory - (global or via arguments) to generate a return value, but changes nothing - and has no side-effects. __GMP_NO_ATTRIBUTE_CONST_PURE lets - tune/common.c etc turn this off when trying to write timing loops. */ -#if __GMP_GNUC_PREREQ (2,96) && ! defined (__GMP_NO_ATTRIBUTE_CONST_PURE) -#define __GMP_ATTRIBUTE_PURE __attribute__ ((__pure__)) -#else -#define __GMP_ATTRIBUTE_PURE -#endif - - -/* __GMP_CAST allows us to use static_cast in C++, so our macros are clean - to "g++ -Wold-style-cast". - - Casts in "extern inline" code within an extern "C" block don't induce - these warnings, so __GMP_CAST only needs to be used on documented - macros. */ - -#ifdef __cplusplus -#define __GMP_CAST(type, expr) (static_cast (expr)) -#else -#define __GMP_CAST(type, expr) ((type) (expr)) -#endif - - -/* An empty "throw ()" means the function doesn't throw any C++ exceptions, - this can save some stack frame info in applications. - - Currently it's given only on functions which never divide-by-zero etc, - don't allocate memory, and are expected to never need to allocate memory. - This leaves open the possibility of a C++ throw from a future GMP - exceptions scheme. - - mpz_set_ui etc are omitted to leave open the lazy allocation scheme - described in doc/tasks.html. mpz_get_d etc are omitted to leave open - exceptions for float overflows. - - Note that __GMP_NOTHROW must be given on any inlines the same as on their - prototypes (for g++ at least, where they're used together). Note also - that g++ 3.0 demands that __GMP_NOTHROW is before other attributes like - __GMP_ATTRIBUTE_PURE. */ - -#if defined (__cplusplus) -#if __cplusplus >= 201103L -#define __GMP_NOTHROW noexcept -#else -#define __GMP_NOTHROW throw () -#endif -#else -#define __GMP_NOTHROW -#endif - - -/* PORTME: What other compilers have a useful "extern inline"? "static - inline" would be an acceptable substitute if the compiler (or linker) - discards unused statics. */ - - /* gcc has __inline__ in all modes, including strict ansi. Give a prototype - for an inline too, so as to correctly specify "dllimport" on windows, in - case the function is called rather than inlined. - GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 - inline semantics, unless -fgnu89-inline is used. */ -#ifdef __GNUC__ -#if (defined __GNUC_STDC_INLINE__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 2) \ - || (defined __GNUC_GNU_INLINE__ && defined __cplusplus) -#define __GMP_EXTERN_INLINE extern __inline__ __attribute__ ((__gnu_inline__)) -#else -#define __GMP_EXTERN_INLINE extern __inline__ -#endif -#define __GMP_INLINE_PROTOTYPES 1 -#endif - -/* DEC C (eg. version 5.9) supports "static __inline foo()", even in -std1 - strict ANSI mode. Inlining is done even when not optimizing (ie. -O0 - mode, which is the default), but an unnecessary local copy of foo is - emitted unless -O is used. "extern __inline" is accepted, but the - "extern" appears to be ignored, ie. it becomes a plain global function - but which is inlined within its file. Don't know if all old versions of - DEC C supported __inline, but as a start let's do the right thing for - current versions. */ -#ifdef __DECC -#define __GMP_EXTERN_INLINE static __inline -#endif - -/* SCO OpenUNIX 8 cc supports "static inline foo()" but not in -Xc strict - ANSI mode (__STDC__ is 1 in that mode). Inlining only actually takes - place under -O. Without -O "foo" seems to be emitted whether it's used - or not, which is wasteful. "extern inline foo()" isn't useful, the - "extern" is apparently ignored, so foo is inlined if possible but also - emitted as a global, which causes multiple definition errors when - building a shared libgmp. */ -#ifdef __SCO_VERSION__ -#if __SCO_VERSION__ > 400000000 && __STDC__ != 1 \ - && ! defined (__GMP_EXTERN_INLINE) -#define __GMP_EXTERN_INLINE static inline -#endif -#endif - -/* Microsoft's C compiler accepts __inline */ -#ifdef _MSC_VER -#define __GMP_EXTERN_INLINE __inline -#endif - -/* Recent enough Sun C compilers want "inline" */ -#if defined (__SUNPRO_C) && __SUNPRO_C >= 0x560 \ - && ! defined (__GMP_EXTERN_INLINE) -#define __GMP_EXTERN_INLINE inline -#endif - -/* Somewhat older Sun C compilers want "static inline" */ -#if defined (__SUNPRO_C) && __SUNPRO_C >= 0x540 \ - && ! defined (__GMP_EXTERN_INLINE) -#define __GMP_EXTERN_INLINE static inline -#endif - - -/* C++ always has "inline" and since it's a normal feature the linker should - discard duplicate non-inlined copies, or if it doesn't then that's a - problem for everyone, not just GMP. */ -#if defined (__cplusplus) && ! defined (__GMP_EXTERN_INLINE) -#define __GMP_EXTERN_INLINE inline -#endif - -/* Don't do any inlining within a configure run, since if the compiler ends - up emitting copies of the code into the object file it can end up - demanding the various support routines (like mpn_popcount) for linking, - making the "alloca" test and perhaps others fail. And on hppa ia64 a - pre-release gcc 3.2 was seen not respecting the "extern" in "extern - __inline__", triggering this problem too. */ -#if defined (__GMP_WITHIN_CONFIGURE) && ! __GMP_WITHIN_CONFIGURE_INLINE -#undef __GMP_EXTERN_INLINE -#endif - -/* By default, don't give a prototype when there's going to be an inline - version. Note in particular that Cray C++ objects to the combination of - prototype and inline. */ -#ifdef __GMP_EXTERN_INLINE -#ifndef __GMP_INLINE_PROTOTYPES -#define __GMP_INLINE_PROTOTYPES 0 -#endif -#else -#define __GMP_INLINE_PROTOTYPES 1 -#endif - - -#define __GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) -#define __GMP_MAX(h,i) ((h) > (i) ? (h) : (i)) - - -/* __builtin_expect is in gcc 3.0, and not in 2.95. */ -#if __GMP_GNUC_PREREQ (3,0) -#define __GMP_LIKELY(cond) __builtin_expect ((cond) != 0, 1) -#define __GMP_UNLIKELY(cond) __builtin_expect ((cond) != 0, 0) -#else -#define __GMP_LIKELY(cond) (cond) -#define __GMP_UNLIKELY(cond) (cond) -#endif - -#ifdef _CRAY -#define __GMP_CRAY_Pragma(str) _Pragma (str) -#else -#define __GMP_CRAY_Pragma(str) -#endif - - -/* Allow direct user access to numerator and denominator of an mpq_t object. */ -#define mpq_numref(Q) (&((Q)->_mp_num)) -#define mpq_denref(Q) (&((Q)->_mp_den)) - - -#if defined (__cplusplus) -extern "C" { -using std::FILE; -#endif - -#define mp_set_memory_functions __gmp_set_memory_functions -__GMP_DECLSPEC void mp_set_memory_functions (void *(*) (size_t), - void *(*) (void *, size_t, size_t), - void (*) (void *, size_t)) __GMP_NOTHROW; - -#define mp_get_memory_functions __gmp_get_memory_functions -__GMP_DECLSPEC void mp_get_memory_functions (void *(**) (size_t), - void *(**) (void *, size_t, size_t), - void (**) (void *, size_t)) __GMP_NOTHROW; - -#define mp_bits_per_limb __gmp_bits_per_limb -__GMP_DECLSPEC extern const int mp_bits_per_limb; - -#define gmp_errno __gmp_errno -__GMP_DECLSPEC extern int gmp_errno; - -#define gmp_version __gmp_version -__GMP_DECLSPEC extern const char * const gmp_version; - - -/**************** Random number routines. ****************/ - -/* obsolete */ -#define gmp_randinit __gmp_randinit -__GMP_DECLSPEC void gmp_randinit (gmp_randstate_t, gmp_randalg_t, ...); - -#define gmp_randinit_default __gmp_randinit_default -__GMP_DECLSPEC void gmp_randinit_default (gmp_randstate_t); - -#define gmp_randinit_lc_2exp __gmp_randinit_lc_2exp -__GMP_DECLSPEC void gmp_randinit_lc_2exp (gmp_randstate_t, mpz_srcptr, unsigned long int, mp_bitcnt_t); - -#define gmp_randinit_lc_2exp_size __gmp_randinit_lc_2exp_size -__GMP_DECLSPEC int gmp_randinit_lc_2exp_size (gmp_randstate_t, mp_bitcnt_t); - -#define gmp_randinit_mt __gmp_randinit_mt -__GMP_DECLSPEC void gmp_randinit_mt (gmp_randstate_t); - -#define gmp_randinit_set __gmp_randinit_set -__GMP_DECLSPEC void gmp_randinit_set (gmp_randstate_t, const __gmp_randstate_struct *); - -#define gmp_randseed __gmp_randseed -__GMP_DECLSPEC void gmp_randseed (gmp_randstate_t, mpz_srcptr); - -#define gmp_randseed_ui __gmp_randseed_ui -__GMP_DECLSPEC void gmp_randseed_ui (gmp_randstate_t, unsigned long int); - -#define gmp_randclear __gmp_randclear -__GMP_DECLSPEC void gmp_randclear (gmp_randstate_t); - -#define gmp_urandomb_ui __gmp_urandomb_ui -__GMP_DECLSPEC unsigned long gmp_urandomb_ui (gmp_randstate_t, unsigned long); - -#define gmp_urandomm_ui __gmp_urandomm_ui -__GMP_DECLSPEC unsigned long gmp_urandomm_ui (gmp_randstate_t, unsigned long); - - -/**************** Formatted output routines. ****************/ - -#define gmp_asprintf __gmp_asprintf -__GMP_DECLSPEC int gmp_asprintf (char **, const char *, ...); - -#define gmp_fprintf __gmp_fprintf -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC int gmp_fprintf (FILE *, const char *, ...); -#endif - -#define gmp_obstack_printf __gmp_obstack_printf -#if defined (_GMP_H_HAVE_OBSTACK) -__GMP_DECLSPEC int gmp_obstack_printf (struct obstack *, const char *, ...); -#endif - -#define gmp_obstack_vprintf __gmp_obstack_vprintf -#if defined (_GMP_H_HAVE_OBSTACK) && defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_obstack_vprintf (struct obstack *, const char *, va_list); -#endif - -#define gmp_printf __gmp_printf -__GMP_DECLSPEC int gmp_printf (const char *, ...); - -#define gmp_snprintf __gmp_snprintf -__GMP_DECLSPEC int gmp_snprintf (char *, size_t, const char *, ...); - -#define gmp_sprintf __gmp_sprintf -__GMP_DECLSPEC int gmp_sprintf (char *, const char *, ...); - -#define gmp_vasprintf __gmp_vasprintf -#if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vasprintf (char **, const char *, va_list); -#endif - -#define gmp_vfprintf __gmp_vfprintf -#if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vfprintf (FILE *, const char *, va_list); -#endif - -#define gmp_vprintf __gmp_vprintf -#if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vprintf (const char *, va_list); -#endif - -#define gmp_vsnprintf __gmp_vsnprintf -#if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vsnprintf (char *, size_t, const char *, va_list); -#endif - -#define gmp_vsprintf __gmp_vsprintf -#if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vsprintf (char *, const char *, va_list); -#endif - - -/**************** Formatted input routines. ****************/ - -#define gmp_fscanf __gmp_fscanf -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC int gmp_fscanf (FILE *, const char *, ...); -#endif - -#define gmp_scanf __gmp_scanf -__GMP_DECLSPEC int gmp_scanf (const char *, ...); - -#define gmp_sscanf __gmp_sscanf -__GMP_DECLSPEC int gmp_sscanf (const char *, const char *, ...); - -#define gmp_vfscanf __gmp_vfscanf -#if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vfscanf (FILE *, const char *, va_list); -#endif - -#define gmp_vscanf __gmp_vscanf -#if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vscanf (const char *, va_list); -#endif - -#define gmp_vsscanf __gmp_vsscanf -#if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vsscanf (const char *, const char *, va_list); -#endif - - -/**************** Integer (i.e. Z) routines. ****************/ - -#define _mpz_realloc __gmpz_realloc -#define mpz_realloc __gmpz_realloc -__GMP_DECLSPEC void *_mpz_realloc (mpz_ptr, mp_size_t); - -#define mpz_abs __gmpz_abs -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_abs) -__GMP_DECLSPEC void mpz_abs (mpz_ptr, mpz_srcptr); -#endif - -#define mpz_add __gmpz_add -__GMP_DECLSPEC void mpz_add (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_add_ui __gmpz_add_ui -__GMP_DECLSPEC void mpz_add_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_addmul __gmpz_addmul -__GMP_DECLSPEC void mpz_addmul (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_addmul_ui __gmpz_addmul_ui -__GMP_DECLSPEC void mpz_addmul_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_and __gmpz_and -__GMP_DECLSPEC void mpz_and (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_array_init __gmpz_array_init -__GMP_DECLSPEC void mpz_array_init (mpz_ptr, mp_size_t, mp_size_t); - -#define mpz_bin_ui __gmpz_bin_ui -__GMP_DECLSPEC void mpz_bin_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_bin_uiui __gmpz_bin_uiui -__GMP_DECLSPEC void mpz_bin_uiui (mpz_ptr, unsigned long int, unsigned long int); - -#define mpz_cdiv_q __gmpz_cdiv_q -__GMP_DECLSPEC void mpz_cdiv_q (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_cdiv_q_2exp __gmpz_cdiv_q_2exp -__GMP_DECLSPEC void mpz_cdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); - -#define mpz_cdiv_q_ui __gmpz_cdiv_q_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_q_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_cdiv_qr __gmpz_cdiv_qr -__GMP_DECLSPEC void mpz_cdiv_qr (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_cdiv_qr_ui __gmpz_cdiv_qr_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_qr_ui (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_cdiv_r __gmpz_cdiv_r -__GMP_DECLSPEC void mpz_cdiv_r (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_cdiv_r_2exp __gmpz_cdiv_r_2exp -__GMP_DECLSPEC void mpz_cdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); - -#define mpz_cdiv_r_ui __gmpz_cdiv_r_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_r_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_cdiv_ui __gmpz_cdiv_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_ui (mpz_srcptr, unsigned long int) __GMP_ATTRIBUTE_PURE; - -#define mpz_clear __gmpz_clear -__GMP_DECLSPEC void mpz_clear (mpz_ptr); - -#define mpz_clears __gmpz_clears -__GMP_DECLSPEC void mpz_clears (mpz_ptr, ...); - -#define mpz_clrbit __gmpz_clrbit -__GMP_DECLSPEC void mpz_clrbit (mpz_ptr, mp_bitcnt_t); - -#define mpz_cmp __gmpz_cmp -__GMP_DECLSPEC int mpz_cmp (mpz_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_cmp_d __gmpz_cmp_d -__GMP_DECLSPEC int mpz_cmp_d (mpz_srcptr, double) __GMP_ATTRIBUTE_PURE; - -#define _mpz_cmp_si __gmpz_cmp_si -__GMP_DECLSPEC int _mpz_cmp_si (mpz_srcptr, signed long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define _mpz_cmp_ui __gmpz_cmp_ui -__GMP_DECLSPEC int _mpz_cmp_ui (mpz_srcptr, unsigned long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_cmpabs __gmpz_cmpabs -__GMP_DECLSPEC int mpz_cmpabs (mpz_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_cmpabs_d __gmpz_cmpabs_d -__GMP_DECLSPEC int mpz_cmpabs_d (mpz_srcptr, double) __GMP_ATTRIBUTE_PURE; - -#define mpz_cmpabs_ui __gmpz_cmpabs_ui -__GMP_DECLSPEC int mpz_cmpabs_ui (mpz_srcptr, unsigned long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_com __gmpz_com -__GMP_DECLSPEC void mpz_com (mpz_ptr, mpz_srcptr); - -#define mpz_combit __gmpz_combit -__GMP_DECLSPEC void mpz_combit (mpz_ptr, mp_bitcnt_t); - -#define mpz_congruent_p __gmpz_congruent_p -__GMP_DECLSPEC int mpz_congruent_p (mpz_srcptr, mpz_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; - -#define mpz_congruent_2exp_p __gmpz_congruent_2exp_p -__GMP_DECLSPEC int mpz_congruent_2exp_p (mpz_srcptr, mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_congruent_ui_p __gmpz_congruent_ui_p -__GMP_DECLSPEC int mpz_congruent_ui_p (mpz_srcptr, unsigned long, unsigned long) __GMP_ATTRIBUTE_PURE; - -#define mpz_divexact __gmpz_divexact -__GMP_DECLSPEC void mpz_divexact (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_divexact_ui __gmpz_divexact_ui -__GMP_DECLSPEC void mpz_divexact_ui (mpz_ptr, mpz_srcptr, unsigned long); - -#define mpz_divisible_p __gmpz_divisible_p -__GMP_DECLSPEC int mpz_divisible_p (mpz_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; - -#define mpz_divisible_ui_p __gmpz_divisible_ui_p -__GMP_DECLSPEC int mpz_divisible_ui_p (mpz_srcptr, unsigned long) __GMP_ATTRIBUTE_PURE; - -#define mpz_divisible_2exp_p __gmpz_divisible_2exp_p -__GMP_DECLSPEC int mpz_divisible_2exp_p (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_dump __gmpz_dump -__GMP_DECLSPEC void mpz_dump (mpz_srcptr); - -#define mpz_export __gmpz_export -__GMP_DECLSPEC void *mpz_export (void *, size_t *, int, size_t, int, size_t, mpz_srcptr); - -#define mpz_fac_ui __gmpz_fac_ui -__GMP_DECLSPEC void mpz_fac_ui (mpz_ptr, unsigned long int); - -#define mpz_2fac_ui __gmpz_2fac_ui -__GMP_DECLSPEC void mpz_2fac_ui (mpz_ptr, unsigned long int); - -#define mpz_mfac_uiui __gmpz_mfac_uiui -__GMP_DECLSPEC void mpz_mfac_uiui (mpz_ptr, unsigned long int, unsigned long int); - -#define mpz_primorial_ui __gmpz_primorial_ui -__GMP_DECLSPEC void mpz_primorial_ui (mpz_ptr, unsigned long int); - -#define mpz_fdiv_q __gmpz_fdiv_q -__GMP_DECLSPEC void mpz_fdiv_q (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_fdiv_q_2exp __gmpz_fdiv_q_2exp -__GMP_DECLSPEC void mpz_fdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); - -#define mpz_fdiv_q_ui __gmpz_fdiv_q_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_q_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_fdiv_qr __gmpz_fdiv_qr -__GMP_DECLSPEC void mpz_fdiv_qr (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_fdiv_qr_ui __gmpz_fdiv_qr_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_qr_ui (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_fdiv_r __gmpz_fdiv_r -__GMP_DECLSPEC void mpz_fdiv_r (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_fdiv_r_2exp __gmpz_fdiv_r_2exp -__GMP_DECLSPEC void mpz_fdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); - -#define mpz_fdiv_r_ui __gmpz_fdiv_r_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_r_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_fdiv_ui __gmpz_fdiv_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_ui (mpz_srcptr, unsigned long int) __GMP_ATTRIBUTE_PURE; - -#define mpz_fib_ui __gmpz_fib_ui -__GMP_DECLSPEC void mpz_fib_ui (mpz_ptr, unsigned long int); - -#define mpz_fib2_ui __gmpz_fib2_ui -__GMP_DECLSPEC void mpz_fib2_ui (mpz_ptr, mpz_ptr, unsigned long int); - -#define mpz_fits_sint_p __gmpz_fits_sint_p -__GMP_DECLSPEC int mpz_fits_sint_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_fits_slong_p __gmpz_fits_slong_p -__GMP_DECLSPEC int mpz_fits_slong_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_fits_sshort_p __gmpz_fits_sshort_p -__GMP_DECLSPEC int mpz_fits_sshort_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_fits_uint_p __gmpz_fits_uint_p -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_uint_p) -__GMP_DECLSPEC int mpz_fits_uint_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_fits_ulong_p __gmpz_fits_ulong_p -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ulong_p) -__GMP_DECLSPEC int mpz_fits_ulong_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_fits_ushort_p __gmpz_fits_ushort_p -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ushort_p) -__GMP_DECLSPEC int mpz_fits_ushort_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_gcd __gmpz_gcd -__GMP_DECLSPEC void mpz_gcd (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_gcd_ui __gmpz_gcd_ui -__GMP_DECLSPEC unsigned long int mpz_gcd_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_gcdext __gmpz_gcdext -__GMP_DECLSPEC void mpz_gcdext (mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_get_d __gmpz_get_d -__GMP_DECLSPEC double mpz_get_d (mpz_srcptr) __GMP_ATTRIBUTE_PURE; - -#define mpz_get_d_2exp __gmpz_get_d_2exp -__GMP_DECLSPEC double mpz_get_d_2exp (signed long int *, mpz_srcptr); - -#define mpz_get_si __gmpz_get_si -__GMP_DECLSPEC /* signed */ long int mpz_get_si (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_get_str __gmpz_get_str -__GMP_DECLSPEC char *mpz_get_str (char *, int, mpz_srcptr); - -#define mpz_get_ui __gmpz_get_ui -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_get_ui) -__GMP_DECLSPEC unsigned long int mpz_get_ui (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_getlimbn __gmpz_getlimbn -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_getlimbn) -__GMP_DECLSPEC mp_limb_t mpz_getlimbn (mpz_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_hamdist __gmpz_hamdist -__GMP_DECLSPEC mp_bitcnt_t mpz_hamdist (mpz_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_import __gmpz_import -__GMP_DECLSPEC void mpz_import (mpz_ptr, size_t, int, size_t, int, size_t, const void *); - -#define mpz_init __gmpz_init -__GMP_DECLSPEC void mpz_init (mpz_ptr) __GMP_NOTHROW; - -#define mpz_init2 __gmpz_init2 -__GMP_DECLSPEC void mpz_init2 (mpz_ptr, mp_bitcnt_t); - -#define mpz_inits __gmpz_inits -__GMP_DECLSPEC void mpz_inits (mpz_ptr, ...) __GMP_NOTHROW; - -#define mpz_init_set __gmpz_init_set -__GMP_DECLSPEC void mpz_init_set (mpz_ptr, mpz_srcptr); - -#define mpz_init_set_d __gmpz_init_set_d -__GMP_DECLSPEC void mpz_init_set_d (mpz_ptr, double); - -#define mpz_init_set_si __gmpz_init_set_si -__GMP_DECLSPEC void mpz_init_set_si (mpz_ptr, signed long int); - -#define mpz_init_set_str __gmpz_init_set_str -__GMP_DECLSPEC int mpz_init_set_str (mpz_ptr, const char *, int); - -#define mpz_init_set_ui __gmpz_init_set_ui -__GMP_DECLSPEC void mpz_init_set_ui (mpz_ptr, unsigned long int); - -#define mpz_inp_raw __gmpz_inp_raw -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_inp_raw (mpz_ptr, FILE *); -#endif - -#define mpz_inp_str __gmpz_inp_str -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_inp_str (mpz_ptr, FILE *, int); -#endif - -#define mpz_invert __gmpz_invert -__GMP_DECLSPEC int mpz_invert (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_ior __gmpz_ior -__GMP_DECLSPEC void mpz_ior (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_jacobi __gmpz_jacobi -__GMP_DECLSPEC int mpz_jacobi (mpz_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; - -#define mpz_kronecker mpz_jacobi /* alias */ - -#define mpz_kronecker_si __gmpz_kronecker_si -__GMP_DECLSPEC int mpz_kronecker_si (mpz_srcptr, long) __GMP_ATTRIBUTE_PURE; - -#define mpz_kronecker_ui __gmpz_kronecker_ui -__GMP_DECLSPEC int mpz_kronecker_ui (mpz_srcptr, unsigned long) __GMP_ATTRIBUTE_PURE; - -#define mpz_si_kronecker __gmpz_si_kronecker -__GMP_DECLSPEC int mpz_si_kronecker (long, mpz_srcptr) __GMP_ATTRIBUTE_PURE; - -#define mpz_ui_kronecker __gmpz_ui_kronecker -__GMP_DECLSPEC int mpz_ui_kronecker (unsigned long, mpz_srcptr) __GMP_ATTRIBUTE_PURE; - -#define mpz_lcm __gmpz_lcm -__GMP_DECLSPEC void mpz_lcm (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_lcm_ui __gmpz_lcm_ui -__GMP_DECLSPEC void mpz_lcm_ui (mpz_ptr, mpz_srcptr, unsigned long); - -#define mpz_legendre mpz_jacobi /* alias */ - -#define mpz_lucnum_ui __gmpz_lucnum_ui -__GMP_DECLSPEC void mpz_lucnum_ui (mpz_ptr, unsigned long int); - -#define mpz_lucnum2_ui __gmpz_lucnum2_ui -__GMP_DECLSPEC void mpz_lucnum2_ui (mpz_ptr, mpz_ptr, unsigned long int); - -#define mpz_millerrabin __gmpz_millerrabin -__GMP_DECLSPEC int mpz_millerrabin (mpz_srcptr, int) __GMP_ATTRIBUTE_PURE; - -#define mpz_mod __gmpz_mod -__GMP_DECLSPEC void mpz_mod (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_mod_ui mpz_fdiv_r_ui /* same as fdiv_r because divisor unsigned */ - -#define mpz_mul __gmpz_mul -__GMP_DECLSPEC void mpz_mul (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_mul_2exp __gmpz_mul_2exp -__GMP_DECLSPEC void mpz_mul_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); - -#define mpz_mul_si __gmpz_mul_si -__GMP_DECLSPEC void mpz_mul_si (mpz_ptr, mpz_srcptr, long int); - -#define mpz_mul_ui __gmpz_mul_ui -__GMP_DECLSPEC void mpz_mul_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_neg __gmpz_neg -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_neg) -__GMP_DECLSPEC void mpz_neg (mpz_ptr, mpz_srcptr); -#endif - -#define mpz_nextprime __gmpz_nextprime -__GMP_DECLSPEC void mpz_nextprime (mpz_ptr, mpz_srcptr); - -#define mpz_out_raw __gmpz_out_raw -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_out_raw (FILE *, mpz_srcptr); -#endif - -#define mpz_out_str __gmpz_out_str -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_out_str (FILE *, int, mpz_srcptr); -#endif - -#define mpz_perfect_power_p __gmpz_perfect_power_p -__GMP_DECLSPEC int mpz_perfect_power_p (mpz_srcptr) __GMP_ATTRIBUTE_PURE; - -#define mpz_perfect_square_p __gmpz_perfect_square_p -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_perfect_square_p) -__GMP_DECLSPEC int mpz_perfect_square_p (mpz_srcptr) __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_popcount __gmpz_popcount -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_popcount) -__GMP_DECLSPEC mp_bitcnt_t mpz_popcount (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_pow_ui __gmpz_pow_ui -__GMP_DECLSPEC void mpz_pow_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_powm __gmpz_powm -__GMP_DECLSPEC void mpz_powm (mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr); - -#define mpz_powm_sec __gmpz_powm_sec -__GMP_DECLSPEC void mpz_powm_sec (mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr); - -#define mpz_powm_ui __gmpz_powm_ui -__GMP_DECLSPEC void mpz_powm_ui (mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr); - -#define mpz_probab_prime_p __gmpz_probab_prime_p -__GMP_DECLSPEC int mpz_probab_prime_p (mpz_srcptr, int) __GMP_ATTRIBUTE_PURE; - -#define mpz_random __gmpz_random -__GMP_DECLSPEC void mpz_random (mpz_ptr, mp_size_t); - -#define mpz_random2 __gmpz_random2 -__GMP_DECLSPEC void mpz_random2 (mpz_ptr, mp_size_t); - -#define mpz_realloc2 __gmpz_realloc2 -__GMP_DECLSPEC void mpz_realloc2 (mpz_ptr, mp_bitcnt_t); - -#define mpz_remove __gmpz_remove -__GMP_DECLSPEC mp_bitcnt_t mpz_remove (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_root __gmpz_root -__GMP_DECLSPEC int mpz_root (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_rootrem __gmpz_rootrem -__GMP_DECLSPEC void mpz_rootrem (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_rrandomb __gmpz_rrandomb -__GMP_DECLSPEC void mpz_rrandomb (mpz_ptr, gmp_randstate_t, mp_bitcnt_t); - -#define mpz_scan0 __gmpz_scan0 -__GMP_DECLSPEC mp_bitcnt_t mpz_scan0 (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_scan1 __gmpz_scan1 -__GMP_DECLSPEC mp_bitcnt_t mpz_scan1 (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_set __gmpz_set -__GMP_DECLSPEC void mpz_set (mpz_ptr, mpz_srcptr); - -#define mpz_set_d __gmpz_set_d -__GMP_DECLSPEC void mpz_set_d (mpz_ptr, double); - -#define mpz_set_f __gmpz_set_f -__GMP_DECLSPEC void mpz_set_f (mpz_ptr, mpf_srcptr); - -#define mpz_set_q __gmpz_set_q -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_set_q) -__GMP_DECLSPEC void mpz_set_q (mpz_ptr, mpq_srcptr); -#endif - -#define mpz_set_si __gmpz_set_si -__GMP_DECLSPEC void mpz_set_si (mpz_ptr, signed long int); - -#define mpz_set_str __gmpz_set_str -__GMP_DECLSPEC int mpz_set_str (mpz_ptr, const char *, int); - -#define mpz_set_ui __gmpz_set_ui -__GMP_DECLSPEC void mpz_set_ui (mpz_ptr, unsigned long int); - -#define mpz_setbit __gmpz_setbit -__GMP_DECLSPEC void mpz_setbit (mpz_ptr, mp_bitcnt_t); - -#define mpz_size __gmpz_size -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_size) -__GMP_DECLSPEC size_t mpz_size (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpz_sizeinbase __gmpz_sizeinbase -__GMP_DECLSPEC size_t mpz_sizeinbase (mpz_srcptr, int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_sqrt __gmpz_sqrt -__GMP_DECLSPEC void mpz_sqrt (mpz_ptr, mpz_srcptr); - -#define mpz_sqrtrem __gmpz_sqrtrem -__GMP_DECLSPEC void mpz_sqrtrem (mpz_ptr, mpz_ptr, mpz_srcptr); - -#define mpz_sub __gmpz_sub -__GMP_DECLSPEC void mpz_sub (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_sub_ui __gmpz_sub_ui -__GMP_DECLSPEC void mpz_sub_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_ui_sub __gmpz_ui_sub -__GMP_DECLSPEC void mpz_ui_sub (mpz_ptr, unsigned long int, mpz_srcptr); - -#define mpz_submul __gmpz_submul -__GMP_DECLSPEC void mpz_submul (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_submul_ui __gmpz_submul_ui -__GMP_DECLSPEC void mpz_submul_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_swap __gmpz_swap -__GMP_DECLSPEC void mpz_swap (mpz_ptr, mpz_ptr) __GMP_NOTHROW; - -#define mpz_tdiv_ui __gmpz_tdiv_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_ui (mpz_srcptr, unsigned long int) __GMP_ATTRIBUTE_PURE; - -#define mpz_tdiv_q __gmpz_tdiv_q -__GMP_DECLSPEC void mpz_tdiv_q (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_tdiv_q_2exp __gmpz_tdiv_q_2exp -__GMP_DECLSPEC void mpz_tdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); - -#define mpz_tdiv_q_ui __gmpz_tdiv_q_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_q_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_tdiv_qr __gmpz_tdiv_qr -__GMP_DECLSPEC void mpz_tdiv_qr (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_tdiv_qr_ui __gmpz_tdiv_qr_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_qr_ui (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_tdiv_r __gmpz_tdiv_r -__GMP_DECLSPEC void mpz_tdiv_r (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_tdiv_r_2exp __gmpz_tdiv_r_2exp -__GMP_DECLSPEC void mpz_tdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); - -#define mpz_tdiv_r_ui __gmpz_tdiv_r_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_r_ui (mpz_ptr, mpz_srcptr, unsigned long int); - -#define mpz_tstbit __gmpz_tstbit -__GMP_DECLSPEC int mpz_tstbit (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpz_ui_pow_ui __gmpz_ui_pow_ui -__GMP_DECLSPEC void mpz_ui_pow_ui (mpz_ptr, unsigned long int, unsigned long int); - -#define mpz_urandomb __gmpz_urandomb -__GMP_DECLSPEC void mpz_urandomb (mpz_ptr, gmp_randstate_t, mp_bitcnt_t); - -#define mpz_urandomm __gmpz_urandomm -__GMP_DECLSPEC void mpz_urandomm (mpz_ptr, gmp_randstate_t, mpz_srcptr); - -#define mpz_xor __gmpz_xor -#define mpz_eor __gmpz_xor -__GMP_DECLSPEC void mpz_xor (mpz_ptr, mpz_srcptr, mpz_srcptr); - -#define mpz_limbs_read __gmpz_limbs_read -__GMP_DECLSPEC mp_srcptr mpz_limbs_read (mpz_srcptr); - -#define mpz_limbs_write __gmpz_limbs_write -__GMP_DECLSPEC mp_ptr mpz_limbs_write (mpz_ptr, mp_size_t); - -#define mpz_limbs_modify __gmpz_limbs_modify -__GMP_DECLSPEC mp_ptr mpz_limbs_modify (mpz_ptr, mp_size_t); - -#define mpz_limbs_finish __gmpz_limbs_finish -__GMP_DECLSPEC void mpz_limbs_finish (mpz_ptr, mp_size_t); - -#define mpz_roinit_n __gmpz_roinit_n -__GMP_DECLSPEC mpz_srcptr mpz_roinit_n (mpz_ptr, mp_srcptr, mp_size_t); - -#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }} - -/**************** Rational (i.e. Q) routines. ****************/ - -#define mpq_abs __gmpq_abs -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_abs) -__GMP_DECLSPEC void mpq_abs (mpq_ptr, mpq_srcptr); -#endif - -#define mpq_add __gmpq_add -__GMP_DECLSPEC void mpq_add (mpq_ptr, mpq_srcptr, mpq_srcptr); - -#define mpq_canonicalize __gmpq_canonicalize -__GMP_DECLSPEC void mpq_canonicalize (mpq_ptr); - -#define mpq_clear __gmpq_clear -__GMP_DECLSPEC void mpq_clear (mpq_ptr); - -#define mpq_clears __gmpq_clears -__GMP_DECLSPEC void mpq_clears (mpq_ptr, ...); - -#define mpq_cmp __gmpq_cmp -__GMP_DECLSPEC int mpq_cmp (mpq_srcptr, mpq_srcptr) __GMP_ATTRIBUTE_PURE; - -#define _mpq_cmp_si __gmpq_cmp_si -__GMP_DECLSPEC int _mpq_cmp_si (mpq_srcptr, long, unsigned long) __GMP_ATTRIBUTE_PURE; - -#define _mpq_cmp_ui __gmpq_cmp_ui -__GMP_DECLSPEC int _mpq_cmp_ui (mpq_srcptr, unsigned long int, unsigned long int) __GMP_ATTRIBUTE_PURE; - -#define mpq_cmp_z __gmpq_cmp_z -__GMP_DECLSPEC int mpq_cmp_z (mpq_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; - -#define mpq_div __gmpq_div -__GMP_DECLSPEC void mpq_div (mpq_ptr, mpq_srcptr, mpq_srcptr); - -#define mpq_div_2exp __gmpq_div_2exp -__GMP_DECLSPEC void mpq_div_2exp (mpq_ptr, mpq_srcptr, mp_bitcnt_t); - -#define mpq_equal __gmpq_equal -__GMP_DECLSPEC int mpq_equal (mpq_srcptr, mpq_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpq_get_num __gmpq_get_num -__GMP_DECLSPEC void mpq_get_num (mpz_ptr, mpq_srcptr); - -#define mpq_get_den __gmpq_get_den -__GMP_DECLSPEC void mpq_get_den (mpz_ptr, mpq_srcptr); - -#define mpq_get_d __gmpq_get_d -__GMP_DECLSPEC double mpq_get_d (mpq_srcptr) __GMP_ATTRIBUTE_PURE; - -#define mpq_get_str __gmpq_get_str -__GMP_DECLSPEC char *mpq_get_str (char *, int, mpq_srcptr); - -#define mpq_init __gmpq_init -__GMP_DECLSPEC void mpq_init (mpq_ptr); - -#define mpq_inits __gmpq_inits -__GMP_DECLSPEC void mpq_inits (mpq_ptr, ...); - -#define mpq_inp_str __gmpq_inp_str -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpq_inp_str (mpq_ptr, FILE *, int); -#endif - -#define mpq_inv __gmpq_inv -__GMP_DECLSPEC void mpq_inv (mpq_ptr, mpq_srcptr); - -#define mpq_mul __gmpq_mul -__GMP_DECLSPEC void mpq_mul (mpq_ptr, mpq_srcptr, mpq_srcptr); - -#define mpq_mul_2exp __gmpq_mul_2exp -__GMP_DECLSPEC void mpq_mul_2exp (mpq_ptr, mpq_srcptr, mp_bitcnt_t); - -#define mpq_neg __gmpq_neg -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_neg) -__GMP_DECLSPEC void mpq_neg (mpq_ptr, mpq_srcptr); -#endif - -#define mpq_out_str __gmpq_out_str -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpq_out_str (FILE *, int, mpq_srcptr); -#endif - -#define mpq_set __gmpq_set -__GMP_DECLSPEC void mpq_set (mpq_ptr, mpq_srcptr); - -#define mpq_set_d __gmpq_set_d -__GMP_DECLSPEC void mpq_set_d (mpq_ptr, double); - -#define mpq_set_den __gmpq_set_den -__GMP_DECLSPEC void mpq_set_den (mpq_ptr, mpz_srcptr); - -#define mpq_set_f __gmpq_set_f -__GMP_DECLSPEC void mpq_set_f (mpq_ptr, mpf_srcptr); - -#define mpq_set_num __gmpq_set_num -__GMP_DECLSPEC void mpq_set_num (mpq_ptr, mpz_srcptr); - -#define mpq_set_si __gmpq_set_si -__GMP_DECLSPEC void mpq_set_si (mpq_ptr, signed long int, unsigned long int); - -#define mpq_set_str __gmpq_set_str -__GMP_DECLSPEC int mpq_set_str (mpq_ptr, const char *, int); - -#define mpq_set_ui __gmpq_set_ui -__GMP_DECLSPEC void mpq_set_ui (mpq_ptr, unsigned long int, unsigned long int); - -#define mpq_set_z __gmpq_set_z -__GMP_DECLSPEC void mpq_set_z (mpq_ptr, mpz_srcptr); - -#define mpq_sub __gmpq_sub -__GMP_DECLSPEC void mpq_sub (mpq_ptr, mpq_srcptr, mpq_srcptr); - -#define mpq_swap __gmpq_swap -__GMP_DECLSPEC void mpq_swap (mpq_ptr, mpq_ptr) __GMP_NOTHROW; - - -/**************** Float (i.e. F) routines. ****************/ - -#define mpf_abs __gmpf_abs -__GMP_DECLSPEC void mpf_abs (mpf_ptr, mpf_srcptr); - -#define mpf_add __gmpf_add -__GMP_DECLSPEC void mpf_add (mpf_ptr, mpf_srcptr, mpf_srcptr); - -#define mpf_add_ui __gmpf_add_ui -__GMP_DECLSPEC void mpf_add_ui (mpf_ptr, mpf_srcptr, unsigned long int); -#define mpf_ceil __gmpf_ceil -__GMP_DECLSPEC void mpf_ceil (mpf_ptr, mpf_srcptr); - -#define mpf_clear __gmpf_clear -__GMP_DECLSPEC void mpf_clear (mpf_ptr); - -#define mpf_clears __gmpf_clears -__GMP_DECLSPEC void mpf_clears (mpf_ptr, ...); - -#define mpf_cmp __gmpf_cmp -__GMP_DECLSPEC int mpf_cmp (mpf_srcptr, mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_cmp_z __gmpf_cmp_z -__GMP_DECLSPEC int mpf_cmp_z (mpf_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_cmp_d __gmpf_cmp_d -__GMP_DECLSPEC int mpf_cmp_d (mpf_srcptr, double) __GMP_ATTRIBUTE_PURE; - -#define mpf_cmp_si __gmpf_cmp_si -__GMP_DECLSPEC int mpf_cmp_si (mpf_srcptr, signed long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_cmp_ui __gmpf_cmp_ui -__GMP_DECLSPEC int mpf_cmp_ui (mpf_srcptr, unsigned long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_div __gmpf_div -__GMP_DECLSPEC void mpf_div (mpf_ptr, mpf_srcptr, mpf_srcptr); - -#define mpf_div_2exp __gmpf_div_2exp -__GMP_DECLSPEC void mpf_div_2exp (mpf_ptr, mpf_srcptr, mp_bitcnt_t); - -#define mpf_div_ui __gmpf_div_ui -__GMP_DECLSPEC void mpf_div_ui (mpf_ptr, mpf_srcptr, unsigned long int); - -#define mpf_dump __gmpf_dump -__GMP_DECLSPEC void mpf_dump (mpf_srcptr); - -#define mpf_eq __gmpf_eq -__GMP_DECLSPEC int mpf_eq (mpf_srcptr, mpf_srcptr, mp_bitcnt_t) __GMP_ATTRIBUTE_PURE; - -#define mpf_fits_sint_p __gmpf_fits_sint_p -__GMP_DECLSPEC int mpf_fits_sint_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_fits_slong_p __gmpf_fits_slong_p -__GMP_DECLSPEC int mpf_fits_slong_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_fits_sshort_p __gmpf_fits_sshort_p -__GMP_DECLSPEC int mpf_fits_sshort_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_fits_uint_p __gmpf_fits_uint_p -__GMP_DECLSPEC int mpf_fits_uint_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_fits_ulong_p __gmpf_fits_ulong_p -__GMP_DECLSPEC int mpf_fits_ulong_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_fits_ushort_p __gmpf_fits_ushort_p -__GMP_DECLSPEC int mpf_fits_ushort_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_floor __gmpf_floor -__GMP_DECLSPEC void mpf_floor (mpf_ptr, mpf_srcptr); - -#define mpf_get_d __gmpf_get_d -__GMP_DECLSPEC double mpf_get_d (mpf_srcptr) __GMP_ATTRIBUTE_PURE; - -#define mpf_get_d_2exp __gmpf_get_d_2exp -__GMP_DECLSPEC double mpf_get_d_2exp (signed long int *, mpf_srcptr); - -#define mpf_get_default_prec __gmpf_get_default_prec -__GMP_DECLSPEC mp_bitcnt_t mpf_get_default_prec (void) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_get_prec __gmpf_get_prec -__GMP_DECLSPEC mp_bitcnt_t mpf_get_prec (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_get_si __gmpf_get_si -__GMP_DECLSPEC long mpf_get_si (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_get_str __gmpf_get_str -__GMP_DECLSPEC char *mpf_get_str (char *, mp_exp_t *, int, size_t, mpf_srcptr); - -#define mpf_get_ui __gmpf_get_ui -__GMP_DECLSPEC unsigned long mpf_get_ui (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_init __gmpf_init -__GMP_DECLSPEC void mpf_init (mpf_ptr); - -#define mpf_init2 __gmpf_init2 -__GMP_DECLSPEC void mpf_init2 (mpf_ptr, mp_bitcnt_t); - -#define mpf_inits __gmpf_inits -__GMP_DECLSPEC void mpf_inits (mpf_ptr, ...); - -#define mpf_init_set __gmpf_init_set -__GMP_DECLSPEC void mpf_init_set (mpf_ptr, mpf_srcptr); - -#define mpf_init_set_d __gmpf_init_set_d -__GMP_DECLSPEC void mpf_init_set_d (mpf_ptr, double); - -#define mpf_init_set_si __gmpf_init_set_si -__GMP_DECLSPEC void mpf_init_set_si (mpf_ptr, signed long int); - -#define mpf_init_set_str __gmpf_init_set_str -__GMP_DECLSPEC int mpf_init_set_str (mpf_ptr, const char *, int); - -#define mpf_init_set_ui __gmpf_init_set_ui -__GMP_DECLSPEC void mpf_init_set_ui (mpf_ptr, unsigned long int); - -#define mpf_inp_str __gmpf_inp_str -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpf_inp_str (mpf_ptr, FILE *, int); -#endif - -#define mpf_integer_p __gmpf_integer_p -__GMP_DECLSPEC int mpf_integer_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_mul __gmpf_mul -__GMP_DECLSPEC void mpf_mul (mpf_ptr, mpf_srcptr, mpf_srcptr); - -#define mpf_mul_2exp __gmpf_mul_2exp -__GMP_DECLSPEC void mpf_mul_2exp (mpf_ptr, mpf_srcptr, mp_bitcnt_t); - -#define mpf_mul_ui __gmpf_mul_ui -__GMP_DECLSPEC void mpf_mul_ui (mpf_ptr, mpf_srcptr, unsigned long int); - -#define mpf_neg __gmpf_neg -__GMP_DECLSPEC void mpf_neg (mpf_ptr, mpf_srcptr); - -#define mpf_out_str __gmpf_out_str -#ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpf_out_str (FILE *, int, size_t, mpf_srcptr); -#endif - -#define mpf_pow_ui __gmpf_pow_ui -__GMP_DECLSPEC void mpf_pow_ui (mpf_ptr, mpf_srcptr, unsigned long int); - -#define mpf_random2 __gmpf_random2 -__GMP_DECLSPEC void mpf_random2 (mpf_ptr, mp_size_t, mp_exp_t); - -#define mpf_reldiff __gmpf_reldiff -__GMP_DECLSPEC void mpf_reldiff (mpf_ptr, mpf_srcptr, mpf_srcptr); - -#define mpf_set __gmpf_set -__GMP_DECLSPEC void mpf_set (mpf_ptr, mpf_srcptr); - -#define mpf_set_d __gmpf_set_d -__GMP_DECLSPEC void mpf_set_d (mpf_ptr, double); - -#define mpf_set_default_prec __gmpf_set_default_prec -__GMP_DECLSPEC void mpf_set_default_prec (mp_bitcnt_t) __GMP_NOTHROW; - -#define mpf_set_prec __gmpf_set_prec -__GMP_DECLSPEC void mpf_set_prec (mpf_ptr, mp_bitcnt_t); - -#define mpf_set_prec_raw __gmpf_set_prec_raw -__GMP_DECLSPEC void mpf_set_prec_raw (mpf_ptr, mp_bitcnt_t) __GMP_NOTHROW; - -#define mpf_set_q __gmpf_set_q -__GMP_DECLSPEC void mpf_set_q (mpf_ptr, mpq_srcptr); - -#define mpf_set_si __gmpf_set_si -__GMP_DECLSPEC void mpf_set_si (mpf_ptr, signed long int); - -#define mpf_set_str __gmpf_set_str -__GMP_DECLSPEC int mpf_set_str (mpf_ptr, const char *, int); - -#define mpf_set_ui __gmpf_set_ui -__GMP_DECLSPEC void mpf_set_ui (mpf_ptr, unsigned long int); - -#define mpf_set_z __gmpf_set_z -__GMP_DECLSPEC void mpf_set_z (mpf_ptr, mpz_srcptr); - -#define mpf_size __gmpf_size -__GMP_DECLSPEC size_t mpf_size (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpf_sqrt __gmpf_sqrt -__GMP_DECLSPEC void mpf_sqrt (mpf_ptr, mpf_srcptr); - -#define mpf_sqrt_ui __gmpf_sqrt_ui -__GMP_DECLSPEC void mpf_sqrt_ui (mpf_ptr, unsigned long int); - -#define mpf_sub __gmpf_sub -__GMP_DECLSPEC void mpf_sub (mpf_ptr, mpf_srcptr, mpf_srcptr); - -#define mpf_sub_ui __gmpf_sub_ui -__GMP_DECLSPEC void mpf_sub_ui (mpf_ptr, mpf_srcptr, unsigned long int); - -#define mpf_swap __gmpf_swap -__GMP_DECLSPEC void mpf_swap (mpf_ptr, mpf_ptr) __GMP_NOTHROW; - -#define mpf_trunc __gmpf_trunc -__GMP_DECLSPEC void mpf_trunc (mpf_ptr, mpf_srcptr); - -#define mpf_ui_div __gmpf_ui_div -__GMP_DECLSPEC void mpf_ui_div (mpf_ptr, unsigned long int, mpf_srcptr); - -#define mpf_ui_sub __gmpf_ui_sub -__GMP_DECLSPEC void mpf_ui_sub (mpf_ptr, unsigned long int, mpf_srcptr); - -#define mpf_urandomb __gmpf_urandomb -__GMP_DECLSPEC void mpf_urandomb (mpf_t, gmp_randstate_t, mp_bitcnt_t); - - -/************ Low level positive-integer (i.e. N) routines. ************/ - -/* This is ugly, but we need to make user calls reach the prefixed function. */ - -#define mpn_add __MPN(add) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add) -__GMP_DECLSPEC mp_limb_t mpn_add (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); -#endif - -#define mpn_add_1 __MPN(add_1) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add_1) -__GMP_DECLSPEC mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t) __GMP_NOTHROW; -#endif - -#define mpn_add_n __MPN(add_n) -__GMP_DECLSPEC mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); - -#define mpn_addmul_1 __MPN(addmul_1) -__GMP_DECLSPEC mp_limb_t mpn_addmul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); - -#define mpn_cmp __MPN(cmp) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_cmp) -__GMP_DECLSPEC int mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpn_zero_p __MPN(zero_p) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_zero_p) -__GMP_DECLSPEC int mpn_zero_p (mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; -#endif - -#define mpn_divexact_1 __MPN(divexact_1) -__GMP_DECLSPEC void mpn_divexact_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); - -#define mpn_divexact_by3(dst,src,size) \ - mpn_divexact_by3c (dst, src, size, __GMP_CAST (mp_limb_t, 0)) - -#define mpn_divexact_by3c __MPN(divexact_by3c) -__GMP_DECLSPEC mp_limb_t mpn_divexact_by3c (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); - -#define mpn_divmod_1(qp,np,nsize,dlimb) \ - mpn_divrem_1 (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dlimb) - -#define mpn_divrem __MPN(divrem) -__GMP_DECLSPEC mp_limb_t mpn_divrem (mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t); - -#define mpn_divrem_1 __MPN(divrem_1) -__GMP_DECLSPEC mp_limb_t mpn_divrem_1 (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t); - -#define mpn_divrem_2 __MPN(divrem_2) -__GMP_DECLSPEC mp_limb_t mpn_divrem_2 (mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr); - -#define mpn_div_qr_1 __MPN(div_qr_1) -__GMP_DECLSPEC mp_limb_t mpn_div_qr_1 (mp_ptr, mp_limb_t *, mp_srcptr, mp_size_t, mp_limb_t); - -#define mpn_div_qr_2 __MPN(div_qr_2) -__GMP_DECLSPEC mp_limb_t mpn_div_qr_2 (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); - -#define mpn_gcd __MPN(gcd) -__GMP_DECLSPEC mp_size_t mpn_gcd (mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t); - -#define mpn_gcd_11 __MPN(gcd_11) -__GMP_DECLSPEC mp_limb_t mpn_gcd_11 (mp_limb_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_gcd_1 __MPN(gcd_1) -__GMP_DECLSPEC mp_limb_t mpn_gcd_1 (mp_srcptr, mp_size_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_gcdext_1 __MPN(gcdext_1) -__GMP_DECLSPEC mp_limb_t mpn_gcdext_1 (mp_limb_signed_t *, mp_limb_signed_t *, mp_limb_t, mp_limb_t); - -#define mpn_gcdext __MPN(gcdext) -__GMP_DECLSPEC mp_size_t mpn_gcdext (mp_ptr, mp_ptr, mp_size_t *, mp_ptr, mp_size_t, mp_ptr, mp_size_t); - -#define mpn_get_str __MPN(get_str) -__GMP_DECLSPEC size_t mpn_get_str (unsigned char *, int, mp_ptr, mp_size_t); - -#define mpn_hamdist __MPN(hamdist) -__GMP_DECLSPEC mp_bitcnt_t mpn_hamdist (mp_srcptr, mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpn_lshift __MPN(lshift) -__GMP_DECLSPEC mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); - -#define mpn_mod_1 __MPN(mod_1) -__GMP_DECLSPEC mp_limb_t mpn_mod_1 (mp_srcptr, mp_size_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_mul __MPN(mul) -__GMP_DECLSPEC mp_limb_t mpn_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); - -#define mpn_mul_1 __MPN(mul_1) -__GMP_DECLSPEC mp_limb_t mpn_mul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); - -#define mpn_mul_n __MPN(mul_n) -__GMP_DECLSPEC void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); - -#define mpn_sqr __MPN(sqr) -__GMP_DECLSPEC void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t); - -#define mpn_neg __MPN(neg) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_neg) -__GMP_DECLSPEC mp_limb_t mpn_neg (mp_ptr, mp_srcptr, mp_size_t); -#endif - -#define mpn_com __MPN(com) -__GMP_DECLSPEC void mpn_com (mp_ptr, mp_srcptr, mp_size_t); - -#define mpn_perfect_square_p __MPN(perfect_square_p) -__GMP_DECLSPEC int mpn_perfect_square_p (mp_srcptr, mp_size_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_perfect_power_p __MPN(perfect_power_p) -__GMP_DECLSPEC int mpn_perfect_power_p (mp_srcptr, mp_size_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_popcount __MPN(popcount) -__GMP_DECLSPEC mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; - -#define mpn_pow_1 __MPN(pow_1) -__GMP_DECLSPEC mp_size_t mpn_pow_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); - -/* undocumented now, but retained here for upward compatibility */ -#define mpn_preinv_mod_1 __MPN(preinv_mod_1) -__GMP_DECLSPEC mp_limb_t mpn_preinv_mod_1 (mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_random __MPN(random) -__GMP_DECLSPEC void mpn_random (mp_ptr, mp_size_t); - -#define mpn_random2 __MPN(random2) -__GMP_DECLSPEC void mpn_random2 (mp_ptr, mp_size_t); - -#define mpn_rshift __MPN(rshift) -__GMP_DECLSPEC mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); - -#define mpn_scan0 __MPN(scan0) -__GMP_DECLSPEC mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_scan1 __MPN(scan1) -__GMP_DECLSPEC mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_set_str __MPN(set_str) -__GMP_DECLSPEC mp_size_t mpn_set_str (mp_ptr, const unsigned char *, size_t, int); - -#define mpn_sizeinbase __MPN(sizeinbase) -__GMP_DECLSPEC size_t mpn_sizeinbase (mp_srcptr, mp_size_t, int); - -#define mpn_sqrtrem __MPN(sqrtrem) -__GMP_DECLSPEC mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t); - -#define mpn_sub __MPN(sub) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub) -__GMP_DECLSPEC mp_limb_t mpn_sub (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); -#endif - -#define mpn_sub_1 __MPN(sub_1) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub_1) -__GMP_DECLSPEC mp_limb_t mpn_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t) __GMP_NOTHROW; -#endif - -#define mpn_sub_n __MPN(sub_n) -__GMP_DECLSPEC mp_limb_t mpn_sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); - -#define mpn_submul_1 __MPN(submul_1) -__GMP_DECLSPEC mp_limb_t mpn_submul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); - -#define mpn_tdiv_qr __MPN(tdiv_qr) -__GMP_DECLSPEC void mpn_tdiv_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); - -#define mpn_and_n __MPN(and_n) -__GMP_DECLSPEC void mpn_and_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); -#define mpn_andn_n __MPN(andn_n) -__GMP_DECLSPEC void mpn_andn_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); -#define mpn_nand_n __MPN(nand_n) -__GMP_DECLSPEC void mpn_nand_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); -#define mpn_ior_n __MPN(ior_n) -__GMP_DECLSPEC void mpn_ior_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); -#define mpn_iorn_n __MPN(iorn_n) -__GMP_DECLSPEC void mpn_iorn_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); -#define mpn_nior_n __MPN(nior_n) -__GMP_DECLSPEC void mpn_nior_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); -#define mpn_xor_n __MPN(xor_n) -__GMP_DECLSPEC void mpn_xor_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); -#define mpn_xnor_n __MPN(xnor_n) -__GMP_DECLSPEC void mpn_xnor_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); - -#define mpn_copyi __MPN(copyi) -__GMP_DECLSPEC void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t); -#define mpn_copyd __MPN(copyd) -__GMP_DECLSPEC void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t); -#define mpn_zero __MPN(zero) -__GMP_DECLSPEC void mpn_zero (mp_ptr, mp_size_t); - -#define mpn_cnd_add_n __MPN(cnd_add_n) -__GMP_DECLSPEC mp_limb_t mpn_cnd_add_n (mp_limb_t, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); -#define mpn_cnd_sub_n __MPN(cnd_sub_n) -__GMP_DECLSPEC mp_limb_t mpn_cnd_sub_n (mp_limb_t, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); - -#define mpn_sec_add_1 __MPN(sec_add_1) -__GMP_DECLSPEC mp_limb_t mpn_sec_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); -#define mpn_sec_add_1_itch __MPN(sec_add_1_itch) -__GMP_DECLSPEC mp_size_t mpn_sec_add_1_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_sec_sub_1 __MPN(sec_sub_1) -__GMP_DECLSPEC mp_limb_t mpn_sec_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); -#define mpn_sec_sub_1_itch __MPN(sec_sub_1_itch) -__GMP_DECLSPEC mp_size_t mpn_sec_sub_1_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_cnd_swap __MPN(cnd_swap) -__GMP_DECLSPEC void mpn_cnd_swap (mp_limb_t, volatile mp_limb_t *, volatile mp_limb_t *, mp_size_t); - -#define mpn_sec_mul __MPN(sec_mul) -__GMP_DECLSPEC void mpn_sec_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); -#define mpn_sec_mul_itch __MPN(sec_mul_itch) -__GMP_DECLSPEC mp_size_t mpn_sec_mul_itch (mp_size_t, mp_size_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_sec_sqr __MPN(sec_sqr) -__GMP_DECLSPEC void mpn_sec_sqr (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); -#define mpn_sec_sqr_itch __MPN(sec_sqr_itch) -__GMP_DECLSPEC mp_size_t mpn_sec_sqr_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_sec_powm __MPN(sec_powm) -__GMP_DECLSPEC void mpn_sec_powm (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_bitcnt_t, mp_srcptr, mp_size_t, mp_ptr); -#define mpn_sec_powm_itch __MPN(sec_powm_itch) -__GMP_DECLSPEC mp_size_t mpn_sec_powm_itch (mp_size_t, mp_bitcnt_t, mp_size_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_sec_tabselect __MPN(sec_tabselect) -__GMP_DECLSPEC void mpn_sec_tabselect (volatile mp_limb_t *, volatile const mp_limb_t *, mp_size_t, mp_size_t, mp_size_t); - -#define mpn_sec_div_qr __MPN(sec_div_qr) -__GMP_DECLSPEC mp_limb_t mpn_sec_div_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); -#define mpn_sec_div_qr_itch __MPN(sec_div_qr_itch) -__GMP_DECLSPEC mp_size_t mpn_sec_div_qr_itch (mp_size_t, mp_size_t) __GMP_ATTRIBUTE_PURE; -#define mpn_sec_div_r __MPN(sec_div_r) -__GMP_DECLSPEC void mpn_sec_div_r (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); -#define mpn_sec_div_r_itch __MPN(sec_div_r_itch) -__GMP_DECLSPEC mp_size_t mpn_sec_div_r_itch (mp_size_t, mp_size_t) __GMP_ATTRIBUTE_PURE; - -#define mpn_sec_invert __MPN(sec_invert) -__GMP_DECLSPEC int mpn_sec_invert (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_bitcnt_t, mp_ptr); -#define mpn_sec_invert_itch __MPN(sec_invert_itch) -__GMP_DECLSPEC mp_size_t mpn_sec_invert_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; - - -/**************** mpz inlines ****************/ - -/* The following are provided as inlines where possible, but always exist as - library functions too, for binary compatibility. - - Within gmp itself this inlining generally isn't relied on, since it - doesn't get done for all compilers, whereas if something is worth - inlining then it's worth arranging always. - - There are two styles of inlining here. When the same bit of code is - wanted for the inline as for the library version, then __GMP_FORCE_foo - arranges for that code to be emitted and the __GMP_EXTERN_INLINE - directive suppressed, eg. mpz_fits_uint_p. When a different bit of code - is wanted for the inline than for the library version, then - __GMP_FORCE_foo arranges the inline to be suppressed, eg. mpz_abs. */ - -#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_abs) -__GMP_EXTERN_INLINE void -mpz_abs (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) -{ - if (__gmp_w != __gmp_u) - mpz_set (__gmp_w, __gmp_u); - __gmp_w->_mp_size = __GMP_ABS (__gmp_w->_mp_size); -} -#endif - -#if GMP_NAIL_BITS == 0 -#define __GMPZ_FITS_UTYPE_P(z,maxval) \ - mp_size_t __gmp_n = z->_mp_size; \ - mp_ptr __gmp_p = z->_mp_d; \ - return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval)); -#else -#define __GMPZ_FITS_UTYPE_P(z,maxval) \ - mp_size_t __gmp_n = z->_mp_size; \ - mp_ptr __gmp_p = z->_mp_d; \ - return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval) \ - || (__gmp_n == 2 && __gmp_p[1] <= ((mp_limb_t) maxval >> GMP_NUMB_BITS))); -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_uint_p) -#if ! defined (__GMP_FORCE_mpz_fits_uint_p) -__GMP_EXTERN_INLINE -#endif -int -mpz_fits_uint_p (mpz_srcptr __gmp_z) __GMP_NOTHROW -{ - __GMPZ_FITS_UTYPE_P (__gmp_z, UINT_MAX); -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ulong_p) -#if ! defined (__GMP_FORCE_mpz_fits_ulong_p) -__GMP_EXTERN_INLINE -#endif -int -mpz_fits_ulong_p (mpz_srcptr __gmp_z) __GMP_NOTHROW -{ - __GMPZ_FITS_UTYPE_P (__gmp_z, ULONG_MAX); -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ushort_p) -#if ! defined (__GMP_FORCE_mpz_fits_ushort_p) -__GMP_EXTERN_INLINE -#endif -int -mpz_fits_ushort_p (mpz_srcptr __gmp_z) __GMP_NOTHROW -{ - __GMPZ_FITS_UTYPE_P (__gmp_z, USHRT_MAX); -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_get_ui) -#if ! defined (__GMP_FORCE_mpz_get_ui) -__GMP_EXTERN_INLINE -#endif -unsigned long -mpz_get_ui (mpz_srcptr __gmp_z) __GMP_NOTHROW -{ - mp_ptr __gmp_p = __gmp_z->_mp_d; - mp_size_t __gmp_n = __gmp_z->_mp_size; - mp_limb_t __gmp_l = __gmp_p[0]; - /* This is a "#if" rather than a plain "if" so as to avoid gcc warnings - about "<< GMP_NUMB_BITS" exceeding the type size, and to avoid Borland - C++ 6.0 warnings about condition always true for something like - "ULONG_MAX < GMP_NUMB_MASK". */ -#if GMP_NAIL_BITS == 0 || defined (_LONG_LONG_LIMB) - /* limb==long and no nails, or limb==longlong, one limb is enough */ - return (__gmp_n != 0 ? __gmp_l : 0); -#else - /* limb==long and nails, need two limbs when available */ - __gmp_n = __GMP_ABS (__gmp_n); - if (__gmp_n <= 1) - return (__gmp_n != 0 ? __gmp_l : 0); - else - return __gmp_l + (__gmp_p[1] << GMP_NUMB_BITS); -#endif -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_getlimbn) -#if ! defined (__GMP_FORCE_mpz_getlimbn) -__GMP_EXTERN_INLINE -#endif -mp_limb_t -mpz_getlimbn (mpz_srcptr __gmp_z, mp_size_t __gmp_n) __GMP_NOTHROW -{ - mp_limb_t __gmp_result = 0; - if (__GMP_LIKELY (__gmp_n >= 0 && __gmp_n < __GMP_ABS (__gmp_z->_mp_size))) - __gmp_result = __gmp_z->_mp_d[__gmp_n]; - return __gmp_result; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_neg) -__GMP_EXTERN_INLINE void -mpz_neg (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) -{ - if (__gmp_w != __gmp_u) - mpz_set (__gmp_w, __gmp_u); - __gmp_w->_mp_size = - __gmp_w->_mp_size; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_perfect_square_p) -#if ! defined (__GMP_FORCE_mpz_perfect_square_p) -__GMP_EXTERN_INLINE -#endif -int -mpz_perfect_square_p (mpz_srcptr __gmp_a) -{ - mp_size_t __gmp_asize; - int __gmp_result; - - __gmp_asize = __gmp_a->_mp_size; - __gmp_result = (__gmp_asize >= 0); /* zero is a square, negatives are not */ - if (__GMP_LIKELY (__gmp_asize > 0)) - __gmp_result = mpn_perfect_square_p (__gmp_a->_mp_d, __gmp_asize); - return __gmp_result; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_popcount) -#if ! defined (__GMP_FORCE_mpz_popcount) -__GMP_EXTERN_INLINE -#endif -mp_bitcnt_t -mpz_popcount (mpz_srcptr __gmp_u) __GMP_NOTHROW -{ - mp_size_t __gmp_usize; - mp_bitcnt_t __gmp_result; - - __gmp_usize = __gmp_u->_mp_size; - __gmp_result = (__gmp_usize < 0 ? ~ __GMP_CAST (mp_bitcnt_t, 0) : __GMP_CAST (mp_bitcnt_t, 0)); - if (__GMP_LIKELY (__gmp_usize > 0)) - __gmp_result = mpn_popcount (__gmp_u->_mp_d, __gmp_usize); - return __gmp_result; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_set_q) -#if ! defined (__GMP_FORCE_mpz_set_q) -__GMP_EXTERN_INLINE -#endif -void -mpz_set_q (mpz_ptr __gmp_w, mpq_srcptr __gmp_u) -{ - mpz_tdiv_q (__gmp_w, mpq_numref (__gmp_u), mpq_denref (__gmp_u)); -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_size) -#if ! defined (__GMP_FORCE_mpz_size) -__GMP_EXTERN_INLINE -#endif -size_t -mpz_size (mpz_srcptr __gmp_z) __GMP_NOTHROW -{ - return __GMP_ABS (__gmp_z->_mp_size); -} -#endif - - -/**************** mpq inlines ****************/ - -#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpq_abs) -__GMP_EXTERN_INLINE void -mpq_abs (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) -{ - if (__gmp_w != __gmp_u) - mpq_set (__gmp_w, __gmp_u); - __gmp_w->_mp_num._mp_size = __GMP_ABS (__gmp_w->_mp_num._mp_size); -} -#endif - -#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpq_neg) -__GMP_EXTERN_INLINE void -mpq_neg (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) -{ - if (__gmp_w != __gmp_u) - mpq_set (__gmp_w, __gmp_u); - __gmp_w->_mp_num._mp_size = - __gmp_w->_mp_num._mp_size; -} -#endif - - -/**************** mpn inlines ****************/ - -/* The comments with __GMPN_ADD_1 below apply here too. - - The test for FUNCTION returning 0 should predict well. If it's assumed - {yp,ysize} will usually have a random number of bits then the high limb - won't be full and a carry out will occur a good deal less than 50% of the - time. - - ysize==0 isn't a documented feature, but is used internally in a few - places. - - Producing cout last stops it using up a register during the main part of - the calculation, though gcc (as of 3.0) on an "if (mpn_add (...))" - doesn't seem able to move the true and false legs of the conditional up - to the two places cout is generated. */ - -#define __GMPN_AORS(cout, wp, xp, xsize, yp, ysize, FUNCTION, TEST) \ - do { \ - mp_size_t __gmp_i; \ - mp_limb_t __gmp_x; \ - \ - /* ASSERT ((ysize) >= 0); */ \ - /* ASSERT ((xsize) >= (ysize)); */ \ - /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, xp, xsize)); */ \ - /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, yp, ysize)); */ \ - \ - __gmp_i = (ysize); \ - if (__gmp_i != 0) \ - { \ - if (FUNCTION (wp, xp, yp, __gmp_i)) \ - { \ - do \ - { \ - if (__gmp_i >= (xsize)) \ - { \ - (cout) = 1; \ - goto __gmp_done; \ - } \ - __gmp_x = (xp)[__gmp_i]; \ - } \ - while (TEST); \ - } \ - } \ - if ((wp) != (xp)) \ - __GMPN_COPY_REST (wp, xp, xsize, __gmp_i); \ - (cout) = 0; \ - __gmp_done: \ - ; \ - } while (0) - -#define __GMPN_ADD(cout, wp, xp, xsize, yp, ysize) \ - __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_add_n, \ - (((wp)[__gmp_i++] = (__gmp_x + 1) & GMP_NUMB_MASK) == 0)) -#define __GMPN_SUB(cout, wp, xp, xsize, yp, ysize) \ - __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_sub_n, \ - (((wp)[__gmp_i++] = (__gmp_x - 1) & GMP_NUMB_MASK), __gmp_x == 0)) - - -/* The use of __gmp_i indexing is designed to ensure a compile time src==dst - remains nice and clear to the compiler, so that __GMPN_COPY_REST can - disappear, and the load/add/store gets a chance to become a - read-modify-write on CISC CPUs. - - Alternatives: - - Using a pair of pointers instead of indexing would be possible, but gcc - isn't able to recognise compile-time src==dst in that case, even when the - pointers are incremented more or less together. Other compilers would - very likely have similar difficulty. - - gcc could use "if (__builtin_constant_p(src==dst) && src==dst)" or - similar to detect a compile-time src==dst. This works nicely on gcc - 2.95.x, it's not good on gcc 3.0 where __builtin_constant_p(p==p) seems - to be always false, for a pointer p. But the current code form seems - good enough for src==dst anyway. - - gcc on x86 as usual doesn't give particularly good flags handling for the - carry/borrow detection. It's tempting to want some multi instruction asm - blocks to help it, and this was tried, but in truth there's only a few - instructions to save and any gain is all too easily lost by register - juggling setting up for the asm. */ - -#if GMP_NAIL_BITS == 0 -#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ - do { \ - mp_size_t __gmp_i; \ - mp_limb_t __gmp_x, __gmp_r; \ - \ - /* ASSERT ((n) >= 1); */ \ - /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ - \ - __gmp_x = (src)[0]; \ - __gmp_r = __gmp_x OP (v); \ - (dst)[0] = __gmp_r; \ - if (CB (__gmp_r, __gmp_x, (v))) \ - { \ - (cout) = 1; \ - for (__gmp_i = 1; __gmp_i < (n);) \ - { \ - __gmp_x = (src)[__gmp_i]; \ - __gmp_r = __gmp_x OP 1; \ - (dst)[__gmp_i] = __gmp_r; \ - ++__gmp_i; \ - if (!CB (__gmp_r, __gmp_x, 1)) \ - { \ - if ((src) != (dst)) \ - __GMPN_COPY_REST (dst, src, n, __gmp_i); \ - (cout) = 0; \ - break; \ - } \ - } \ - } \ - else \ - { \ - if ((src) != (dst)) \ - __GMPN_COPY_REST (dst, src, n, 1); \ - (cout) = 0; \ - } \ - } while (0) -#endif - -#if GMP_NAIL_BITS >= 1 -#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ - do { \ - mp_size_t __gmp_i; \ - mp_limb_t __gmp_x, __gmp_r; \ - \ - /* ASSERT ((n) >= 1); */ \ - /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ - \ - __gmp_x = (src)[0]; \ - __gmp_r = __gmp_x OP (v); \ - (dst)[0] = __gmp_r & GMP_NUMB_MASK; \ - if (__gmp_r >> GMP_NUMB_BITS != 0) \ - { \ - (cout) = 1; \ - for (__gmp_i = 1; __gmp_i < (n);) \ - { \ - __gmp_x = (src)[__gmp_i]; \ - __gmp_r = __gmp_x OP 1; \ - (dst)[__gmp_i] = __gmp_r & GMP_NUMB_MASK; \ - ++__gmp_i; \ - if (__gmp_r >> GMP_NUMB_BITS == 0) \ - { \ - if ((src) != (dst)) \ - __GMPN_COPY_REST (dst, src, n, __gmp_i); \ - (cout) = 0; \ - break; \ - } \ - } \ - } \ - else \ - { \ - if ((src) != (dst)) \ - __GMPN_COPY_REST (dst, src, n, 1); \ - (cout) = 0; \ - } \ - } while (0) -#endif - -#define __GMPN_ADDCB(r,x,y) ((r) < (y)) -#define __GMPN_SUBCB(r,x,y) ((x) < (y)) - -#define __GMPN_ADD_1(cout, dst, src, n, v) \ - __GMPN_AORS_1(cout, dst, src, n, v, +, __GMPN_ADDCB) -#define __GMPN_SUB_1(cout, dst, src, n, v) \ - __GMPN_AORS_1(cout, dst, src, n, v, -, __GMPN_SUBCB) - - -/* Compare {xp,size} and {yp,size}, setting "result" to positive, zero or - negative. size==0 is allowed. On random data usually only one limb will - need to be examined to get a result, so it's worth having it inline. */ -#define __GMPN_CMP(result, xp, yp, size) \ - do { \ - mp_size_t __gmp_i; \ - mp_limb_t __gmp_x, __gmp_y; \ - \ - /* ASSERT ((size) >= 0); */ \ - \ - (result) = 0; \ - __gmp_i = (size); \ - while (--__gmp_i >= 0) \ - { \ - __gmp_x = (xp)[__gmp_i]; \ - __gmp_y = (yp)[__gmp_i]; \ - if (__gmp_x != __gmp_y) \ - { \ - /* Cannot use __gmp_x - __gmp_y, may overflow an "int" */ \ - (result) = (__gmp_x > __gmp_y ? 1 : -1); \ - break; \ - } \ - } \ - } while (0) - - -#if defined (__GMPN_COPY) && ! defined (__GMPN_COPY_REST) -#define __GMPN_COPY_REST(dst, src, size, start) \ - do { \ - /* ASSERT ((start) >= 0); */ \ - /* ASSERT ((start) <= (size)); */ \ - __GMPN_COPY ((dst)+(start), (src)+(start), (size)-(start)); \ - } while (0) -#endif - -/* Copy {src,size} to {dst,size}, starting at "start". This is designed to - keep the indexing dst[j] and src[j] nice and simple for __GMPN_ADD_1, - __GMPN_ADD, etc. */ -#if ! defined (__GMPN_COPY_REST) -#define __GMPN_COPY_REST(dst, src, size, start) \ - do { \ - mp_size_t __gmp_j; \ - /* ASSERT ((size) >= 0); */ \ - /* ASSERT ((start) >= 0); */ \ - /* ASSERT ((start) <= (size)); */ \ - /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, size)); */ \ - __GMP_CRAY_Pragma ("_CRI ivdep"); \ - for (__gmp_j = (start); __gmp_j < (size); __gmp_j++) \ - (dst)[__gmp_j] = (src)[__gmp_j]; \ - } while (0) -#endif - -/* Enhancement: Use some of the smarter code from gmp-impl.h. Maybe use - mpn_copyi if there's a native version, and if we don't mind demanding - binary compatibility for it (on targets which use it). */ - -#if ! defined (__GMPN_COPY) -#define __GMPN_COPY(dst, src, size) __GMPN_COPY_REST (dst, src, size, 0) -#endif - - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_add) -#if ! defined (__GMP_FORCE_mpn_add) -__GMP_EXTERN_INLINE -#endif -mp_limb_t -mpn_add (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) -{ - mp_limb_t __gmp_c; - __GMPN_ADD (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); - return __gmp_c; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_add_1) -#if ! defined (__GMP_FORCE_mpn_add_1) -__GMP_EXTERN_INLINE -#endif -mp_limb_t -mpn_add_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW -{ - mp_limb_t __gmp_c; - __GMPN_ADD_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); - return __gmp_c; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_cmp) -#if ! defined (__GMP_FORCE_mpn_cmp) -__GMP_EXTERN_INLINE -#endif -int -mpn_cmp (mp_srcptr __gmp_xp, mp_srcptr __gmp_yp, mp_size_t __gmp_size) __GMP_NOTHROW -{ - int __gmp_result; - __GMPN_CMP (__gmp_result, __gmp_xp, __gmp_yp, __gmp_size); - return __gmp_result; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_zero_p) -#if ! defined (__GMP_FORCE_mpn_zero_p) -__GMP_EXTERN_INLINE -#endif -int -mpn_zero_p (mp_srcptr __gmp_p, mp_size_t __gmp_n) __GMP_NOTHROW -{ - /* if (__GMP_LIKELY (__gmp_n > 0)) */ - do { - if (__gmp_p[--__gmp_n] != 0) - return 0; - } while (__gmp_n != 0); - return 1; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub) -#if ! defined (__GMP_FORCE_mpn_sub) -__GMP_EXTERN_INLINE -#endif -mp_limb_t -mpn_sub (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) -{ - mp_limb_t __gmp_c; - __GMPN_SUB (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); - return __gmp_c; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub_1) -#if ! defined (__GMP_FORCE_mpn_sub_1) -__GMP_EXTERN_INLINE -#endif -mp_limb_t -mpn_sub_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW -{ - mp_limb_t __gmp_c; - __GMPN_SUB_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); - return __gmp_c; -} -#endif - -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_neg) -#if ! defined (__GMP_FORCE_mpn_neg) -__GMP_EXTERN_INLINE -#endif -mp_limb_t -mpn_neg (mp_ptr __gmp_rp, mp_srcptr __gmp_up, mp_size_t __gmp_n) -{ - while (*__gmp_up == 0) /* Low zero limbs are unchanged by negation. */ - { - *__gmp_rp = 0; - if (!--__gmp_n) /* All zero */ - return 0; - ++__gmp_up; ++__gmp_rp; - } - - *__gmp_rp = (- *__gmp_up) & GMP_NUMB_MASK; - - if (--__gmp_n) /* Higher limbs get complemented. */ - mpn_com (++__gmp_rp, ++__gmp_up, __gmp_n); - - return 1; -} -#endif - -#if defined (__cplusplus) -} -#endif - - -/* Allow faster testing for negative, zero, and positive. */ -#define mpz_sgn(Z) ((Z)->_mp_size < 0 ? -1 : (Z)->_mp_size > 0) -#define mpf_sgn(F) ((F)->_mp_size < 0 ? -1 : (F)->_mp_size > 0) -#define mpq_sgn(Q) ((Q)->_mp_num._mp_size < 0 ? -1 : (Q)->_mp_num._mp_size > 0) - -/* When using GCC, optimize certain common comparisons. */ -#if defined (__GNUC__) && __GNUC__ >= 2 -#define mpz_cmp_ui(Z,UI) \ - (__builtin_constant_p (UI) && (UI) == 0 \ - ? mpz_sgn (Z) : _mpz_cmp_ui (Z,UI)) -#define mpz_cmp_si(Z,SI) \ - (__builtin_constant_p ((SI) >= 0) && (SI) >= 0 \ - ? mpz_cmp_ui (Z, __GMP_CAST (unsigned long, SI)) \ - : _mpz_cmp_si (Z,SI)) -#define mpq_cmp_ui(Q,NUI,DUI) \ - (__builtin_constant_p (NUI) && (NUI) == 0 ? mpq_sgn (Q) \ - : __builtin_constant_p ((NUI) == (DUI)) && (NUI) == (DUI) \ - ? mpz_cmp (mpq_numref (Q), mpq_denref (Q)) \ - : _mpq_cmp_ui (Q,NUI,DUI)) -#define mpq_cmp_si(q,n,d) \ - (__builtin_constant_p ((n) >= 0) && (n) >= 0 \ - ? mpq_cmp_ui (q, __GMP_CAST (unsigned long, n), d) \ - : _mpq_cmp_si (q, n, d)) -#else -#define mpz_cmp_ui(Z,UI) _mpz_cmp_ui (Z,UI) -#define mpz_cmp_si(Z,UI) _mpz_cmp_si (Z,UI) -#define mpq_cmp_ui(Q,NUI,DUI) _mpq_cmp_ui (Q,NUI,DUI) -#define mpq_cmp_si(q,n,d) _mpq_cmp_si(q,n,d) -#endif - - -/* Using "&" rather than "&&" means these can come out branch-free. Every - mpz_t has at least one limb allocated, so fetching the low limb is always - allowed. */ -#define mpz_odd_p(z) (((z)->_mp_size != 0) & __GMP_CAST (int, (z)->_mp_d[0])) -#define mpz_even_p(z) (! mpz_odd_p (z)) - - -/**************** C++ routines ****************/ - -#ifdef __cplusplus -__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpz_srcptr); -__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpq_srcptr); -__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpf_srcptr); -__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpz_ptr); -__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpq_ptr); -__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpf_ptr); -#endif - - -/* Source-level compatibility with GMP 2 and earlier. */ -#define mpn_divmod(qp,np,nsize,dp,dsize) \ - mpn_divrem (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dp, dsize) - -/* Source-level compatibility with GMP 1. */ -#define mpz_mdiv mpz_fdiv_q -#define mpz_mdivmod mpz_fdiv_qr -#define mpz_mmod mpz_fdiv_r -#define mpz_mdiv_ui mpz_fdiv_q_ui -#define mpz_mdivmod_ui(q,r,n,d) \ - (((r) == 0) ? mpz_fdiv_q_ui (q,n,d) : mpz_fdiv_qr_ui (q,r,n,d)) -#define mpz_mmod_ui(r,n,d) \ - (((r) == 0) ? mpz_fdiv_ui (n,d) : mpz_fdiv_r_ui (r,n,d)) - -/* Useful synonyms, but not quite compatible with GMP 1. */ -#define mpz_div mpz_fdiv_q -#define mpz_divmod mpz_fdiv_qr -#define mpz_div_ui mpz_fdiv_q_ui -#define mpz_divmod_ui mpz_fdiv_qr_ui -#define mpz_div_2exp mpz_fdiv_q_2exp -#define mpz_mod_2exp mpz_fdiv_r_2exp - -enum -{ - GMP_ERROR_NONE = 0, - GMP_ERROR_UNSUPPORTED_ARGUMENT = 1, - GMP_ERROR_DIVISION_BY_ZERO = 2, - GMP_ERROR_SQRT_OF_NEGATIVE = 4, - GMP_ERROR_INVALID_ARGUMENT = 8 -}; - -/* Define CC and CFLAGS which were used to build this version of GMP */ -#define __GMP_CC "gcc" -#define __GMP_CFLAGS "-O2 -pedantic -march=armv8-a" - -/* Major version number is the value of __GNU_MP__ too, above. */ -#define __GNU_MP_VERSION 6 -#define __GNU_MP_VERSION_MINOR 2 -#define __GNU_MP_VERSION_PATCHLEVEL 1 -#define __GNU_MP_RELEASE (__GNU_MP_VERSION * 10000 + __GNU_MP_VERSION_MINOR * 100 + __GNU_MP_VERSION_PATCHLEVEL) - -#define __GMP_H__ -#endif /* __GMP_H__ */ diff --git a/include/gmpxx.h b/include/gmpxx.h deleted file mode 100644 index 0342116e..00000000 --- a/include/gmpxx.h +++ /dev/null @@ -1,3703 +0,0 @@ -/* gmpxx.h -- C++ class wrapper for GMP types. -*- C++ -*- - -Copyright 2001-2003, 2006, 2008, 2011-2015, 2018 Free Software -Foundation, Inc. - -This file is part of the GNU MP Library. - -The GNU MP Library is free software; you can redistribute it and/or modify -it under the terms of either: - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at your - option) any later version. - -or - - * the GNU General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - -or both in parallel, as here. - -The GNU MP Library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received copies of the GNU General Public License and the -GNU Lesser General Public License along with the GNU MP Library. If not, -see https://www.gnu.org/licenses/. */ - -#ifndef __GMP_PLUSPLUS__ -#define __GMP_PLUSPLUS__ - -#include - -#include /* for strlen */ -#include /* numeric_limits */ -#include -#include /* swap */ -#include -#include -#include -#include - -// wrapper for gcc's __builtin_constant_p -// __builtin_constant_p has been in gcc since forever, -// but g++-3.4 miscompiles it. -#if __GMP_GNUC_PREREQ(4, 2) -#define __GMPXX_CONSTANT(X) __builtin_constant_p(X) -#else -#define __GMPXX_CONSTANT(X) false -#endif -#define __GMPXX_CONSTANT_TRUE(X) (__GMPXX_CONSTANT(X) && (X)) - -// Use C++11 features -#ifndef __GMPXX_USE_CXX11 -#if __cplusplus >= 201103L -#define __GMPXX_USE_CXX11 1 -#else -#define __GMPXX_USE_CXX11 0 -#endif -#endif - -#if __GMPXX_USE_CXX11 -#define __GMPXX_NOEXCEPT noexcept -#include // for common_type -#else -#define __GMPXX_NOEXCEPT -#endif - -// Max allocations for plain types when converted to GMP types -#if GMP_NAIL_BITS != 0 && ! defined _LONG_LONG_LIMB -#define __GMPZ_ULI_LIMBS 2 -#else -#define __GMPZ_ULI_LIMBS 1 -#endif - -#define __GMPXX_BITS_TO_LIMBS(n) (((n) + (GMP_NUMB_BITS - 1)) / GMP_NUMB_BITS) -#define __GMPZ_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MAX_EXP)+1 -#define __GMPQ_NUM_DBL_LIMBS __GMPZ_DBL_LIMBS -#define __GMPQ_DEN_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MANT_DIG+1-DBL_MIN_EXP)+1 -// The final +1s are a security margin. The current implementation of -// mpq_set_d seems to need it for the denominator. - -inline void __mpz_set_ui_safe(mpz_ptr p, unsigned long l) -{ - p->_mp_size = (l != 0); - p->_mp_d[0] = l & GMP_NUMB_MASK; -#if __GMPZ_ULI_LIMBS > 1 - l >>= GMP_NUMB_BITS; - p->_mp_d[1] = l; - p->_mp_size += (l != 0); -#endif -} - -inline void __mpz_set_si_safe(mpz_ptr p, long l) -{ - if(l < 0) - { - __mpz_set_ui_safe(p, -static_cast(l)); - mpz_neg(p, p); - } - else - __mpz_set_ui_safe(p, l); - // Note: we know the high bit of l is 0 so we could do slightly better -} - -// Fake temporary variables -#define __GMPXX_TMPZ_UI \ - mpz_t temp; \ - mp_limb_t limbs[__GMPZ_ULI_LIMBS]; \ - temp->_mp_d = limbs; \ - __mpz_set_ui_safe (temp, l) -#define __GMPXX_TMPZ_SI \ - mpz_t temp; \ - mp_limb_t limbs[__GMPZ_ULI_LIMBS]; \ - temp->_mp_d = limbs; \ - __mpz_set_si_safe (temp, l) -#define __GMPXX_TMPZ_D \ - mpz_t temp; \ - mp_limb_t limbs[__GMPZ_DBL_LIMBS]; \ - temp->_mp_d = limbs; \ - temp->_mp_alloc = __GMPZ_DBL_LIMBS; \ - mpz_set_d (temp, d) - -#define __GMPXX_TMPQ_UI \ - mpq_t temp; \ - mp_limb_t limbs[__GMPZ_ULI_LIMBS+1]; \ - mpq_numref(temp)->_mp_d = limbs; \ - __mpz_set_ui_safe (mpq_numref(temp), l); \ - mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS; \ - mpq_denref(temp)->_mp_size = 1; \ - mpq_denref(temp)->_mp_d[0] = 1 -#define __GMPXX_TMPQ_SI \ - mpq_t temp; \ - mp_limb_t limbs[__GMPZ_ULI_LIMBS+1]; \ - mpq_numref(temp)->_mp_d = limbs; \ - __mpz_set_si_safe (mpq_numref(temp), l); \ - mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS; \ - mpq_denref(temp)->_mp_size = 1; \ - mpq_denref(temp)->_mp_d[0] = 1 -#define __GMPXX_TMPQ_D \ - mpq_t temp; \ - mp_limb_t limbs[__GMPQ_NUM_DBL_LIMBS + __GMPQ_DEN_DBL_LIMBS]; \ - mpq_numref(temp)->_mp_d = limbs; \ - mpq_numref(temp)->_mp_alloc = __GMPQ_NUM_DBL_LIMBS; \ - mpq_denref(temp)->_mp_d = limbs + __GMPQ_NUM_DBL_LIMBS; \ - mpq_denref(temp)->_mp_alloc = __GMPQ_DEN_DBL_LIMBS; \ - mpq_set_d (temp, d) - -inline unsigned long __gmpxx_abs_ui (signed long l) -{ - return l >= 0 ? static_cast(l) - : -static_cast(l); -} - -/**************** Function objects ****************/ -/* Any evaluation of a __gmp_expr ends up calling one of these functions - all intermediate functions being inline, the evaluation should optimize - to a direct call to the relevant function, thus yielding no overhead - over the C interface. */ - -struct __gmp_unary_plus -{ - static void eval(mpz_ptr z, mpz_srcptr w) { mpz_set(z, w); } - static void eval(mpq_ptr q, mpq_srcptr r) { mpq_set(q, r); } - static void eval(mpf_ptr f, mpf_srcptr g) { mpf_set(f, g); } -}; - -struct __gmp_unary_minus -{ - static void eval(mpz_ptr z, mpz_srcptr w) { mpz_neg(z, w); } - static void eval(mpq_ptr q, mpq_srcptr r) { mpq_neg(q, r); } - static void eval(mpf_ptr f, mpf_srcptr g) { mpf_neg(f, g); } -}; - -struct __gmp_unary_com -{ - static void eval(mpz_ptr z, mpz_srcptr w) { mpz_com(z, w); } -}; - -struct __gmp_binary_plus -{ - static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) - { mpz_add(z, w, v); } - - static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) - { - // Ideally, those checks should happen earlier so that the tree - // generated for a+0+b would just be sum(a,b). - if (__GMPXX_CONSTANT(l) && l == 0) - { - if (z != w) mpz_set(z, w); - } - else - mpz_add_ui(z, w, l); - } - static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) - { - if (l >= 0) - eval(z, w, static_cast(l)); - else - mpz_sub_ui(z, w, -static_cast(l)); - } - static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, double d) - { __GMPXX_TMPZ_D; mpz_add (z, w, temp); } - static void eval(mpz_ptr z, double d, mpz_srcptr w) - { eval(z, w, d); } - - static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s) - { mpq_add(q, r, s); } - - static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) - { - if (__GMPXX_CONSTANT(l) && l == 0) - { - if (q != r) mpq_set(q, r); - } - else if (__GMPXX_CONSTANT(l) && l == 1) - { - mpz_add (mpq_numref(q), mpq_numref(r), mpq_denref(r)); - if (q != r) mpz_set(mpq_denref(q), mpq_denref(r)); - } - else - { - if (q == r) - mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l); - else - { - mpz_mul_ui(mpq_numref(q), mpq_denref(r), l); - mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r)); - mpz_set(mpq_denref(q), mpq_denref(r)); - } - } - } - static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r) - { eval(q, r, l); } - static inline void eval(mpq_ptr q, mpq_srcptr r, signed long int l); - // defined after __gmp_binary_minus - static void eval(mpq_ptr q, signed long int l, mpq_srcptr r) - { eval(q, r, l); } - static void eval(mpq_ptr q, mpq_srcptr r, double d) - { __GMPXX_TMPQ_D; mpq_add (q, r, temp); } - static void eval(mpq_ptr q, double d, mpq_srcptr r) - { eval(q, r, d); } - - static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z) - { - if (q == r) - mpz_addmul(mpq_numref(q), mpq_denref(q), z); - else - { - mpz_mul(mpq_numref(q), mpq_denref(r), z); - mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r)); - mpz_set(mpq_denref(q), mpq_denref(r)); - } - } - static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r) - { eval(q, r, z); } - - static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) - { mpf_add(f, g, h); } - - static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) - { mpf_add_ui(f, g, l); } - static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) - { mpf_add_ui(f, g, l); } - static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) - { - if (l >= 0) - mpf_add_ui(f, g, l); - else - mpf_sub_ui(f, g, -static_cast(l)); - } - static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) - { eval(f, g, l); } - static void eval(mpf_ptr f, mpf_srcptr g, double d) - { - mpf_t temp; - mpf_init2(temp, 8*sizeof(double)); - mpf_set_d(temp, d); - mpf_add(f, g, temp); - mpf_clear(temp); - } - static void eval(mpf_ptr f, double d, mpf_srcptr g) - { eval(f, g, d); } -}; - -struct __gmp_binary_minus -{ - static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) - { mpz_sub(z, w, v); } - - static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) - { - if (__GMPXX_CONSTANT(l) && l == 0) - { - if (z != w) mpz_set(z, w); - } - else - mpz_sub_ui(z, w, l); - } - static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) - { - if (__GMPXX_CONSTANT(l) && l == 0) - { - mpz_neg(z, w); - } - else - mpz_ui_sub(z, l, w); - } - static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) - { - if (l >= 0) - eval(z, w, static_cast(l)); - else - mpz_add_ui(z, w, -static_cast(l)); - } - static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) - { - if (l >= 0) - eval(z, static_cast(l), w); - else - { - mpz_add_ui(z, w, -static_cast(l)); - mpz_neg(z, z); - } - } - static void eval(mpz_ptr z, mpz_srcptr w, double d) - { __GMPXX_TMPZ_D; mpz_sub (z, w, temp); } - static void eval(mpz_ptr z, double d, mpz_srcptr w) - { __GMPXX_TMPZ_D; mpz_sub (z, temp, w); } - - static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s) - { mpq_sub(q, r, s); } - - static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) - { - if (__GMPXX_CONSTANT(l) && l == 0) - { - if (q != r) mpq_set(q, r); - } - else if (__GMPXX_CONSTANT(l) && l == 1) - { - mpz_sub (mpq_numref(q), mpq_numref(r), mpq_denref(r)); - if (q != r) mpz_set(mpq_denref(q), mpq_denref(r)); - } - else - { - if (q == r) - mpz_submul_ui(mpq_numref(q), mpq_denref(q), l); - else - { - mpz_mul_ui(mpq_numref(q), mpq_denref(r), l); - mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q)); - mpz_set(mpq_denref(q), mpq_denref(r)); - } - } - } - static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r) - { eval(q, r, l); mpq_neg(q, q); } - static void eval(mpq_ptr q, mpq_srcptr r, signed long int l) - { - if (l >= 0) - eval(q, r, static_cast(l)); - else - __gmp_binary_plus::eval(q, r, -static_cast(l)); - } - static void eval(mpq_ptr q, signed long int l, mpq_srcptr r) - { eval(q, r, l); mpq_neg(q, q); } - static void eval(mpq_ptr q, mpq_srcptr r, double d) - { __GMPXX_TMPQ_D; mpq_sub (q, r, temp); } - static void eval(mpq_ptr q, double d, mpq_srcptr r) - { __GMPXX_TMPQ_D; mpq_sub (q, temp, r); } - - static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z) - { - if (q == r) - mpz_submul(mpq_numref(q), mpq_denref(q), z); - else - { - mpz_mul(mpq_numref(q), mpq_denref(r), z); - mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q)); - mpz_set(mpq_denref(q), mpq_denref(r)); - } - } - static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r) - { eval(q, r, z); mpq_neg(q, q); } - - static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) - { mpf_sub(f, g, h); } - - static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) - { mpf_sub_ui(f, g, l); } - static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) - { mpf_ui_sub(f, l, g); } - static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) - { - if (l >= 0) - mpf_sub_ui(f, g, l); - else - mpf_add_ui(f, g, -static_cast(l)); - } - static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) - { - if (l >= 0) - mpf_sub_ui(f, g, l); - else - mpf_add_ui(f, g, -static_cast(l)); - mpf_neg(f, f); - } - static void eval(mpf_ptr f, mpf_srcptr g, double d) - { - mpf_t temp; - mpf_init2(temp, 8*sizeof(double)); - mpf_set_d(temp, d); - mpf_sub(f, g, temp); - mpf_clear(temp); - } - static void eval(mpf_ptr f, double d, mpf_srcptr g) - { - mpf_t temp; - mpf_init2(temp, 8*sizeof(double)); - mpf_set_d(temp, d); - mpf_sub(f, temp, g); - mpf_clear(temp); - } -}; - -// defined here so it can reference __gmp_binary_minus -inline void -__gmp_binary_plus::eval(mpq_ptr q, mpq_srcptr r, signed long int l) -{ - if (l >= 0) - eval(q, r, static_cast(l)); - else - __gmp_binary_minus::eval(q, r, -static_cast(l)); -} - -struct __gmp_binary_lshift -{ - static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l) - { - if (__GMPXX_CONSTANT(l) && (l == 0)) - { - if (z != w) mpz_set(z, w); - } - else - mpz_mul_2exp(z, w, l); - } - static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l) - { - if (__GMPXX_CONSTANT(l) && (l == 0)) - { - if (q != r) mpq_set(q, r); - } - else - mpq_mul_2exp(q, r, l); - } - static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l) - { mpf_mul_2exp(f, g, l); } -}; - -struct __gmp_binary_rshift -{ - static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l) - { - if (__GMPXX_CONSTANT(l) && (l == 0)) - { - if (z != w) mpz_set(z, w); - } - else - mpz_fdiv_q_2exp(z, w, l); - } - static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l) - { - if (__GMPXX_CONSTANT(l) && (l == 0)) - { - if (q != r) mpq_set(q, r); - } - else - mpq_div_2exp(q, r, l); - } - static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l) - { mpf_div_2exp(f, g, l); } -}; - -struct __gmp_binary_multiplies -{ - static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) - { mpz_mul(z, w, v); } - - static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) - { -// gcc-3.3 doesn't have __builtin_ctzl. Don't bother optimizing for old gcc. -#if __GMP_GNUC_PREREQ(3, 4) - if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0) - { - if (l == 0) - { - z->_mp_size = 0; - } - else - { - __gmp_binary_lshift::eval(z, w, __builtin_ctzl(l)); - } - } - else -#endif - mpz_mul_ui(z, w, l); - } - static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) - { - if (__GMPXX_CONSTANT_TRUE(l >= 0)) - eval(z, w, static_cast(l)); - else if (__GMPXX_CONSTANT_TRUE(l <= 0)) - { - eval(z, w, -static_cast(l)); - mpz_neg(z, z); - } - else - mpz_mul_si (z, w, l); - } - static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, double d) - { __GMPXX_TMPZ_D; mpz_mul (z, w, temp); } - static void eval(mpz_ptr z, double d, mpz_srcptr w) - { eval(z, w, d); } - - static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s) - { mpq_mul(q, r, s); } - - static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) - { -#if __GMP_GNUC_PREREQ(3, 4) - if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0) - { - if (l == 0) - { - mpq_set_ui(q, 0, 1); - } - else - { - __gmp_binary_lshift::eval(q, r, __builtin_ctzl(l)); - } - } - else -#endif - { - __GMPXX_TMPQ_UI; - mpq_mul (q, r, temp); - } - } - static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r) - { eval(q, r, l); } - static void eval(mpq_ptr q, mpq_srcptr r, signed long int l) - { - if (__GMPXX_CONSTANT_TRUE(l >= 0)) - eval(q, r, static_cast(l)); - else if (__GMPXX_CONSTANT_TRUE(l <= 0)) - { - eval(q, r, -static_cast(l)); - mpq_neg(q, q); - } - else - { - __GMPXX_TMPQ_SI; - mpq_mul (q, r, temp); - } - } - static void eval(mpq_ptr q, signed long int l, mpq_srcptr r) - { eval(q, r, l); } - static void eval(mpq_ptr q, mpq_srcptr r, double d) - { __GMPXX_TMPQ_D; mpq_mul (q, r, temp); } - static void eval(mpq_ptr q, double d, mpq_srcptr r) - { eval(q, r, d); } - - static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) - { mpf_mul(f, g, h); } - - static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) - { mpf_mul_ui(f, g, l); } - static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) - { mpf_mul_ui(f, g, l); } - static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) - { - if (l >= 0) - mpf_mul_ui(f, g, l); - else - { - mpf_mul_ui(f, g, -static_cast(l)); - mpf_neg(f, f); - } - } - static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) - { eval(f, g, l); } - static void eval(mpf_ptr f, mpf_srcptr g, double d) - { - mpf_t temp; - mpf_init2(temp, 8*sizeof(double)); - mpf_set_d(temp, d); - mpf_mul(f, g, temp); - mpf_clear(temp); - } - static void eval(mpf_ptr f, double d, mpf_srcptr g) - { eval(f, g, d); } -}; - -struct __gmp_binary_divides -{ - static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) - { mpz_tdiv_q(z, w, v); } - - static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) - { -#if __GMP_GNUC_PREREQ(3, 4) - // Don't optimize division by 0... - if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0) - { - if (l == 1) - { - if (z != w) mpz_set(z, w); - } - else - mpz_tdiv_q_2exp(z, w, __builtin_ctzl(l)); - // warning: do not use rshift (fdiv) - } - else -#endif - mpz_tdiv_q_ui(z, w, l); - } - static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) - { - if (mpz_sgn(w) >= 0) - { - if (mpz_fits_ulong_p(w)) - mpz_set_ui(z, l / mpz_get_ui(w)); - else - mpz_set_ui(z, 0); - } - else - { - mpz_neg(z, w); - if (mpz_fits_ulong_p(z)) - { - mpz_set_ui(z, l / mpz_get_ui(z)); - mpz_neg(z, z); - } - else - mpz_set_ui(z, 0); - } - } - static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) - { - if (l >= 0) - eval(z, w, static_cast(l)); - else - { - eval(z, w, -static_cast(l)); - mpz_neg(z, z); - } - } - static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) - { - if (mpz_fits_slong_p(w)) - mpz_set_si(z, l / mpz_get_si(w)); - else - { - /* if w is bigger than a long then the quotient must be zero, unless - l==LONG_MIN and w==-LONG_MIN in which case the quotient is -1 */ - mpz_set_si (z, (mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? -1 : 0)); - } - } - static void eval(mpz_ptr z, mpz_srcptr w, double d) - { __GMPXX_TMPZ_D; mpz_tdiv_q (z, w, temp); } - static void eval(mpz_ptr z, double d, mpz_srcptr w) - { __GMPXX_TMPZ_D; mpz_tdiv_q (z, temp, w); } - - static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s) - { mpq_div(q, r, s); } - - static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) - { -#if __GMP_GNUC_PREREQ(3, 4) - if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0) - __gmp_binary_rshift::eval(q, r, __builtin_ctzl(l)); - else -#endif - { - __GMPXX_TMPQ_UI; - mpq_div (q, r, temp); - } - } - static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r) - { - if (__GMPXX_CONSTANT_TRUE(l == 0)) - mpq_set_ui(q, 0, 1); - else if (__GMPXX_CONSTANT_TRUE(l == 1)) - mpq_inv(q, r); - else - { - __GMPXX_TMPQ_UI; - mpq_div (q, temp, r); - } - } - static void eval(mpq_ptr q, mpq_srcptr r, signed long int l) - { - if (__GMPXX_CONSTANT_TRUE(l >= 0)) - eval(q, r, static_cast(l)); - else if (__GMPXX_CONSTANT_TRUE(l <= 0)) - { - eval(q, r, -static_cast(l)); - mpq_neg(q, q); - } - else - { - __GMPXX_TMPQ_SI; - mpq_div (q, r, temp); - } - } - static void eval(mpq_ptr q, signed long int l, mpq_srcptr r) - { - if (__GMPXX_CONSTANT_TRUE(l == 0)) - mpq_set_ui(q, 0, 1); - else if (__GMPXX_CONSTANT_TRUE(l == 1)) - mpq_inv(q, r); - else if (__GMPXX_CONSTANT_TRUE(l == -1)) - { - mpq_inv(q, r); - mpq_neg(q, q); - } - else - { - __GMPXX_TMPQ_SI; - mpq_div (q, temp, r); - } - } - static void eval(mpq_ptr q, mpq_srcptr r, double d) - { __GMPXX_TMPQ_D; mpq_div (q, r, temp); } - static void eval(mpq_ptr q, double d, mpq_srcptr r) - { __GMPXX_TMPQ_D; mpq_div (q, temp, r); } - - static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) - { mpf_div(f, g, h); } - - static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) - { mpf_div_ui(f, g, l); } - static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) - { mpf_ui_div(f, l, g); } - static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) - { - if (l >= 0) - mpf_div_ui(f, g, l); - else - { - mpf_div_ui(f, g, -static_cast(l)); - mpf_neg(f, f); - } - } - static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) - { - if (l >= 0) - mpf_ui_div(f, l, g); - else - { - mpf_ui_div(f, -static_cast(l), g); - mpf_neg(f, f); - } - } - static void eval(mpf_ptr f, mpf_srcptr g, double d) - { - mpf_t temp; - mpf_init2(temp, 8*sizeof(double)); - mpf_set_d(temp, d); - mpf_div(f, g, temp); - mpf_clear(temp); - } - static void eval(mpf_ptr f, double d, mpf_srcptr g) - { - mpf_t temp; - mpf_init2(temp, 8*sizeof(double)); - mpf_set_d(temp, d); - mpf_div(f, temp, g); - mpf_clear(temp); - } -}; - -struct __gmp_binary_modulus -{ - static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) - { mpz_tdiv_r(z, w, v); } - - static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) - { mpz_tdiv_r_ui(z, w, l); } - static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) - { - if (mpz_sgn(w) >= 0) - { - if (mpz_fits_ulong_p(w)) - mpz_set_ui(z, l % mpz_get_ui(w)); - else - mpz_set_ui(z, l); - } - else - { - mpz_neg(z, w); - if (mpz_fits_ulong_p(z)) - mpz_set_ui(z, l % mpz_get_ui(z)); - else - mpz_set_ui(z, l); - } - } - static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) - { - mpz_tdiv_r_ui (z, w, __gmpxx_abs_ui(l)); - } - static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) - { - if (mpz_fits_slong_p(w)) - mpz_set_si(z, l % mpz_get_si(w)); - else - { - /* if w is bigger than a long then the remainder is l unchanged, - unless l==LONG_MIN and w==-LONG_MIN in which case it's 0 */ - mpz_set_si (z, mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? 0 : l); - } - } - static void eval(mpz_ptr z, mpz_srcptr w, double d) - { __GMPXX_TMPZ_D; mpz_tdiv_r (z, w, temp); } - static void eval(mpz_ptr z, double d, mpz_srcptr w) - { __GMPXX_TMPZ_D; mpz_tdiv_r (z, temp, w); } -}; - -struct __gmp_binary_and -{ - static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) - { mpz_and(z, w, v); } - - static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) - { __GMPXX_TMPZ_UI; mpz_and (z, w, temp); } - static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) - { __GMPXX_TMPZ_SI; mpz_and (z, w, temp); } - static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, double d) - { __GMPXX_TMPZ_D; mpz_and (z, w, temp); } - static void eval(mpz_ptr z, double d, mpz_srcptr w) - { eval(z, w, d); } -}; - -struct __gmp_binary_ior -{ - static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) - { mpz_ior(z, w, v); } - static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) - { __GMPXX_TMPZ_UI; mpz_ior (z, w, temp); } - static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) - { __GMPXX_TMPZ_SI; mpz_ior (z, w, temp); } - static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, double d) - { __GMPXX_TMPZ_D; mpz_ior (z, w, temp); } - static void eval(mpz_ptr z, double d, mpz_srcptr w) - { eval(z, w, d); } -}; - -struct __gmp_binary_xor -{ - static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) - { mpz_xor(z, w, v); } - static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) - { __GMPXX_TMPZ_UI; mpz_xor (z, w, temp); } - static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) - { __GMPXX_TMPZ_SI; mpz_xor (z, w, temp); } - static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, double d) - { __GMPXX_TMPZ_D; mpz_xor (z, w, temp); } - static void eval(mpz_ptr z, double d, mpz_srcptr w) - { eval(z, w, d); } -}; - -struct __gmp_cmp_function -{ - static int eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w); } - - static int eval(mpz_srcptr z, unsigned long int l) - { return mpz_cmp_ui(z, l); } - static int eval(unsigned long int l, mpz_srcptr z) - { return -mpz_cmp_ui(z, l); } - static int eval(mpz_srcptr z, signed long int l) - { return mpz_cmp_si(z, l); } - static int eval(signed long int l, mpz_srcptr z) - { return -mpz_cmp_si(z, l); } - static int eval(mpz_srcptr z, double d) - { return mpz_cmp_d(z, d); } - static int eval(double d, mpz_srcptr z) - { return -mpz_cmp_d(z, d); } - - static int eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r); } - - static int eval(mpq_srcptr q, unsigned long int l) - { return mpq_cmp_ui(q, l, 1); } - static int eval(unsigned long int l, mpq_srcptr q) - { return -mpq_cmp_ui(q, l, 1); } - static int eval(mpq_srcptr q, signed long int l) - { return mpq_cmp_si(q, l, 1); } - static int eval(signed long int l, mpq_srcptr q) - { return -mpq_cmp_si(q, l, 1); } - static int eval(mpq_srcptr q, double d) - { __GMPXX_TMPQ_D; return mpq_cmp (q, temp); } - static int eval(double d, mpq_srcptr q) - { __GMPXX_TMPQ_D; return mpq_cmp (temp, q); } - static int eval(mpq_srcptr q, mpz_srcptr z) - { return mpq_cmp_z(q, z); } - static int eval(mpz_srcptr z, mpq_srcptr q) - { return -mpq_cmp_z(q, z); } - - static int eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g); } - - static int eval(mpf_srcptr f, unsigned long int l) - { return mpf_cmp_ui(f, l); } - static int eval(unsigned long int l, mpf_srcptr f) - { return -mpf_cmp_ui(f, l); } - static int eval(mpf_srcptr f, signed long int l) - { return mpf_cmp_si(f, l); } - static int eval(signed long int l, mpf_srcptr f) - { return -mpf_cmp_si(f, l); } - static int eval(mpf_srcptr f, double d) - { return mpf_cmp_d(f, d); } - static int eval(double d, mpf_srcptr f) - { return -mpf_cmp_d(f, d); } - static int eval(mpf_srcptr f, mpz_srcptr z) - { return mpf_cmp_z(f, z); } - static int eval(mpz_srcptr z, mpf_srcptr f) - { return -mpf_cmp_z(f, z); } - static int eval(mpf_srcptr f, mpq_srcptr q) - { - mpf_t qf; - mpf_init(qf); /* Should we use the precision of f? */ - mpf_set_q(qf, q); - int ret = eval(f, qf); - mpf_clear(qf); - return ret; - } - static int eval(mpq_srcptr q, mpf_srcptr f) - { return -eval(f, q); } -}; - -struct __gmp_binary_equal -{ - static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) == 0; } - - static bool eval(mpz_srcptr z, unsigned long int l) - { return mpz_cmp_ui(z, l) == 0; } - static bool eval(unsigned long int l, mpz_srcptr z) - { return eval(z, l); } - static bool eval(mpz_srcptr z, signed long int l) - { return mpz_cmp_si(z, l) == 0; } - static bool eval(signed long int l, mpz_srcptr z) - { return eval(z, l); } - static bool eval(mpz_srcptr z, double d) - { return mpz_cmp_d(z, d) == 0; } - static bool eval(double d, mpz_srcptr z) - { return eval(z, d); } - - static bool eval(mpq_srcptr q, mpq_srcptr r) - { return mpq_equal(q, r) != 0; } - - static bool eval(mpq_srcptr q, unsigned long int l) - { return ((__GMPXX_CONSTANT(l) && l == 0) || - mpz_cmp_ui(mpq_denref(q), 1) == 0) && - mpz_cmp_ui(mpq_numref(q), l) == 0; } - static bool eval(unsigned long int l, mpq_srcptr q) - { return eval(q, l); } - static bool eval(mpq_srcptr q, signed long int l) - { return ((__GMPXX_CONSTANT(l) && l == 0) || - mpz_cmp_ui(mpq_denref(q), 1) == 0) && - mpz_cmp_si(mpq_numref(q), l) == 0; } - static bool eval(signed long int l, mpq_srcptr q) - { return eval(q, l); } - static bool eval(mpq_srcptr q, double d) - { __GMPXX_TMPQ_D; return mpq_equal (q, temp) != 0; } - static bool eval(double d, mpq_srcptr q) - { return eval(q, d); } - static bool eval(mpq_srcptr q, mpz_srcptr z) - { return mpz_cmp_ui(mpq_denref(q), 1) == 0 && mpz_cmp(mpq_numref(q), z) == 0; } - static bool eval(mpz_srcptr z, mpq_srcptr q) - { return eval(q, z); } - - static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) == 0; } - - static bool eval(mpf_srcptr f, unsigned long int l) - { return mpf_cmp_ui(f, l) == 0; } - static bool eval(unsigned long int l, mpf_srcptr f) - { return eval(f, l); } - static bool eval(mpf_srcptr f, signed long int l) - { return mpf_cmp_si(f, l) == 0; } - static bool eval(signed long int l, mpf_srcptr f) - { return eval(f, l); } - static bool eval(mpf_srcptr f, double d) - { return mpf_cmp_d(f, d) == 0; } - static bool eval(double d, mpf_srcptr f) - { return eval(f, d); } - static bool eval(mpf_srcptr f, mpz_srcptr z) - { return mpf_cmp_z(f, z) == 0; } - static bool eval(mpz_srcptr z, mpf_srcptr f) - { return eval(f, z); } - static bool eval(mpf_srcptr f, mpq_srcptr q) - { return __gmp_cmp_function::eval(f, q) == 0; } - static bool eval(mpq_srcptr q, mpf_srcptr f) - { return eval(f, q); } -}; - -struct __gmp_binary_less -{ - static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) < 0; } - - static bool eval(mpz_srcptr z, unsigned long int l) - { return mpz_cmp_ui(z, l) < 0; } - static bool eval(unsigned long int l, mpz_srcptr z) - { return mpz_cmp_ui(z, l) > 0; } - static bool eval(mpz_srcptr z, signed long int l) - { return mpz_cmp_si(z, l) < 0; } - static bool eval(signed long int l, mpz_srcptr z) - { return mpz_cmp_si(z, l) > 0; } - static bool eval(mpz_srcptr z, double d) - { return mpz_cmp_d(z, d) < 0; } - static bool eval(double d, mpz_srcptr z) - { return mpz_cmp_d(z, d) > 0; } - - static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) < 0; } - - static bool eval(mpq_srcptr q, unsigned long int l) - { return mpq_cmp_ui(q, l, 1) < 0; } - static bool eval(unsigned long int l, mpq_srcptr q) - { return mpq_cmp_ui(q, l, 1) > 0; } - static bool eval(mpq_srcptr q, signed long int l) - { return mpq_cmp_si(q, l, 1) < 0; } - static bool eval(signed long int l, mpq_srcptr q) - { return mpq_cmp_si(q, l, 1) > 0; } - static bool eval(mpq_srcptr q, double d) - { __GMPXX_TMPQ_D; return mpq_cmp (q, temp) < 0; } - static bool eval(double d, mpq_srcptr q) - { __GMPXX_TMPQ_D; return mpq_cmp (temp, q) < 0; } - static bool eval(mpq_srcptr q, mpz_srcptr z) - { return mpq_cmp_z(q, z) < 0; } - static bool eval(mpz_srcptr z, mpq_srcptr q) - { return mpq_cmp_z(q, z) > 0; } - - static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) < 0; } - - static bool eval(mpf_srcptr f, unsigned long int l) - { return mpf_cmp_ui(f, l) < 0; } - static bool eval(unsigned long int l, mpf_srcptr f) - { return mpf_cmp_ui(f, l) > 0; } - static bool eval(mpf_srcptr f, signed long int l) - { return mpf_cmp_si(f, l) < 0; } - static bool eval(signed long int l, mpf_srcptr f) - { return mpf_cmp_si(f, l) > 0; } - static bool eval(mpf_srcptr f, double d) - { return mpf_cmp_d(f, d) < 0; } - static bool eval(double d, mpf_srcptr f) - { return mpf_cmp_d(f, d) > 0; } - static bool eval(mpf_srcptr f, mpz_srcptr z) - { return mpf_cmp_z(f, z) < 0; } - static bool eval(mpz_srcptr z, mpf_srcptr f) - { return mpf_cmp_z(f, z) > 0; } - static bool eval(mpf_srcptr f, mpq_srcptr q) - { return __gmp_cmp_function::eval(f, q) < 0; } - static bool eval(mpq_srcptr q, mpf_srcptr f) - { return __gmp_cmp_function::eval(q, f) < 0; } -}; - -struct __gmp_binary_greater -{ - template - static inline bool eval(T t, U u) { return __gmp_binary_less::eval(u, t); } -}; - -struct __gmp_unary_increment -{ - static void eval(mpz_ptr z) { mpz_add_ui(z, z, 1); } - static void eval(mpq_ptr q) - { mpz_add(mpq_numref(q), mpq_numref(q), mpq_denref(q)); } - static void eval(mpf_ptr f) { mpf_add_ui(f, f, 1); } -}; - -struct __gmp_unary_decrement -{ - static void eval(mpz_ptr z) { mpz_sub_ui(z, z, 1); } - static void eval(mpq_ptr q) - { mpz_sub(mpq_numref(q), mpq_numref(q), mpq_denref(q)); } - static void eval(mpf_ptr f) { mpf_sub_ui(f, f, 1); } -}; - -struct __gmp_abs_function -{ - static void eval(mpz_ptr z, mpz_srcptr w) { mpz_abs(z, w); } - static void eval(mpq_ptr q, mpq_srcptr r) { mpq_abs(q, r); } - static void eval(mpf_ptr f, mpf_srcptr g) { mpf_abs(f, g); } -}; - -struct __gmp_trunc_function -{ - static void eval(mpf_ptr f, mpf_srcptr g) { mpf_trunc(f, g); } -}; - -struct __gmp_floor_function -{ - static void eval(mpf_ptr f, mpf_srcptr g) { mpf_floor(f, g); } -}; - -struct __gmp_ceil_function -{ - static void eval(mpf_ptr f, mpf_srcptr g) { mpf_ceil(f, g); } -}; - -struct __gmp_sqrt_function -{ - static void eval(mpz_ptr z, mpz_srcptr w) { mpz_sqrt(z, w); } - static void eval(mpf_ptr f, mpf_srcptr g) { mpf_sqrt(f, g); } -}; - -struct __gmp_hypot_function -{ - static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) - { - mpf_t temp; - mpf_init2(temp, mpf_get_prec(f)); - mpf_mul(temp, g, g); - mpf_mul(f, h, h); - mpf_add(f, f, temp); - mpf_sqrt(f, f); - mpf_clear(temp); - } - - static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) - { - mpf_t temp; - mpf_init2(temp, mpf_get_prec(f)); - mpf_mul(temp, g, g); - mpf_set_ui(f, l); - mpf_mul_ui(f, f, l); - mpf_add(f, f, temp); - mpf_clear(temp); - mpf_sqrt(f, f); - } - static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) - { eval(f, g, l); } - static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) - { eval(f, g, __gmpxx_abs_ui(l)); } - static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) - { eval(f, g, l); } - static void eval(mpf_ptr f, mpf_srcptr g, double d) - { - mpf_t temp; - mpf_init2(temp, mpf_get_prec(f)); - mpf_mul(temp, g, g); - mpf_set_d(f, d); - mpf_mul(f, f, f); - mpf_add(f, f, temp); - mpf_sqrt(f, f); - mpf_clear(temp); - } - static void eval(mpf_ptr f, double d, mpf_srcptr g) - { eval(f, g, d); } -}; - -struct __gmp_sgn_function -{ - static int eval(mpz_srcptr z) { return mpz_sgn(z); } - static int eval(mpq_srcptr q) { return mpq_sgn(q); } - static int eval(mpf_srcptr f) { return mpf_sgn(f); } -}; - -struct __gmp_gcd_function -{ - static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) - { mpz_gcd(z, w, v); } - static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) - { mpz_gcd_ui(z, w, l); } - static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) - { eval(z, w, __gmpxx_abs_ui(l)); } - static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, double d) - { __GMPXX_TMPZ_D; mpz_gcd (z, w, temp); } - static void eval(mpz_ptr z, double d, mpz_srcptr w) - { eval(z, w, d); } -}; - -struct __gmp_lcm_function -{ - static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) - { mpz_lcm(z, w, v); } - static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) - { mpz_lcm_ui(z, w, l); } - static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) - { eval(z, w, __gmpxx_abs_ui(l)); } - static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) - { eval(z, w, l); } - static void eval(mpz_ptr z, mpz_srcptr w, double d) - { __GMPXX_TMPZ_D; mpz_lcm (z, w, temp); } - static void eval(mpz_ptr z, double d, mpz_srcptr w) - { eval(z, w, d); } -}; - -struct __gmp_rand_function -{ - static void eval(mpz_ptr z, gmp_randstate_t s, mp_bitcnt_t l) - { mpz_urandomb(z, s, l); } - static void eval(mpz_ptr z, gmp_randstate_t s, mpz_srcptr w) - { mpz_urandomm(z, s, w); } - static void eval(mpf_ptr f, gmp_randstate_t s, mp_bitcnt_t prec) - { mpf_urandomb(f, s, prec); } -}; - -struct __gmp_fac_function -{ - static void eval(mpz_ptr z, unsigned long l) { mpz_fac_ui(z, l); } - static void eval(mpz_ptr z, signed long l) - { - if (l < 0) - throw std::domain_error ("factorial(negative)"); - eval(z, static_cast(l)); - } - static void eval(mpz_ptr z, mpz_srcptr w) - { - if (!mpz_fits_ulong_p(w)) - { - if (mpz_sgn(w) < 0) - throw std::domain_error ("factorial(negative)"); - else - throw std::bad_alloc(); // or std::overflow_error ("factorial")? - } - eval(z, mpz_get_ui(w)); - } - static void eval(mpz_ptr z, double d) - { __GMPXX_TMPZ_D; eval (z, temp); } -}; - -struct __gmp_primorial_function -{ - static void eval(mpz_ptr z, unsigned long l) { mpz_primorial_ui(z, l); } - static void eval(mpz_ptr z, signed long l) - { - if (l < 0) - throw std::domain_error ("primorial(negative)"); - eval(z, static_cast(l)); - } - static void eval(mpz_ptr z, mpz_srcptr w) - { - if (!mpz_fits_ulong_p(w)) - { - if (mpz_sgn(w) < 0) - throw std::domain_error ("primorial(negative)"); - else - throw std::bad_alloc(); // or std::overflow_error ("primorial")? - } - eval(z, mpz_get_ui(w)); - } - static void eval(mpz_ptr z, double d) - { __GMPXX_TMPZ_D; eval (z, temp); } -}; - -struct __gmp_fib_function -{ - static void eval(mpz_ptr z, unsigned long l) { mpz_fib_ui(z, l); } - static void eval(mpz_ptr z, signed long l) - { - if (l < 0) - { - eval(z, -static_cast(l)); - if ((l & 1) == 0) - mpz_neg(z, z); - } - else - eval(z, static_cast(l)); - } - static void eval(mpz_ptr z, mpz_srcptr w) - { - if (!mpz_fits_slong_p(w)) - throw std::bad_alloc(); // or std::overflow_error ("fibonacci")? - eval(z, mpz_get_si(w)); - } - static void eval(mpz_ptr z, double d) - { __GMPXX_TMPZ_D; eval (z, temp); } -}; - - -/**************** Auxiliary classes ****************/ - -/* this is much the same as gmp_allocated_string in gmp-impl.h - since gmp-impl.h is not publicly available, I redefine it here - I use a different name to avoid possible clashes */ - -extern "C" { - typedef void (*__gmp_freefunc_t) (void *, size_t); -} -struct __gmp_alloc_cstring -{ - char *str; - __gmp_alloc_cstring(char *s) { str = s; } - ~__gmp_alloc_cstring() - { - __gmp_freefunc_t freefunc; - mp_get_memory_functions (NULL, NULL, &freefunc); - (*freefunc) (str, std::strlen(str)+1); - } -}; - - -// general expression template class -template -class __gmp_expr; - - -// templates for resolving expression types -template -struct __gmp_resolve_ref -{ - typedef T ref_type; -}; - -template -struct __gmp_resolve_ref<__gmp_expr > -{ - typedef const __gmp_expr & ref_type; -}; - - -template -struct __gmp_resolve_expr; - -template <> -struct __gmp_resolve_expr -{ - typedef mpz_t value_type; - typedef mpz_ptr ptr_type; - typedef mpz_srcptr srcptr_type; -}; - -template <> -struct __gmp_resolve_expr -{ - typedef mpq_t value_type; - typedef mpq_ptr ptr_type; - typedef mpq_srcptr srcptr_type; -}; - -template <> -struct __gmp_resolve_expr -{ - typedef mpf_t value_type; - typedef mpf_ptr ptr_type; - typedef mpf_srcptr srcptr_type; -}; - -template <> -struct __gmp_resolve_expr -{ - typedef mpq_t value_type; -}; - -template <> -struct __gmp_resolve_expr -{ - typedef mpq_t value_type; -}; - -template <> -struct __gmp_resolve_expr -{ - typedef mpf_t value_type; -}; - -template <> -struct __gmp_resolve_expr -{ - typedef mpf_t value_type; -}; - -template <> -struct __gmp_resolve_expr -{ - typedef mpf_t value_type; -}; - -template <> -struct __gmp_resolve_expr -{ - typedef mpf_t value_type; -}; - -#if __GMPXX_USE_CXX11 -namespace std { - template - struct common_type <__gmp_expr, __gmp_expr > - { - private: - typedef typename __gmp_resolve_expr::value_type X; - public: - typedef __gmp_expr type; - }; - - template - struct common_type <__gmp_expr > - { - typedef __gmp_expr type; - }; - -#define __GMPXX_DECLARE_COMMON_TYPE(typ) \ - template \ - struct common_type <__gmp_expr, typ > \ - { \ - typedef __gmp_expr type; \ - }; \ - \ - template \ - struct common_type > \ - { \ - typedef __gmp_expr type; \ - } - - __GMPXX_DECLARE_COMMON_TYPE(signed char); - __GMPXX_DECLARE_COMMON_TYPE(unsigned char); - __GMPXX_DECLARE_COMMON_TYPE(signed int); - __GMPXX_DECLARE_COMMON_TYPE(unsigned int); - __GMPXX_DECLARE_COMMON_TYPE(signed short int); - __GMPXX_DECLARE_COMMON_TYPE(unsigned short int); - __GMPXX_DECLARE_COMMON_TYPE(signed long int); - __GMPXX_DECLARE_COMMON_TYPE(unsigned long int); - __GMPXX_DECLARE_COMMON_TYPE(float); - __GMPXX_DECLARE_COMMON_TYPE(double); -#undef __GMPXX_DECLARE_COMMON_TYPE -} -#endif - -// classes for evaluating unary and binary expressions -template -struct __gmp_unary_expr -{ - typename __gmp_resolve_ref::ref_type val; - - __gmp_unary_expr(const T &v) : val(v) { } -private: - __gmp_unary_expr(); -}; - -template -struct __gmp_binary_expr -{ - typename __gmp_resolve_ref::ref_type val1; - typename __gmp_resolve_ref::ref_type val2; - - __gmp_binary_expr(const T &v1, const U &v2) : val1(v1), val2(v2) { } -private: - __gmp_binary_expr(); -}; - - - -/**************** Macros for in-class declarations ****************/ -/* This is just repetitive code that is easier to maintain if it's written - only once */ - -#define __GMPP_DECLARE_COMPOUND_OPERATOR(fun) \ - template \ - __gmp_expr & fun(const __gmp_expr &); - -#define __GMPN_DECLARE_COMPOUND_OPERATOR(fun) \ - __gmp_expr & fun(signed char); \ - __gmp_expr & fun(unsigned char); \ - __gmp_expr & fun(signed int); \ - __gmp_expr & fun(unsigned int); \ - __gmp_expr & fun(signed short int); \ - __gmp_expr & fun(unsigned short int); \ - __gmp_expr & fun(signed long int); \ - __gmp_expr & fun(unsigned long int); \ - __gmp_expr & fun(float); \ - __gmp_expr & fun(double); \ - /* __gmp_expr & fun(long double); */ - -#define __GMP_DECLARE_COMPOUND_OPERATOR(fun) \ -__GMPP_DECLARE_COMPOUND_OPERATOR(fun) \ -__GMPN_DECLARE_COMPOUND_OPERATOR(fun) - -#define __GMP_DECLARE_COMPOUND_OPERATOR_UI(fun) \ - __gmp_expr & fun(mp_bitcnt_t); - -#define __GMP_DECLARE_INCREMENT_OPERATOR(fun) \ - inline __gmp_expr & fun(); \ - inline __gmp_expr fun(int); - -#define __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS \ - __gmp_expr(signed char c) { init_si(c); } \ - __gmp_expr(unsigned char c) { init_ui(c); } \ - __gmp_expr(signed int i) { init_si(i); } \ - __gmp_expr(unsigned int i) { init_ui(i); } \ - __gmp_expr(signed short int s) { init_si(s); } \ - __gmp_expr(unsigned short int s) { init_ui(s); } \ - __gmp_expr(signed long int l) { init_si(l); } \ - __gmp_expr(unsigned long int l) { init_ui(l); } \ - __gmp_expr(float f) { init_d(f); } \ - __gmp_expr(double d) { init_d(d); } - -#define __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS \ - __gmp_expr & operator=(signed char c) { assign_si(c); return *this; } \ - __gmp_expr & operator=(unsigned char c) { assign_ui(c); return *this; } \ - __gmp_expr & operator=(signed int i) { assign_si(i); return *this; } \ - __gmp_expr & operator=(unsigned int i) { assign_ui(i); return *this; } \ - __gmp_expr & operator=(signed short int s) { assign_si(s); return *this; } \ - __gmp_expr & operator=(unsigned short int s) { assign_ui(s); return *this; } \ - __gmp_expr & operator=(signed long int l) { assign_si(l); return *this; } \ - __gmp_expr & operator=(unsigned long int l) { assign_ui(l); return *this; } \ - __gmp_expr & operator=(float f) { assign_d(f); return *this; } \ - __gmp_expr & operator=(double d) { assign_d(d); return *this; } - -#define __GMPP_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun) \ -template \ -static __gmp_expr, eval_fun> > \ -fun(const __gmp_expr &expr); - -#define __GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, bigtype) \ -static inline __gmp_expr > \ -fun(type expr); - -#define __GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type) \ -__GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, signed long) -#define __GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type) \ -__GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, unsigned long) -#define __GMPND_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type) \ -__GMPNN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, double) - -#define __GMPN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun) \ -__GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed char) \ -__GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned char) \ -__GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed int) \ -__GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned int) \ -__GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed short int) \ -__GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned short int) \ -__GMPNS_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed long int) \ -__GMPNU_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned long int) \ -__GMPND_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, float) \ -__GMPND_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, double) - -#define __GMP_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun) \ -__GMPP_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun) \ -__GMPN_DECLARE_UNARY_STATIC_MEMFUN(T, fun, eval_fun) - -/**************** mpz_class -- wrapper for mpz_t ****************/ - -template <> -class __gmp_expr -{ -private: - typedef mpz_t value_type; - value_type mp; - - // Helper functions used for all arithmetic types - void assign_ui(unsigned long l) - { - if (__GMPXX_CONSTANT_TRUE(l == 0)) - mp->_mp_size = 0; - else - mpz_set_ui(mp, l); - } - void assign_si(signed long l) - { - if (__GMPXX_CONSTANT_TRUE(l >= 0)) - assign_ui(l); - else if (__GMPXX_CONSTANT_TRUE(l <= 0)) - { - assign_ui(-static_cast(l)); - mpz_neg(mp, mp); - } - else - mpz_set_si(mp, l); - } - void assign_d (double d) - { - mpz_set_d (mp, d); - } - - void init_ui(unsigned long l) - { - if (__GMPXX_CONSTANT_TRUE(l == 0)) - mpz_init(mp); - else - mpz_init_set_ui(mp, l); - } - void init_si(signed long l) - { - if (__GMPXX_CONSTANT_TRUE(l >= 0)) - init_ui(l); - else if (__GMPXX_CONSTANT_TRUE(l <= 0)) - { - init_ui(-static_cast(l)); - mpz_neg(mp, mp); - } - else - mpz_init_set_si(mp, l); - } - void init_d (double d) - { - mpz_init_set_d (mp, d); - } - -public: - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } - - // constructors and destructor - __gmp_expr() __GMPXX_NOEXCEPT { mpz_init(mp); } - - __gmp_expr(const __gmp_expr &z) { mpz_init_set(mp, z.mp); } -#if __GMPXX_USE_CXX11 - __gmp_expr(__gmp_expr &&z) noexcept - { *mp = *z.mp; mpz_init(z.mp); } -#endif - template - __gmp_expr(const __gmp_expr &expr) - { mpz_init(mp); __gmp_set_expr(mp, expr); } - template - explicit __gmp_expr(const __gmp_expr &expr) - { mpz_init(mp); __gmp_set_expr(mp, expr); } - - __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS - - explicit __gmp_expr(const char *s, int base = 0) - { - if (mpz_init_set_str (mp, s, base) != 0) - { - mpz_clear (mp); - throw std::invalid_argument ("mpz_set_str"); - } - } - explicit __gmp_expr(const std::string &s, int base = 0) - { - if (mpz_init_set_str(mp, s.c_str(), base) != 0) - { - mpz_clear (mp); - throw std::invalid_argument ("mpz_set_str"); - } - } - - explicit __gmp_expr(mpz_srcptr z) { mpz_init_set(mp, z); } - - ~__gmp_expr() { mpz_clear(mp); } - - void swap(__gmp_expr& z) __GMPXX_NOEXCEPT { std::swap(*mp, *z.mp); } - - // assignment operators - __gmp_expr & operator=(const __gmp_expr &z) - { mpz_set(mp, z.mp); return *this; } -#if __GMPXX_USE_CXX11 - __gmp_expr & operator=(__gmp_expr &&z) noexcept - { swap(z); return *this; } -#endif - template - __gmp_expr & operator=(const __gmp_expr &expr) - { __gmp_set_expr(mp, expr); return *this; } - - __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS - - __gmp_expr & operator=(const char *s) - { - if (mpz_set_str (mp, s, 0) != 0) - throw std::invalid_argument ("mpz_set_str"); - return *this; - } - __gmp_expr & operator=(const std::string &s) - { - if (mpz_set_str(mp, s.c_str(), 0) != 0) - throw std::invalid_argument ("mpz_set_str"); - return *this; - } - - // string input/output functions - int set_str(const char *s, int base) - { return mpz_set_str(mp, s, base); } - int set_str(const std::string &s, int base) - { return mpz_set_str(mp, s.c_str(), base); } - std::string get_str(int base = 10) const - { - __gmp_alloc_cstring temp(mpz_get_str(0, base, mp)); - return std::string(temp.str); - } - - // conversion functions - mpz_srcptr __get_mp() const { return mp; } - mpz_ptr __get_mp() { return mp; } - mpz_srcptr get_mpz_t() const { return mp; } - mpz_ptr get_mpz_t() { return mp; } - - signed long int get_si() const { return mpz_get_si(mp); } - unsigned long int get_ui() const { return mpz_get_ui(mp); } - double get_d() const { return mpz_get_d(mp); } - - // bool fits_schar_p() const { return mpz_fits_schar_p(mp); } - // bool fits_uchar_p() const { return mpz_fits_uchar_p(mp); } - bool fits_sint_p() const { return mpz_fits_sint_p(mp); } - bool fits_uint_p() const { return mpz_fits_uint_p(mp); } - bool fits_sshort_p() const { return mpz_fits_sshort_p(mp); } - bool fits_ushort_p() const { return mpz_fits_ushort_p(mp); } - bool fits_slong_p() const { return mpz_fits_slong_p(mp); } - bool fits_ulong_p() const { return mpz_fits_ulong_p(mp); } - // bool fits_float_p() const { return mpz_fits_float_p(mp); } - // bool fits_double_p() const { return mpz_fits_double_p(mp); } - // bool fits_ldouble_p() const { return mpz_fits_ldouble_p(mp); } - -#if __GMPXX_USE_CXX11 - explicit operator bool() const { return mp->_mp_size != 0; } -#endif - - // member operators - __GMP_DECLARE_COMPOUND_OPERATOR(operator+=) - __GMP_DECLARE_COMPOUND_OPERATOR(operator-=) - __GMP_DECLARE_COMPOUND_OPERATOR(operator*=) - __GMP_DECLARE_COMPOUND_OPERATOR(operator/=) - __GMP_DECLARE_COMPOUND_OPERATOR(operator%=) - - __GMP_DECLARE_COMPOUND_OPERATOR(operator&=) - __GMP_DECLARE_COMPOUND_OPERATOR(operator|=) - __GMP_DECLARE_COMPOUND_OPERATOR(operator^=) - - __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=) - __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=) - - __GMP_DECLARE_INCREMENT_OPERATOR(operator++) - __GMP_DECLARE_INCREMENT_OPERATOR(operator--) - - __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, factorial, __gmp_fac_function) - __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, primorial, __gmp_primorial_function) - __GMP_DECLARE_UNARY_STATIC_MEMFUN(mpz_t, fibonacci, __gmp_fib_function) -}; - -typedef __gmp_expr mpz_class; - - -/**************** mpq_class -- wrapper for mpq_t ****************/ - -template <> -class __gmp_expr -{ -private: - typedef mpq_t value_type; - value_type mp; - - // Helper functions used for all arithmetic types - void assign_ui(unsigned long l) { mpq_set_ui(mp, l, 1); } - void assign_si(signed long l) - { - if (__GMPXX_CONSTANT_TRUE(l >= 0)) - assign_ui(l); - else - mpq_set_si(mp, l, 1); - } - void assign_d (double d) { mpq_set_d (mp, d); } - - void init_ui(unsigned long l) { mpq_init(mp); get_num() = l; } - void init_si(signed long l) { mpq_init(mp); get_num() = l; } - void init_d (double d) { mpq_init(mp); assign_d (d); } - -public: - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } - void canonicalize() { mpq_canonicalize(mp); } - - // constructors and destructor - __gmp_expr() { mpq_init(mp); } - - __gmp_expr(const __gmp_expr &q) - { - mpz_init_set(mpq_numref(mp), mpq_numref(q.mp)); - mpz_init_set(mpq_denref(mp), mpq_denref(q.mp)); - } -#if __GMPXX_USE_CXX11 - __gmp_expr(__gmp_expr &&q) - { *mp = *q.mp; mpq_init(q.mp); } -#endif - template - __gmp_expr(const __gmp_expr &expr) - { mpq_init(mp); __gmp_set_expr(mp, expr); } - template - __gmp_expr(const __gmp_expr &expr) - { mpq_init(mp); __gmp_set_expr(mp, expr); } - template - explicit __gmp_expr(const __gmp_expr &expr) - { mpq_init(mp); __gmp_set_expr(mp, expr); } - - __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS - - explicit __gmp_expr(const char *s, int base = 0) - { - mpq_init (mp); - // If s is the literal 0, we meant to call another constructor. - // If s just happens to evaluate to 0, we would crash, so whatever. - if (s == 0) - { - // Don't turn mpq_class(0,0) into 0 - mpz_set_si(mpq_denref(mp), base); - } - else if (mpq_set_str(mp, s, base) != 0) - { - mpq_clear (mp); - throw std::invalid_argument ("mpq_set_str"); - } - } - explicit __gmp_expr(const std::string &s, int base = 0) - { - mpq_init(mp); - if (mpq_set_str (mp, s.c_str(), base) != 0) - { - mpq_clear (mp); - throw std::invalid_argument ("mpq_set_str"); - } - } - explicit __gmp_expr(mpq_srcptr q) - { - mpz_init_set(mpq_numref(mp), mpq_numref(q)); - mpz_init_set(mpq_denref(mp), mpq_denref(q)); - } - - __gmp_expr(const mpz_class &num, const mpz_class &den) - { - mpz_init_set(mpq_numref(mp), num.get_mpz_t()); - mpz_init_set(mpq_denref(mp), den.get_mpz_t()); - } - - ~__gmp_expr() { mpq_clear(mp); } - - void swap(__gmp_expr& q) __GMPXX_NOEXCEPT { std::swap(*mp, *q.mp); } - - // assignment operators - __gmp_expr & operator=(const __gmp_expr &q) - { mpq_set(mp, q.mp); return *this; } -#if __GMPXX_USE_CXX11 - __gmp_expr & operator=(__gmp_expr &&q) noexcept - { swap(q); return *this; } - __gmp_expr & operator=(mpz_class &&z) noexcept - { get_num() = std::move(z); get_den() = 1u; return *this; } -#endif - template - __gmp_expr & operator=(const __gmp_expr &expr) - { __gmp_set_expr(mp, expr); return *this; } - - __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS - - __gmp_expr & operator=(const char *s) - { - if (mpq_set_str (mp, s, 0) != 0) - throw std::invalid_argument ("mpq_set_str"); - return *this; - } - __gmp_expr & operator=(const std::string &s) - { - if (mpq_set_str(mp, s.c_str(), 0) != 0) - throw std::invalid_argument ("mpq_set_str"); - return *this; - } - - // string input/output functions - int set_str(const char *s, int base) - { return mpq_set_str(mp, s, base); } - int set_str(const std::string &s, int base) - { return mpq_set_str(mp, s.c_str(), base); } - std::string get_str(int base = 10) const - { - __gmp_alloc_cstring temp(mpq_get_str(0, base, mp)); - return std::string(temp.str); - } - - // conversion functions - - // casting a reference to an mpz_t to mpz_class & is a dirty hack, - // but works because the internal representation of mpz_class is - // exactly an mpz_t - const mpz_class & get_num() const - { return reinterpret_cast(*mpq_numref(mp)); } - mpz_class & get_num() - { return reinterpret_cast(*mpq_numref(mp)); } - const mpz_class & get_den() const - { return reinterpret_cast(*mpq_denref(mp)); } - mpz_class & get_den() - { return reinterpret_cast(*mpq_denref(mp)); } - - mpq_srcptr __get_mp() const { return mp; } - mpq_ptr __get_mp() { return mp; } - mpq_srcptr get_mpq_t() const { return mp; } - mpq_ptr get_mpq_t() { return mp; } - - mpz_srcptr get_num_mpz_t() const { return mpq_numref(mp); } - mpz_ptr get_num_mpz_t() { return mpq_numref(mp); } - mpz_srcptr get_den_mpz_t() const { return mpq_denref(mp); } - mpz_ptr get_den_mpz_t() { return mpq_denref(mp); } - - double get_d() const { return mpq_get_d(mp); } - -#if __GMPXX_USE_CXX11 - explicit operator bool() const { return mpq_numref(mp)->_mp_size != 0; } -#endif - - // compound assignments - __GMP_DECLARE_COMPOUND_OPERATOR(operator+=) - __GMP_DECLARE_COMPOUND_OPERATOR(operator-=) - __GMP_DECLARE_COMPOUND_OPERATOR(operator*=) - __GMP_DECLARE_COMPOUND_OPERATOR(operator/=) - - __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=) - __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=) - - __GMP_DECLARE_INCREMENT_OPERATOR(operator++) - __GMP_DECLARE_INCREMENT_OPERATOR(operator--) -}; - -typedef __gmp_expr mpq_class; - - -/**************** mpf_class -- wrapper for mpf_t ****************/ - -template <> -class __gmp_expr -{ -private: - typedef mpf_t value_type; - value_type mp; - - // Helper functions used for all arithmetic types - void assign_ui(unsigned long l) { mpf_set_ui(mp, l); } - void assign_si(signed long l) - { - if (__GMPXX_CONSTANT_TRUE(l >= 0)) - assign_ui(l); - else - mpf_set_si(mp, l); - } - void assign_d (double d) { mpf_set_d (mp, d); } - - void init_ui(unsigned long l) - { - if (__GMPXX_CONSTANT_TRUE(l == 0)) - mpf_init(mp); - else - mpf_init_set_ui(mp, l); - } - void init_si(signed long l) - { - if (__GMPXX_CONSTANT_TRUE(l >= 0)) - init_ui(l); - else - mpf_init_set_si(mp, l); - } - void init_d (double d) { mpf_init_set_d (mp, d); } - -public: - mp_bitcnt_t get_prec() const { return mpf_get_prec(mp); } - - void set_prec(mp_bitcnt_t prec) { mpf_set_prec(mp, prec); } - void set_prec_raw(mp_bitcnt_t prec) { mpf_set_prec_raw(mp, prec); } - - // constructors and destructor - __gmp_expr() { mpf_init(mp); } - - __gmp_expr(const __gmp_expr &f) - { mpf_init2(mp, f.get_prec()); mpf_set(mp, f.mp); } -#if __GMPXX_USE_CXX11 - __gmp_expr(__gmp_expr &&f) - { *mp = *f.mp; mpf_init2(f.mp, get_prec()); } -#endif - __gmp_expr(const __gmp_expr &f, mp_bitcnt_t prec) - { mpf_init2(mp, prec); mpf_set(mp, f.mp); } - template - __gmp_expr(const __gmp_expr &expr) - { mpf_init2(mp, expr.get_prec()); __gmp_set_expr(mp, expr); } - template - __gmp_expr(const __gmp_expr &expr, mp_bitcnt_t prec) - { mpf_init2(mp, prec); __gmp_set_expr(mp, expr); } - - __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS - - __gmp_expr(signed char c, mp_bitcnt_t prec) - { mpf_init2(mp, prec); mpf_set_si(mp, c); } - __gmp_expr(unsigned char c, mp_bitcnt_t prec) - { mpf_init2(mp, prec); mpf_set_ui(mp, c); } - - __gmp_expr(signed int i, mp_bitcnt_t prec) - { mpf_init2(mp, prec); mpf_set_si(mp, i); } - __gmp_expr(unsigned int i, mp_bitcnt_t prec) - { mpf_init2(mp, prec); mpf_set_ui(mp, i); } - - __gmp_expr(signed short int s, mp_bitcnt_t prec) - { mpf_init2(mp, prec); mpf_set_si(mp, s); } - __gmp_expr(unsigned short int s, mp_bitcnt_t prec) - { mpf_init2(mp, prec); mpf_set_ui(mp, s); } - - __gmp_expr(signed long int l, mp_bitcnt_t prec) - { mpf_init2(mp, prec); mpf_set_si(mp, l); } - __gmp_expr(unsigned long int l, mp_bitcnt_t prec) - { mpf_init2(mp, prec); mpf_set_ui(mp, l); } - - __gmp_expr(float f, mp_bitcnt_t prec) - { mpf_init2(mp, prec); mpf_set_d(mp, f); } - __gmp_expr(double d, mp_bitcnt_t prec) - { mpf_init2(mp, prec); mpf_set_d(mp, d); } - // __gmp_expr(long double ld) { mpf_init_set_d(mp, ld); } - // __gmp_expr(long double ld, mp_bitcnt_t prec) - // { mpf_init2(mp, prec); mpf_set_d(mp, ld); } - - explicit __gmp_expr(const char *s) - { - if (mpf_init_set_str (mp, s, 0) != 0) - { - mpf_clear (mp); - throw std::invalid_argument ("mpf_set_str"); - } - } - __gmp_expr(const char *s, mp_bitcnt_t prec, int base = 0) - { - mpf_init2(mp, prec); - if (mpf_set_str(mp, s, base) != 0) - { - mpf_clear (mp); - throw std::invalid_argument ("mpf_set_str"); - } - } - explicit __gmp_expr(const std::string &s) - { - if (mpf_init_set_str(mp, s.c_str(), 0) != 0) - { - mpf_clear (mp); - throw std::invalid_argument ("mpf_set_str"); - } - } - __gmp_expr(const std::string &s, mp_bitcnt_t prec, int base = 0) - { - mpf_init2(mp, prec); - if (mpf_set_str(mp, s.c_str(), base) != 0) - { - mpf_clear (mp); - throw std::invalid_argument ("mpf_set_str"); - } - } - - explicit __gmp_expr(mpf_srcptr f) - { mpf_init2(mp, mpf_get_prec(f)); mpf_set(mp, f); } - __gmp_expr(mpf_srcptr f, mp_bitcnt_t prec) - { mpf_init2(mp, prec); mpf_set(mp, f); } - - ~__gmp_expr() { mpf_clear(mp); } - - void swap(__gmp_expr& f) __GMPXX_NOEXCEPT { std::swap(*mp, *f.mp); } - - // assignment operators - __gmp_expr & operator=(const __gmp_expr &f) - { mpf_set(mp, f.mp); return *this; } -#if __GMPXX_USE_CXX11 - __gmp_expr & operator=(__gmp_expr &&f) noexcept - { swap(f); return *this; } -#endif - template - __gmp_expr & operator=(const __gmp_expr &expr) - { __gmp_set_expr(mp, expr); return *this; } - - __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS - - __gmp_expr & operator=(const char *s) - { - if (mpf_set_str (mp, s, 0) != 0) - throw std::invalid_argument ("mpf_set_str"); - return *this; - } - __gmp_expr & operator=(const std::string &s) - { - if (mpf_set_str(mp, s.c_str(), 0) != 0) - throw std::invalid_argument ("mpf_set_str"); - return *this; - } - - // string input/output functions - int set_str(const char *s, int base) - { return mpf_set_str(mp, s, base); } - int set_str(const std::string &s, int base) - { return mpf_set_str(mp, s.c_str(), base); } - std::string get_str(mp_exp_t &expo, int base = 10, size_t size = 0) const - { - __gmp_alloc_cstring temp(mpf_get_str(0, &expo, base, size, mp)); - return std::string(temp.str); - } - - // conversion functions - mpf_srcptr __get_mp() const { return mp; } - mpf_ptr __get_mp() { return mp; } - mpf_srcptr get_mpf_t() const { return mp; } - mpf_ptr get_mpf_t() { return mp; } - - signed long int get_si() const { return mpf_get_si(mp); } - unsigned long int get_ui() const { return mpf_get_ui(mp); } - double get_d() const { return mpf_get_d(mp); } - - // bool fits_schar_p() const { return mpf_fits_schar_p(mp); } - // bool fits_uchar_p() const { return mpf_fits_uchar_p(mp); } - bool fits_sint_p() const { return mpf_fits_sint_p(mp); } - bool fits_uint_p() const { return mpf_fits_uint_p(mp); } - bool fits_sshort_p() const { return mpf_fits_sshort_p(mp); } - bool fits_ushort_p() const { return mpf_fits_ushort_p(mp); } - bool fits_slong_p() const { return mpf_fits_slong_p(mp); } - bool fits_ulong_p() const { return mpf_fits_ulong_p(mp); } - // bool fits_float_p() const { return mpf_fits_float_p(mp); } - // bool fits_double_p() const { return mpf_fits_double_p(mp); } - // bool fits_ldouble_p() const { return mpf_fits_ldouble_p(mp); } - -#if __GMPXX_USE_CXX11 - explicit operator bool() const { return mpf_sgn(mp) != 0; } -#endif - - // compound assignments - __GMP_DECLARE_COMPOUND_OPERATOR(operator+=) - __GMP_DECLARE_COMPOUND_OPERATOR(operator-=) - __GMP_DECLARE_COMPOUND_OPERATOR(operator*=) - __GMP_DECLARE_COMPOUND_OPERATOR(operator/=) - - __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=) - __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=) - - __GMP_DECLARE_INCREMENT_OPERATOR(operator++) - __GMP_DECLARE_INCREMENT_OPERATOR(operator--) -}; - -typedef __gmp_expr mpf_class; - - - -/**************** User-defined literals ****************/ - -#if __GMPXX_USE_CXX11 -inline mpz_class operator"" _mpz(const char* s) -{ - return mpz_class(s); -} - -inline mpq_class operator"" _mpq(const char* s) -{ - mpq_class q; - q.get_num() = s; - return q; -} - -inline mpf_class operator"" _mpf(const char* s) -{ - return mpf_class(s); -} -#endif - -/**************** I/O operators ****************/ - -// these should (and will) be provided separately - -template -inline std::ostream & operator<< -(std::ostream &o, const __gmp_expr &expr) -{ - __gmp_expr const& temp(expr); - return o << temp.__get_mp(); -} - -template -inline std::istream & operator>>(std::istream &i, __gmp_expr &expr) -{ - return i >> expr.__get_mp(); -} - -/* -// you might want to uncomment this -inline std::istream & operator>>(std::istream &i, mpq_class &q) -{ - i >> q.get_mpq_t(); - q.canonicalize(); - return i; -} -*/ - - -/**************** Functions for type conversion ****************/ - -inline void __gmp_set_expr(mpz_ptr z, const mpz_class &w) -{ - mpz_set(z, w.get_mpz_t()); -} - -template -inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr &expr) -{ - expr.eval(z); -} - -template -inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr &expr) -{ - mpq_class const& temp(expr); - mpz_set_q(z, temp.get_mpq_t()); -} - -template -inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr &expr) -{ - mpf_class const& temp(expr); - mpz_set_f(z, temp.get_mpf_t()); -} - -inline void __gmp_set_expr(mpq_ptr q, const mpz_class &z) -{ - mpq_set_z(q, z.get_mpz_t()); -} - -template -inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr &expr) -{ - __gmp_set_expr(mpq_numref(q), expr); - mpz_set_ui(mpq_denref(q), 1); -} - -inline void __gmp_set_expr(mpq_ptr q, const mpq_class &r) -{ - mpq_set(q, r.get_mpq_t()); -} - -template -inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr &expr) -{ - expr.eval(q); -} - -template -inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr &expr) -{ - mpf_class const& temp(expr); - mpq_set_f(q, temp.get_mpf_t()); -} - -template -inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr &expr) -{ - mpz_class const& temp(expr); - mpf_set_z(f, temp.get_mpz_t()); -} - -template -inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr &expr) -{ - mpq_class const& temp(expr); - mpf_set_q(f, temp.get_mpq_t()); -} - -inline void __gmp_set_expr(mpf_ptr f, const mpf_class &g) -{ - mpf_set(f, g.get_mpf_t()); -} - -template -inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr &expr) -{ - expr.eval(f); -} - - -/* Temporary objects */ - -template -class __gmp_temp -{ - __gmp_expr val; - public: - template - __gmp_temp(U const& u, V) : val (u) {} - typename __gmp_resolve_expr::srcptr_type - __get_mp() const { return val.__get_mp(); } -}; - -template <> -class __gmp_temp -{ - mpf_class val; - public: - template - __gmp_temp(U const& u, mpf_ptr res) : val (u, mpf_get_prec(res)) {} - mpf_srcptr __get_mp() const { return val.__get_mp(); } -}; - -/**************** Specializations of __gmp_expr ****************/ -/* The eval() method of __gmp_expr evaluates the corresponding - expression and assigns the result to its argument, which is either an - mpz_t, mpq_t, or mpf_t as specified by the T argument. - Compound expressions are evaluated recursively (temporaries are created - to hold intermediate values), while for simple expressions the eval() - method of the appropriate function object (available as the Op argument - of either __gmp_unary_expr or __gmp_binary_expr) is - called. */ - - -/**************** Unary expressions ****************/ -/* cases: - - simple: argument is mp*_class, that is, __gmp_expr - - compound: argument is __gmp_expr (with U not equal to T) */ - - -// simple expressions - -template -class __gmp_expr, Op> > -{ -private: - typedef __gmp_expr val_type; - - __gmp_unary_expr expr; -public: - explicit __gmp_expr(const val_type &val) : expr(val) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { Op::eval(p, expr.val.__get_mp()); } - const val_type & get_val() const { return expr.val; } - mp_bitcnt_t get_prec() const { return expr.val.get_prec(); } -}; - - -// simple expressions, U is a built-in numerical type - -template -class __gmp_expr > -{ -private: - typedef U val_type; - - __gmp_unary_expr expr; -public: - explicit __gmp_expr(const val_type &val) : expr(val) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { Op::eval(p, expr.val); } - const val_type & get_val() const { return expr.val; } - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } -}; - - -// compound expressions - -template -class __gmp_expr, Op> > -{ -private: - typedef __gmp_expr val_type; - - __gmp_unary_expr expr; -public: - explicit __gmp_expr(const val_type &val) : expr(val) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { expr.val.eval(p); Op::eval(p, p); } - const val_type & get_val() const { return expr.val; } - mp_bitcnt_t get_prec() const { return expr.val.get_prec(); } -}; - - -/**************** Binary expressions ****************/ -/* simple: - - arguments are both mp*_class - - one argument is mp*_class, one is a built-in type - compound: - - one is mp*_class, one is __gmp_expr - - one is __gmp_expr, one is built-in - - both arguments are __gmp_expr<...> */ - - -// simple expressions - -template -class __gmp_expr -, __gmp_expr, Op> > -{ -private: - typedef __gmp_expr val1_type; - typedef __gmp_expr val2_type; - - __gmp_binary_expr expr; -public: - __gmp_expr(const val1_type &val1, const val2_type &val2) - : expr(val1, val2) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { Op::eval(p, expr.val1.__get_mp(), expr.val2.__get_mp()); } - const val1_type & get_val1() const { return expr.val1; } - const val2_type & get_val2() const { return expr.val2; } - mp_bitcnt_t get_prec() const - { - mp_bitcnt_t prec1 = expr.val1.get_prec(), - prec2 = expr.val2.get_prec(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - - -// simple expressions, U is a built-in numerical type - -template -class __gmp_expr, U, Op> > -{ -private: - typedef __gmp_expr val1_type; - typedef U val2_type; - - __gmp_binary_expr expr; -public: - __gmp_expr(const val1_type &val1, const val2_type &val2) - : expr(val1, val2) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { Op::eval(p, expr.val1.__get_mp(), expr.val2); } - const val1_type & get_val1() const { return expr.val1; } - const val2_type & get_val2() const { return expr.val2; } - mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); } -}; - -template -class __gmp_expr, Op> > -{ -private: - typedef U val1_type; - typedef __gmp_expr val2_type; - - __gmp_binary_expr expr; -public: - __gmp_expr(const val1_type &val1, const val2_type &val2) - : expr(val1, val2) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { Op::eval(p, expr.val1, expr.val2.__get_mp()); } - const val1_type & get_val1() const { return expr.val1; } - const val2_type & get_val2() const { return expr.val2; } - mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); } -}; - - -// compound expressions, one argument is a subexpression - -template -class __gmp_expr -, __gmp_expr, Op> > -{ -private: - typedef __gmp_expr val1_type; - typedef __gmp_expr val2_type; - - __gmp_binary_expr expr; -public: - __gmp_expr(const val1_type &val1, const val2_type &val2) - : expr(val1, val2) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { - if(p != expr.val1.__get_mp()) - { - __gmp_set_expr(p, expr.val2); - Op::eval(p, expr.val1.__get_mp(), p); - } - else - { - __gmp_temp temp(expr.val2, p); - Op::eval(p, expr.val1.__get_mp(), temp.__get_mp()); - } - } - const val1_type & get_val1() const { return expr.val1; } - const val2_type & get_val2() const { return expr.val2; } - mp_bitcnt_t get_prec() const - { - mp_bitcnt_t prec1 = expr.val1.get_prec(), - prec2 = expr.val2.get_prec(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -template -class __gmp_expr -, __gmp_expr, Op> > -{ -private: - typedef __gmp_expr val1_type; - typedef __gmp_expr val2_type; - - __gmp_binary_expr expr; -public: - __gmp_expr(const val1_type &val1, const val2_type &val2) - : expr(val1, val2) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { - if(p != expr.val2.__get_mp()) - { - __gmp_set_expr(p, expr.val1); - Op::eval(p, p, expr.val2.__get_mp()); - } - else - { - __gmp_temp temp(expr.val1, p); - Op::eval(p, temp.__get_mp(), expr.val2.__get_mp()); - } - } - const val1_type & get_val1() const { return expr.val1; } - const val2_type & get_val2() const { return expr.val2; } - mp_bitcnt_t get_prec() const - { - mp_bitcnt_t prec1 = expr.val1.get_prec(), - prec2 = expr.val2.get_prec(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -template -class __gmp_expr -, __gmp_expr, Op> > -{ -private: - typedef __gmp_expr val1_type; - typedef __gmp_expr val2_type; - - __gmp_binary_expr expr; -public: - __gmp_expr(const val1_type &val1, const val2_type &val2) - : expr(val1, val2) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { - if(p != expr.val1.__get_mp()) - { - __gmp_set_expr(p, expr.val2); - Op::eval(p, expr.val1.__get_mp(), p); - } - else - { - __gmp_temp temp(expr.val2, p); - Op::eval(p, expr.val1.__get_mp(), temp.__get_mp()); - } - } - const val1_type & get_val1() const { return expr.val1; } - const val2_type & get_val2() const { return expr.val2; } - mp_bitcnt_t get_prec() const - { - mp_bitcnt_t prec1 = expr.val1.get_prec(), - prec2 = expr.val2.get_prec(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -template -class __gmp_expr -, __gmp_expr, Op> > -{ -private: - typedef __gmp_expr val1_type; - typedef __gmp_expr val2_type; - - __gmp_binary_expr expr; -public: - __gmp_expr(const val1_type &val1, const val2_type &val2) - : expr(val1, val2) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { - if(p != expr.val2.__get_mp()) - { - __gmp_set_expr(p, expr.val1); - Op::eval(p, p, expr.val2.__get_mp()); - } - else - { - __gmp_temp temp(expr.val1, p); - Op::eval(p, temp.__get_mp(), expr.val2.__get_mp()); - } - } - const val1_type & get_val1() const { return expr.val1; } - const val2_type & get_val2() const { return expr.val2; } - mp_bitcnt_t get_prec() const - { - mp_bitcnt_t prec1 = expr.val1.get_prec(), - prec2 = expr.val2.get_prec(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - - -// one argument is a subexpression, one is a built-in - -template -class __gmp_expr, V, Op> > -{ -private: - typedef __gmp_expr val1_type; - typedef V val2_type; - - __gmp_binary_expr expr; -public: - __gmp_expr(const val1_type &val1, const val2_type &val2) - : expr(val1, val2) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { - expr.val1.eval(p); - Op::eval(p, p, expr.val2); - } - const val1_type & get_val1() const { return expr.val1; } - const val2_type & get_val2() const { return expr.val2; } - mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); } -}; - -template -class __gmp_expr, Op> > -{ -private: - typedef U val1_type; - typedef __gmp_expr val2_type; - - __gmp_binary_expr expr; -public: - __gmp_expr(const val1_type &val1, const val2_type &val2) - : expr(val1, val2) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { - expr.val2.eval(p); - Op::eval(p, expr.val1, p); - } - const val1_type & get_val1() const { return expr.val1; } - const val2_type & get_val2() const { return expr.val2; } - mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); } -}; - - -// both arguments are subexpressions - -template -class __gmp_expr -, __gmp_expr, Op> > -{ -private: - typedef __gmp_expr val1_type; - typedef __gmp_expr val2_type; - - __gmp_binary_expr expr; -public: - __gmp_expr(const val1_type &val1, const val2_type &val2) - : expr(val1, val2) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { - __gmp_temp temp2(expr.val2, p); - expr.val1.eval(p); - Op::eval(p, p, temp2.__get_mp()); - } - const val1_type & get_val1() const { return expr.val1; } - const val2_type & get_val2() const { return expr.val2; } - mp_bitcnt_t get_prec() const - { - mp_bitcnt_t prec1 = expr.val1.get_prec(), - prec2 = expr.val2.get_prec(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -template -class __gmp_expr -, __gmp_expr, Op> > -{ -private: - typedef __gmp_expr val1_type; - typedef __gmp_expr val2_type; - - __gmp_binary_expr expr; -public: - __gmp_expr(const val1_type &val1, const val2_type &val2) - : expr(val1, val2) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { - __gmp_temp temp1(expr.val1, p); - expr.val2.eval(p); - Op::eval(p, temp1.__get_mp(), p); - } - const val1_type & get_val1() const { return expr.val1; } - const val2_type & get_val2() const { return expr.val2; } - mp_bitcnt_t get_prec() const - { - mp_bitcnt_t prec1 = expr.val1.get_prec(), - prec2 = expr.val2.get_prec(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - -template -class __gmp_expr -, __gmp_expr, Op> > -{ -private: - typedef __gmp_expr val1_type; - typedef __gmp_expr val2_type; - - __gmp_binary_expr expr; -public: - __gmp_expr(const val1_type &val1, const val2_type &val2) - : expr(val1, val2) { } - void eval(typename __gmp_resolve_expr::ptr_type p) const - { - __gmp_temp temp2(expr.val2, p); - expr.val1.eval(p); - Op::eval(p, p, temp2.__get_mp()); - } - const val1_type & get_val1() const { return expr.val1; } - const val2_type & get_val2() const { return expr.val2; } - mp_bitcnt_t get_prec() const - { - mp_bitcnt_t prec1 = expr.val1.get_prec(), - prec2 = expr.val2.get_prec(); - return (prec1 > prec2) ? prec1 : prec2; - } -}; - - -/**************** Special cases ****************/ - -/* Some operations (i.e., add and subtract) with mixed mpz/mpq arguments - can be done directly without first converting the mpz to mpq. - Appropriate specializations of __gmp_expr are required. */ - - -#define __GMPZQ_DEFINE_EXPR(eval_fun) \ - \ -template <> \ -class __gmp_expr > \ -{ \ -private: \ - typedef mpz_class val1_type; \ - typedef mpq_class val2_type; \ - \ - __gmp_binary_expr expr; \ -public: \ - __gmp_expr(const val1_type &val1, const val2_type &val2) \ - : expr(val1, val2) { } \ - void eval(mpq_ptr q) const \ - { eval_fun::eval(q, expr.val1.get_mpz_t(), expr.val2.get_mpq_t()); } \ - const val1_type & get_val1() const { return expr.val1; } \ - const val2_type & get_val2() const { return expr.val2; } \ - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ -}; \ - \ -template <> \ -class __gmp_expr > \ -{ \ -private: \ - typedef mpq_class val1_type; \ - typedef mpz_class val2_type; \ - \ - __gmp_binary_expr expr; \ -public: \ - __gmp_expr(const val1_type &val1, const val2_type &val2) \ - : expr(val1, val2) { } \ - void eval(mpq_ptr q) const \ - { eval_fun::eval(q, expr.val1.get_mpq_t(), expr.val2.get_mpz_t()); } \ - const val1_type & get_val1() const { return expr.val1; } \ - const val2_type & get_val2() const { return expr.val2; } \ - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ -}; \ - \ -template \ -class __gmp_expr \ -, eval_fun> > \ -{ \ -private: \ - typedef mpz_class val1_type; \ - typedef __gmp_expr val2_type; \ - \ - __gmp_binary_expr expr; \ -public: \ - __gmp_expr(const val1_type &val1, const val2_type &val2) \ - : expr(val1, val2) { } \ - void eval(mpq_ptr q) const \ - { \ - mpq_class temp(expr.val2); \ - eval_fun::eval(q, expr.val1.get_mpz_t(), temp.get_mpq_t()); \ - } \ - const val1_type & get_val1() const { return expr.val1; } \ - const val2_type & get_val2() const { return expr.val2; } \ - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ -}; \ - \ -template \ -class __gmp_expr \ -, eval_fun> > \ -{ \ -private: \ - typedef mpq_class val1_type; \ - typedef __gmp_expr val2_type; \ - \ - __gmp_binary_expr expr; \ -public: \ - __gmp_expr(const val1_type &val1, const val2_type &val2) \ - : expr(val1, val2) { } \ - void eval(mpq_ptr q) const \ - { \ - mpz_class temp(expr.val2); \ - eval_fun::eval(q, expr.val1.get_mpq_t(), temp.get_mpz_t()); \ - } \ - const val1_type & get_val1() const { return expr.val1; } \ - const val2_type & get_val2() const { return expr.val2; } \ - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ -}; \ - \ -template \ -class __gmp_expr \ -, mpq_class, eval_fun> > \ -{ \ -private: \ - typedef __gmp_expr val1_type; \ - typedef mpq_class val2_type; \ - \ - __gmp_binary_expr expr; \ -public: \ - __gmp_expr(const val1_type &val1, const val2_type &val2) \ - : expr(val1, val2) { } \ - void eval(mpq_ptr q) const \ - { \ - mpz_class temp(expr.val1); \ - eval_fun::eval(q, temp.get_mpz_t(), expr.val2.get_mpq_t()); \ - } \ - const val1_type & get_val1() const { return expr.val1; } \ - const val2_type & get_val2() const { return expr.val2; } \ - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ -}; \ - \ -template \ -class __gmp_expr \ -, mpz_class, eval_fun> > \ -{ \ -private: \ - typedef __gmp_expr val1_type; \ - typedef mpz_class val2_type; \ - \ - __gmp_binary_expr expr; \ -public: \ - __gmp_expr(const val1_type &val1, const val2_type &val2) \ - : expr(val1, val2) { } \ - void eval(mpq_ptr q) const \ - { \ - mpq_class temp(expr.val1); \ - eval_fun::eval(q, temp.get_mpq_t(), expr.val2.get_mpz_t()); \ - } \ - const val1_type & get_val1() const { return expr.val1; } \ - const val2_type & get_val2() const { return expr.val2; } \ - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ -}; \ - \ -template \ -class __gmp_expr, __gmp_expr, eval_fun> > \ -{ \ -private: \ - typedef __gmp_expr val1_type; \ - typedef __gmp_expr val2_type; \ - \ - __gmp_binary_expr expr; \ -public: \ - __gmp_expr(const val1_type &val1, const val2_type &val2) \ - : expr(val1, val2) { } \ - void eval(mpq_ptr q) const \ - { \ - mpz_class temp1(expr.val1); \ - expr.val2.eval(q); \ - eval_fun::eval(q, temp1.get_mpz_t(), q); \ - } \ - const val1_type & get_val1() const { return expr.val1; } \ - const val2_type & get_val2() const { return expr.val2; } \ - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ -}; \ - \ -template \ -class __gmp_expr, __gmp_expr, eval_fun> > \ -{ \ -private: \ - typedef __gmp_expr val1_type; \ - typedef __gmp_expr val2_type; \ - \ - __gmp_binary_expr expr; \ -public: \ - __gmp_expr(const val1_type &val1, const val2_type &val2) \ - : expr(val1, val2) { } \ - void eval(mpq_ptr q) const \ - { \ - mpz_class temp2(expr.val2); \ - expr.val1.eval(q); \ - eval_fun::eval(q, q, temp2.get_mpz_t()); \ - } \ - const val1_type & get_val1() const { return expr.val1; } \ - const val2_type & get_val2() const { return expr.val2; } \ - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ -}; - - -__GMPZQ_DEFINE_EXPR(__gmp_binary_plus) -__GMPZQ_DEFINE_EXPR(__gmp_binary_minus) - - - -/**************** Macros for defining functions ****************/ -/* Results of operators and functions are instances of __gmp_expr. - T determines the numerical type of the expression: it can be either - mpz_t, mpq_t, or mpf_t. When the arguments of a binary - expression have different numerical types, __gmp_resolve_expr is used - to determine the "larger" type. - U is either __gmp_unary_expr or __gmp_binary_expr, - where V and W are the arguments' types -- they can in turn be - expressions, thus allowing to build compound expressions to any - degree of complexity. - Op is a function object that must have an eval() method accepting - appropriate arguments. - Actual evaluation of a __gmp_expr object is done when it gets - assigned to an mp*_class ("lazy" evaluation): this is done by calling - its eval() method. */ - - -// non-member unary operators and functions - -#define __GMP_DEFINE_UNARY_FUNCTION(fun, eval_fun) \ - \ -template \ -inline __gmp_expr, eval_fun> > \ -fun(const __gmp_expr &expr) \ -{ \ - return __gmp_expr, eval_fun> >(expr); \ -} - -// variant that only works for one of { mpz, mpq, mpf } - -#define __GMP_DEFINE_UNARY_FUNCTION_1(T, fun, eval_fun) \ - \ -template \ -inline __gmp_expr, eval_fun> > \ -fun(const __gmp_expr &expr) \ -{ \ - return __gmp_expr, eval_fun> >(expr); \ -} - -#define __GMP_DEFINE_UNARY_TYPE_FUNCTION(type, fun, eval_fun) \ - \ -template \ -inline type fun(const __gmp_expr &expr) \ -{ \ - __gmp_expr const& temp(expr); \ - return eval_fun::eval(temp.__get_mp()); \ -} - - -// non-member binary operators and functions - -#define __GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ - \ -template \ -inline __gmp_expr::value_type, \ -__gmp_binary_expr<__gmp_expr, __gmp_expr, eval_fun> > \ -fun(const __gmp_expr &expr1, const __gmp_expr &expr2) \ -{ \ - return __gmp_expr::value_type, \ - __gmp_binary_expr<__gmp_expr, __gmp_expr, eval_fun> > \ - (expr1, expr2); \ -} - -#define __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, bigtype) \ - \ -template \ -inline __gmp_expr \ -, bigtype, eval_fun> > \ -fun(const __gmp_expr &expr, type t) \ -{ \ - return __gmp_expr \ - , bigtype, eval_fun> >(expr, t); \ -} \ - \ -template \ -inline __gmp_expr \ -, eval_fun> > \ -fun(type t, const __gmp_expr &expr) \ -{ \ - return __gmp_expr \ - , eval_fun> >(t, expr); \ -} - -#define __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \ -__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, signed long int) - -#define __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \ -__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, unsigned long int) - -#define __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \ -__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, double) - -#define __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \ -__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, long double) - -#define __GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ -__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed char) \ -__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned char) \ -__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed int) \ -__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned int) \ -__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed short int) \ -__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned short int) \ -__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed long int) \ -__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned long int) \ -__GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, float) \ -__GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, double) \ -/* __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, long double) */ - -#define __GMP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ -__GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ -__GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun) - -// variant that only works for one of { mpz, mpq, mpf } - -#define __GMPP_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun) \ - \ -template \ -inline __gmp_expr, __gmp_expr, eval_fun> > \ -fun(const __gmp_expr &expr1, const __gmp_expr &expr2) \ -{ \ - return __gmp_expr, __gmp_expr, eval_fun> > \ - (expr1, expr2); \ -} - -#define __GMPNN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type, bigtype) \ - \ -template \ -inline __gmp_expr \ -, bigtype, eval_fun> > \ -fun(const __gmp_expr &expr, type t) \ -{ \ - return __gmp_expr \ - , bigtype, eval_fun> >(expr, t); \ -} \ - \ -template \ -inline __gmp_expr \ -, eval_fun> > \ -fun(type t, const __gmp_expr &expr) \ -{ \ - return __gmp_expr \ - , eval_fun> >(t, expr); \ -} - -#define __GMPNS_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type) \ -__GMPNN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type, signed long int) - -#define __GMPNU_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type) \ -__GMPNN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type, unsigned long int) - -#define __GMPND_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type) \ -__GMPNN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type, double) - -#define __GMPNLD_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type) \ -__GMPNN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, type, long double) - -#define __GMPN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun) \ -__GMPNS_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, signed char) \ -__GMPNU_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, unsigned char) \ -__GMPNS_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, signed int) \ -__GMPNU_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, unsigned int) \ -__GMPNS_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, signed short int) \ -__GMPNU_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, unsigned short int) \ -__GMPNS_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, signed long int) \ -__GMPNU_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, unsigned long int) \ -__GMPND_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, float) \ -__GMPND_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, double) \ -/* __GMPNLD_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun, long double) */ - -#define __GMP_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun) \ -__GMPP_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun) \ -__GMPN_DEFINE_BINARY_FUNCTION_1(T, fun, eval_fun) - - -#define __GMP_DEFINE_BINARY_FUNCTION_UI(fun, eval_fun) \ - \ -template \ -inline __gmp_expr \ -, mp_bitcnt_t, eval_fun> > \ -fun(const __gmp_expr &expr, mp_bitcnt_t l) \ -{ \ - return __gmp_expr, mp_bitcnt_t, eval_fun> >(expr, l); \ -} - - -#define __GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ - \ -template \ -inline type fun(const __gmp_expr &expr1, \ - const __gmp_expr &expr2) \ -{ \ - __gmp_expr const& temp1(expr1); \ - __gmp_expr const& temp2(expr2); \ - return eval_fun::eval(temp1.__get_mp(), temp2.__get_mp()); \ -} - -#define __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, \ - type2, bigtype) \ - \ -template \ -inline type fun(const __gmp_expr &expr, type2 t) \ -{ \ - __gmp_expr const& temp(expr); \ - return eval_fun::eval(temp.__get_mp(), static_cast(t)); \ -} \ - \ -template \ -inline type fun(type2 t, const __gmp_expr &expr) \ -{ \ - __gmp_expr const& temp(expr); \ - return eval_fun::eval(static_cast(t), temp.__get_mp()); \ -} - -#define __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \ -__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, \ - type2, signed long int) - -#define __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \ -__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, \ - type2, unsigned long int) - -#define __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \ -__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, double) - -#define __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \ -__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, long double) - -#define __GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ -__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed char) \ -__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned char) \ -__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed int) \ -__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned int) \ -__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed short int) \ -__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned short int) \ -__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed long int) \ -__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned long int) \ -__GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, float) \ -__GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, double) \ -/* __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, long double) */ - -#define __GMP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ -__GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ -__GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) - - -// member operators - -#define __GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \ - \ -template \ -inline type##_class & type##_class::fun(const __gmp_expr &expr) \ -{ \ - __gmp_set_expr(mp, __gmp_expr, eval_fun> >(*this, expr)); \ - return *this; \ -} - -#define __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, \ - type2, bigtype) \ - \ -inline type##_class & type##_class::fun(type2 t) \ -{ \ - __gmp_set_expr(mp, __gmp_expr >(*this, t)); \ - return *this; \ -} - -#define __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \ -__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, \ - type2, signed long int) - -#define __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \ -__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, \ - type2, unsigned long int) - -#define __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \ -__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, double) - -#define __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \ -__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, long double) - -#define __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \ -__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed char) \ -__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned char) \ -__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed int) \ -__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned int) \ -__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed short int) \ -__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned short int) \ -__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed long int) \ -__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned long int) \ -__GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, float) \ -__GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, double) \ -/* __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, long double) */ - -#define __GMP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \ -__GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \ -__GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) - -#define __GMPZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ -__GMP_DEFINE_COMPOUND_OPERATOR(mpz, fun, eval_fun) - -#define __GMPQ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ -__GMP_DEFINE_COMPOUND_OPERATOR(mpq, fun, eval_fun) - -#define __GMPF_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ -__GMP_DEFINE_COMPOUND_OPERATOR(mpf, fun, eval_fun) - - - -#define __GMP_DEFINE_COMPOUND_OPERATOR_UI(type, fun, eval_fun) \ - \ -inline type##_class & type##_class::fun(mp_bitcnt_t l) \ -{ \ - __gmp_set_expr(mp, __gmp_expr >(*this, l)); \ - return *this; \ -} - -#define __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ -__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpz, fun, eval_fun) - -#define __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ -__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpq, fun, eval_fun) - -#define __GMPF_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ -__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpf, fun, eval_fun) - - - -#define __GMP_DEFINE_INCREMENT_OPERATOR(type, fun, eval_fun) \ - \ -inline type##_class & type##_class::fun() \ -{ \ - eval_fun::eval(mp); \ - return *this; \ -} \ - \ -inline type##_class type##_class::fun(int) \ -{ \ - type##_class temp(*this); \ - eval_fun::eval(mp); \ - return temp; \ -} - -#define __GMPZ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ -__GMP_DEFINE_INCREMENT_OPERATOR(mpz, fun, eval_fun) - -#define __GMPQ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ -__GMP_DEFINE_INCREMENT_OPERATOR(mpq, fun, eval_fun) - -#define __GMPF_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ -__GMP_DEFINE_INCREMENT_OPERATOR(mpf, fun, eval_fun) - - -#define __GMPP_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun) \ -template \ -__gmp_expr, eval_fun> > \ -fun(const __gmp_expr &expr) \ -{ \ - return __gmp_expr, eval_fun> >(expr); \ -} - -#define __GMPNN_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, bigtype) \ -inline __gmp_expr > \ -fun(type expr) \ -{ \ - return __gmp_expr >(expr); \ -} - -#define __GMPNS_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type) \ -__GMPNN_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, signed long) -#define __GMPNU_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type) \ -__GMPNN_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, unsigned long) -#define __GMPND_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type) \ -__GMPNN_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, type, double) - -#define __GMPN_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun) \ -__GMPNS_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed char) \ -__GMPNU_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned char) \ -__GMPNS_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed int) \ -__GMPNU_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned int) \ -__GMPNS_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed short int) \ -__GMPNU_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned short int) \ -__GMPNS_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, signed long int) \ -__GMPNU_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, unsigned long int) \ -__GMPND_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, float) \ -__GMPND_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun, double) \ - -#define __GMP_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun) \ -__GMPP_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun) \ -__GMPN_DEFINE_UNARY_STATIC_MEMFUN(T, fun, eval_fun) \ - - -/**************** Arithmetic operators and functions ****************/ - -// non-member operators and functions - -__GMP_DEFINE_UNARY_FUNCTION(operator+, __gmp_unary_plus) -__GMP_DEFINE_UNARY_FUNCTION(operator-, __gmp_unary_minus) -__GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, operator~, __gmp_unary_com) - -__GMP_DEFINE_BINARY_FUNCTION(operator+, __gmp_binary_plus) -__GMP_DEFINE_BINARY_FUNCTION(operator-, __gmp_binary_minus) -__GMP_DEFINE_BINARY_FUNCTION(operator*, __gmp_binary_multiplies) -__GMP_DEFINE_BINARY_FUNCTION(operator/, __gmp_binary_divides) -__GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, operator%, __gmp_binary_modulus) -__GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, operator&, __gmp_binary_and) -__GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, operator|, __gmp_binary_ior) -__GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, operator^, __gmp_binary_xor) - -__GMP_DEFINE_BINARY_FUNCTION_UI(operator<<, __gmp_binary_lshift) -__GMP_DEFINE_BINARY_FUNCTION_UI(operator>>, __gmp_binary_rshift) - -__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator==, __gmp_binary_equal) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator!=, ! __gmp_binary_equal) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<, __gmp_binary_less) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<=, ! __gmp_binary_greater) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>, __gmp_binary_greater) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>=, ! __gmp_binary_less) - -__GMP_DEFINE_UNARY_FUNCTION(abs, __gmp_abs_function) -__GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, trunc, __gmp_trunc_function) -__GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, floor, __gmp_floor_function) -__GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, ceil, __gmp_ceil_function) -__GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, sqrt, __gmp_sqrt_function) -__GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, sqrt, __gmp_sqrt_function) -__GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, factorial, __gmp_fac_function) -__GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, primorial, __gmp_primorial_function) -__GMP_DEFINE_UNARY_FUNCTION_1(mpz_t, fibonacci, __gmp_fib_function) -__GMP_DEFINE_BINARY_FUNCTION_1(mpf_t, hypot, __gmp_hypot_function) -__GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, gcd, __gmp_gcd_function) -__GMP_DEFINE_BINARY_FUNCTION_1(mpz_t, lcm, __gmp_lcm_function) - -__GMP_DEFINE_UNARY_TYPE_FUNCTION(int, sgn, __gmp_sgn_function) -__GMP_DEFINE_BINARY_TYPE_FUNCTION(int, cmp, __gmp_cmp_function) - -template -void swap(__gmp_expr& x, __gmp_expr& y) __GMPXX_NOEXCEPT -{ x.swap(y); } - -// member operators for mpz_class - -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus) - -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and) -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior) -__GMPZ_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor) - -__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) -__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) - -__GMPZ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) -__GMPZ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) - -__GMP_DEFINE_UNARY_STATIC_MEMFUN(mpz_t, mpz_class::factorial, __gmp_fac_function) -__GMP_DEFINE_UNARY_STATIC_MEMFUN(mpz_t, mpz_class::primorial, __gmp_primorial_function) -__GMP_DEFINE_UNARY_STATIC_MEMFUN(mpz_t, mpz_class::fibonacci, __gmp_fib_function) - -// member operators for mpq_class - -__GMPQ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) -__GMPQ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) -__GMPQ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) -__GMPQ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) - -__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) -__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) - -__GMPQ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) -__GMPQ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) - -// member operators for mpf_class - -__GMPF_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) -__GMPF_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) -__GMPF_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) -__GMPF_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) - -__GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) -__GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) - -__GMPF_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) -__GMPF_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) - - - -/**************** Class wrapper for gmp_randstate_t ****************/ - -class __gmp_urandomb_value { }; -class __gmp_urandomm_value { }; - -template <> -class __gmp_expr -{ -private: - __gmp_randstate_struct *state; - mp_bitcnt_t bits; -public: - __gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { } - void eval(mpz_ptr z) const { __gmp_rand_function::eval(z, state, bits); } - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } -}; - -template <> -class __gmp_expr -{ -private: - __gmp_randstate_struct *state; - mpz_class range; -public: - __gmp_expr(gmp_randstate_t s, const mpz_class &z) : state(s), range(z) { } - void eval(mpz_ptr z) const - { __gmp_rand_function::eval(z, state, range.get_mpz_t()); } - mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } -}; - -template <> -class __gmp_expr -{ -private: - __gmp_randstate_struct *state; - mp_bitcnt_t bits; -public: - __gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { } - void eval(mpf_ptr f) const - { - __gmp_rand_function::eval(f, state, - (bits>0) ? bits : mpf_get_prec(f)); - } - mp_bitcnt_t get_prec() const - { - if (bits == 0) - return mpf_get_default_prec(); - else - return bits; - } -}; - -extern "C" { - typedef void __gmp_randinit_default_t (gmp_randstate_t); - typedef void __gmp_randinit_lc_2exp_t (gmp_randstate_t, mpz_srcptr, unsigned long int, mp_bitcnt_t); - typedef int __gmp_randinit_lc_2exp_size_t (gmp_randstate_t, mp_bitcnt_t); -} - -class gmp_randclass -{ -private: - gmp_randstate_t state; - - // copy construction and assignment not allowed - gmp_randclass(const gmp_randclass &); - void operator=(const gmp_randclass &); -public: - // constructors and destructor - gmp_randclass(gmp_randalg_t alg, unsigned long int size) - { - switch (alg) - { - case GMP_RAND_ALG_LC: // no other cases for now - default: - gmp_randinit(state, alg, size); - break; - } - } - - // gmp_randinit_default - gmp_randclass(__gmp_randinit_default_t* f) { f(state); } - - // gmp_randinit_lc_2exp - gmp_randclass(__gmp_randinit_lc_2exp_t* f, - mpz_class z, unsigned long int l1, mp_bitcnt_t l2) - { f(state, z.get_mpz_t(), l1, l2); } - - // gmp_randinit_lc_2exp_size - gmp_randclass(__gmp_randinit_lc_2exp_size_t* f, - mp_bitcnt_t size) - { - if (f (state, size) == 0) - throw std::length_error ("gmp_randinit_lc_2exp_size"); - } - - ~gmp_randclass() { gmp_randclear(state); } - - // initialize - void seed(); // choose a random seed some way (?) - void seed(unsigned long int s) { gmp_randseed_ui(state, s); } - void seed(const mpz_class &z) { gmp_randseed(state, z.get_mpz_t()); } - - // get random number - __gmp_expr get_z_bits(mp_bitcnt_t l) - { return __gmp_expr(state, l); } - __gmp_expr get_z_bits(const mpz_class &z) - { return get_z_bits(z.get_ui()); } - // FIXME: z.get_bitcnt_t() ? - - __gmp_expr get_z_range(const mpz_class &z) - { return __gmp_expr(state, z); } - - __gmp_expr get_f(mp_bitcnt_t prec = 0) - { return __gmp_expr(state, prec); } -}; - - -/**************** Specialize std::numeric_limits ****************/ - -namespace std { - template <> class numeric_limits - { - public: - static const bool is_specialized = true; - static mpz_class min() { return mpz_class(); } - static mpz_class max() { return mpz_class(); } - static mpz_class lowest() { return mpz_class(); } - static const int digits = 0; - static const int digits10 = 0; - static const int max_digits10 = 0; - static const bool is_signed = true; - static const bool is_integer = true; - static const bool is_exact = true; - static const int radix = 2; - static mpz_class epsilon() { return mpz_class(); } - static mpz_class round_error() { return mpz_class(); } - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - static mpz_class infinity() { return mpz_class(); } - static mpz_class quiet_NaN() { return mpz_class(); } - static mpz_class signaling_NaN() { return mpz_class(); } - static mpz_class denorm_min() { return mpz_class(); } - static const bool is_iec559 = false; - static const bool is_bounded = false; - static const bool is_modulo = false; - static const bool traps = false; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; - }; - - template <> class numeric_limits - { - public: - static const bool is_specialized = true; - static mpq_class min() { return mpq_class(); } - static mpq_class max() { return mpq_class(); } - static mpq_class lowest() { return mpq_class(); } - static const int digits = 0; - static const int digits10 = 0; - static const int max_digits10 = 0; - static const bool is_signed = true; - static const bool is_integer = false; - static const bool is_exact = true; - static const int radix = 2; - static mpq_class epsilon() { return mpq_class(); } - static mpq_class round_error() { return mpq_class(); } - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - static mpq_class infinity() { return mpq_class(); } - static mpq_class quiet_NaN() { return mpq_class(); } - static mpq_class signaling_NaN() { return mpq_class(); } - static mpq_class denorm_min() { return mpq_class(); } - static const bool is_iec559 = false; - static const bool is_bounded = false; - static const bool is_modulo = false; - static const bool traps = false; - static const bool tinyness_before = false; - static const float_round_style round_style = round_toward_zero; - }; - - template <> class numeric_limits - { - public: - static const bool is_specialized = true; - static mpf_class min() { return mpf_class(); } - static mpf_class max() { return mpf_class(); } - static mpf_class lowest() { return mpf_class(); } - static const int digits = 0; - static const int digits10 = 0; - static const int max_digits10 = 0; - static const bool is_signed = true; - static const bool is_integer = false; - static const bool is_exact = false; - static const int radix = 2; - static mpf_class epsilon() { return mpf_class(); } - static mpf_class round_error() { return mpf_class(); } - static const int min_exponent = 0; - static const int min_exponent10 = 0; - static const int max_exponent = 0; - static const int max_exponent10 = 0; - static const bool has_infinity = false; - static const bool has_quiet_NaN = false; - static const bool has_signaling_NaN = false; - static const float_denorm_style has_denorm = denorm_absent; - static const bool has_denorm_loss = false; - static mpf_class infinity() { return mpf_class(); } - static mpf_class quiet_NaN() { return mpf_class(); } - static mpf_class signaling_NaN() { return mpf_class(); } - static mpf_class denorm_min() { return mpf_class(); } - static const bool is_iec559 = false; - static const bool is_bounded = false; - static const bool is_modulo = false; - static const bool traps = false; - static const bool tinyness_before = false; - static const float_round_style round_style = round_indeterminate; - }; -} - - -/**************** #undef all private macros ****************/ - -#undef __GMPP_DECLARE_COMPOUND_OPERATOR -#undef __GMPN_DECLARE_COMPOUND_OPERATOR -#undef __GMP_DECLARE_COMPOUND_OPERATOR -#undef __GMP_DECLARE_COMPOUND_OPERATOR_UI -#undef __GMP_DECLARE_INCREMENT_OPERATOR -#undef __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS -#undef __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS - -#undef __GMPZQ_DEFINE_EXPR - -#undef __GMP_DEFINE_UNARY_FUNCTION_1 -#undef __GMP_DEFINE_UNARY_FUNCTION -#undef __GMP_DEFINE_UNARY_TYPE_FUNCTION - -#undef __GMPP_DEFINE_BINARY_FUNCTION -#undef __GMPNN_DEFINE_BINARY_FUNCTION -#undef __GMPNS_DEFINE_BINARY_FUNCTION -#undef __GMPNU_DEFINE_BINARY_FUNCTION -#undef __GMPND_DEFINE_BINARY_FUNCTION -#undef __GMPNLD_DEFINE_BINARY_FUNCTION -#undef __GMPN_DEFINE_BINARY_FUNCTION -#undef __GMP_DEFINE_BINARY_FUNCTION - -#undef __GMP_DEFINE_BINARY_FUNCTION_UI - -#undef __GMPP_DEFINE_BINARY_TYPE_FUNCTION -#undef __GMPNN_DEFINE_BINARY_TYPE_FUNCTION -#undef __GMPNS_DEFINE_BINARY_TYPE_FUNCTION -#undef __GMPNU_DEFINE_BINARY_TYPE_FUNCTION -#undef __GMPND_DEFINE_BINARY_TYPE_FUNCTION -#undef __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION -#undef __GMPN_DEFINE_BINARY_TYPE_FUNCTION -#undef __GMP_DEFINE_BINARY_TYPE_FUNCTION - -#undef __GMPZ_DEFINE_COMPOUND_OPERATOR - -#undef __GMPP_DEFINE_COMPOUND_OPERATOR -#undef __GMPNN_DEFINE_COMPOUND_OPERATOR -#undef __GMPNS_DEFINE_COMPOUND_OPERATOR -#undef __GMPNU_DEFINE_COMPOUND_OPERATOR -#undef __GMPND_DEFINE_COMPOUND_OPERATOR -#undef __GMPNLD_DEFINE_COMPOUND_OPERATOR -#undef __GMPN_DEFINE_COMPOUND_OPERATOR -#undef __GMP_DEFINE_COMPOUND_OPERATOR - -#undef __GMPQ_DEFINE_COMPOUND_OPERATOR -#undef __GMPF_DEFINE_COMPOUND_OPERATOR - -#undef __GMP_DEFINE_COMPOUND_OPERATOR_UI -#undef __GMPZ_DEFINE_COMPOUND_OPERATOR_UI -#undef __GMPQ_DEFINE_COMPOUND_OPERATOR_UI -#undef __GMPF_DEFINE_COMPOUND_OPERATOR_UI - -#undef __GMP_DEFINE_INCREMENT_OPERATOR -#undef __GMPZ_DEFINE_INCREMENT_OPERATOR -#undef __GMPQ_DEFINE_INCREMENT_OPERATOR -#undef __GMPF_DEFINE_INCREMENT_OPERATOR - -#undef __GMPXX_CONSTANT_TRUE -#undef __GMPXX_CONSTANT - -#endif /* __GMP_PLUSPLUS__ */ diff --git a/include/gvAbcCmd.h b/include/gvAbcCmd.h deleted file mode 120000 index 87c7f0f9..00000000 --- a/include/gvAbcCmd.h +++ /dev/null @@ -1 +0,0 @@ -../src/abc/gvAbcCmd.h \ No newline at end of file diff --git a/include/gvAbcMgr.h b/include/gvAbcMgr.h deleted file mode 120000 index b8c82217..00000000 --- a/include/gvAbcMgr.h +++ /dev/null @@ -1 +0,0 @@ -../src/abc/gvAbcMgr.h \ No newline at end of file diff --git a/include/gvAbcNtk.h b/include/gvAbcNtk.h deleted file mode 120000 index bf41baed..00000000 --- a/include/gvAbcNtk.h +++ /dev/null @@ -1 +0,0 @@ -../src/abc/gvAbcNtk.h \ No newline at end of file diff --git a/include/gvCmdComm.h b/include/gvCmdComm.h deleted file mode 120000 index 27bbe1c2..00000000 --- a/include/gvCmdComm.h +++ /dev/null @@ -1 +0,0 @@ -../src/cmd/gvCmdComm.h \ No newline at end of file diff --git a/include/gvCmdMgr.h b/include/gvCmdMgr.h deleted file mode 120000 index 1bc8799e..00000000 --- a/include/gvCmdMgr.h +++ /dev/null @@ -1 +0,0 @@ -../src/cmd/gvCmdMgr.h \ No newline at end of file diff --git a/include/gvIntType.h b/include/gvIntType.h deleted file mode 120000 index a6c983c3..00000000 --- a/include/gvIntType.h +++ /dev/null @@ -1 +0,0 @@ -../src/util/gvIntType.h \ No newline at end of file diff --git a/include/gvModCmd.h b/include/gvModCmd.h deleted file mode 120000 index 763cbb22..00000000 --- a/include/gvModCmd.h +++ /dev/null @@ -1 +0,0 @@ -../src/mod/gvModCmd.h \ No newline at end of file diff --git a/include/gvModMgr.h b/include/gvModMgr.h deleted file mode 120000 index f5d7be90..00000000 --- a/include/gvModMgr.h +++ /dev/null @@ -1 +0,0 @@ -../src/mod/gvModMgr.h \ No newline at end of file diff --git a/include/gvMsg.h b/include/gvMsg.h deleted file mode 120000 index 26b49245..00000000 --- a/include/gvMsg.h +++ /dev/null @@ -1 +0,0 @@ -../src/util/gvMsg.h \ No newline at end of file diff --git a/include/gvNtkCmd.h b/include/gvNtkCmd.h deleted file mode 120000 index 4bf9dfae..00000000 --- a/include/gvNtkCmd.h +++ /dev/null @@ -1 +0,0 @@ -../src/ntk/gvNtkCmd.h \ No newline at end of file diff --git a/include/gvSimCmd.h b/include/gvSimCmd.h deleted file mode 120000 index 09fef443..00000000 --- a/include/gvSimCmd.h +++ /dev/null @@ -1 +0,0 @@ -../src/sim/gvSimCmd.h \ No newline at end of file diff --git a/include/gvUsage.h b/include/gvUsage.h deleted file mode 120000 index 2da66c94..00000000 --- a/include/gvUsage.h +++ /dev/null @@ -1 +0,0 @@ -../src/util/gvUsage.h \ No newline at end of file diff --git a/include/gvVrfCmd.h b/include/gvVrfCmd.h deleted file mode 120000 index f9cdd810..00000000 --- a/include/gvVrfCmd.h +++ /dev/null @@ -1 +0,0 @@ -../src/vrf/gvVrfCmd.h \ No newline at end of file diff --git a/include/hashlib.h b/include/hashlib.h deleted file mode 120000 index 93fa5e2c..00000000 --- a/include/hashlib.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/hashlib.h \ No newline at end of file diff --git a/include/libyosys.so b/include/libyosys.so deleted file mode 120000 index ce621502..00000000 --- a/include/libyosys.so +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/libyosys.so \ No newline at end of file diff --git a/include/log.h b/include/log.h deleted file mode 120000 index f2ee7d04..00000000 --- a/include/log.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/log.h \ No newline at end of file diff --git a/include/macc.h b/include/macc.h deleted file mode 120000 index 82204ecb..00000000 --- a/include/macc.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/macc.h \ No newline at end of file diff --git a/include/mem.h b/include/mem.h deleted file mode 120000 index 7312d859..00000000 --- a/include/mem.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/mem.h \ No newline at end of file diff --git a/include/modtools.h b/include/modtools.h deleted file mode 120000 index 8efaa977..00000000 --- a/include/modtools.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/modtools.h \ No newline at end of file diff --git a/include/myHashMap.h b/include/myHashMap.h deleted file mode 120000 index d4bcb81c..00000000 --- a/include/myHashMap.h +++ /dev/null @@ -1 +0,0 @@ -../src/util/myHashMap.h \ No newline at end of file diff --git a/include/myUsage.h b/include/myUsage.h deleted file mode 120000 index 20689518..00000000 --- a/include/myUsage.h +++ /dev/null @@ -1 +0,0 @@ -../src/util/myUsage.h \ No newline at end of file diff --git a/include/preproc.h b/include/preproc.h deleted file mode 120000 index ec99bf3b..00000000 --- a/include/preproc.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/preproc.h \ No newline at end of file diff --git a/include/qcsat.h b/include/qcsat.h deleted file mode 120000 index 0e8b6580..00000000 --- a/include/qcsat.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/qcsat.h \ No newline at end of file diff --git a/include/quteRTL.h b/include/quteRTL.h deleted file mode 120000 index 4121cb5d..00000000 --- a/include/quteRTL.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/quteRTL/quteRTL.h \ No newline at end of file diff --git a/include/register.h b/include/register.h deleted file mode 120000 index d7354657..00000000 --- a/include/register.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/register.h \ No newline at end of file diff --git a/include/rnGen.h b/include/rnGen.h deleted file mode 120000 index 95506035..00000000 --- a/include/rnGen.h +++ /dev/null @@ -1 +0,0 @@ -../src/util/rnGen.h \ No newline at end of file diff --git a/include/rtlil.h b/include/rtlil.h deleted file mode 120000 index cd916c96..00000000 --- a/include/rtlil.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/rtlil.h \ No newline at end of file diff --git a/include/sat.h b/include/sat.h deleted file mode 120000 index 16531751..00000000 --- a/include/sat.h +++ /dev/null @@ -1 +0,0 @@ -../src/sat/sat.h \ No newline at end of file diff --git a/include/satgen.h b/include/satgen.h deleted file mode 120000 index 96fac5b9..00000000 --- a/include/satgen.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/satgen.h \ No newline at end of file diff --git a/include/sigtools.h b/include/sigtools.h deleted file mode 120000 index 0b314726..00000000 --- a/include/sigtools.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/sigtools.h \ No newline at end of file diff --git a/include/timinginfo.h b/include/timinginfo.h deleted file mode 120000 index b2199177..00000000 --- a/include/timinginfo.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/timinginfo.h \ No newline at end of file diff --git a/include/util.h b/include/util.h deleted file mode 120000 index 7f2305cb..00000000 --- a/include/util.h +++ /dev/null @@ -1 +0,0 @@ -../src/util/util.h \ No newline at end of file diff --git a/include/utils.h b/include/utils.h deleted file mode 120000 index 8923cbe3..00000000 --- a/include/utils.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/utils.h \ No newline at end of file diff --git a/include/yosys.h b/include/yosys.h deleted file mode 120000 index b6126261..00000000 --- a/include/yosys.h +++ /dev/null @@ -1 +0,0 @@ -../src/eng/yosys/yosys.h \ No newline at end of file diff --git a/lib/lib.d b/lib/lib.d deleted file mode 100644 index e69de29b..00000000 diff --git a/src/abc/.depend.mak b/src/abc/.depend.mak deleted file mode 100644 index b6aa2c7f..00000000 --- a/src/abc/.depend.mak +++ /dev/null @@ -1,66 +0,0 @@ -abcCmd.o: abcCmd.cpp abcCmd.h ../../include/gvCmdMgr.h abcMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - ../../include/cirGate.h ../../include/cirDef.h ../../include/myHash.h \ - ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ - ../../include/SolverTypesV.h ../../include/GlobalV.h \ - ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ - ../../include/cirGate.h ../../include/cirMgr.h \ - ../../include/base/abc/abc.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h ../../include/cirMgr.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -abcMgr.o: abcMgr.cpp abcMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/base/main/main.h ../../include/base/main/abcapis.h \ - ../../include/base/cmd/cmd.h ../../include/base/io/ioAbc.h \ - ../../include/misc/util/utilNam.h ../../include/base/main/mainInt.h \ - ../../include/base/main/main.h ../../include/misc/tim/tim.h \ - ../../include/map/if/if.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/util/utilTruth.h ../../include/opt/dau/dau.h \ - ../../include/misc/vec/vecHash.h ../../include/aig/aig/aig.h \ - ../../include/proof/ssw/ssw.h ../../include/proof/fra/fra.h \ - ../../include/opt/dar/dar.h ../../include/sat/bsat/satSolver.h \ - ../../include/sat/bsat/satVec.h ../../include/sat/bsat/satClause.h \ - ../../include/misc/util/utilDouble.h ../../include/aig/ioa/ioa.h \ - ../../include/cirGate.h ../../include/cirDef.h ../../include/myHash.h \ - ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ - ../../include/SolverTypesV.h ../../include/GlobalV.h \ - ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ - ../../include/cirGate.h ../../include/cirMgr.h \ - ../../include/base/abc/abc.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h ../../include/cirMgr.h \ - ../../include/bdd/cudd/cudd.h ../../include/bdd/mtr/mtr.h \ - ../../include/bdd/epd/epd.h ../../include/sat/cnf/cnf.h \ - ../../include/opt/dar/darInt.h ../../include/opt/dar/dar.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/abc/.extheader.mak b/src/abc/.extheader.mak deleted file mode 100644 index bd2e8c73..00000000 --- a/src/abc/.extheader.mak +++ /dev/null @@ -1,7 +0,0 @@ -abc.d: ../../include/abcCmd.h ../../include/abcMgr.h -../../include/abcCmd.h: abcCmd.h - @rm -f ../../include/abcCmd.h - @ln -fs ../src/abc/abcCmd.h ../../include/abcCmd.h -../../include/abcMgr.h: abcMgr.h - @rm -f ../../include/abcMgr.h - @ln -fs ../src/abc/abcMgr.h ../../include/abcMgr.h diff --git a/src/bdd/.depend.mak b/src/bdd/.depend.mak deleted file mode 100644 index faf517e0..00000000 --- a/src/bdd/.depend.mak +++ /dev/null @@ -1,24 +0,0 @@ -bddCmd.o: bddCmd.cpp bddCmd.h ../../include/gvCmdMgr.h bddMgrV.h myHash.h \ - bddNodeV.h ../../include/cirGate.h ../../include/cirDef.h myHash.h \ - ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ - ../../include/SolverTypesV.h ../../include/GlobalV.h \ - ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ - ../../include/cirGate.h ../../include/cirMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/gvBitVec.h ../../include/gvIntType.h \ - ../../include/cirMgr.h ../../include/gvMsg.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -bddMgrV.o: bddMgrV.cpp bddMgrV.h myHash.h bddNodeV.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -bddNodeV.o: bddNodeV.cpp bddNodeV.h bddMgrV.h myHash.h diff --git a/src/bdd/.extheader.mak b/src/bdd/.extheader.mak deleted file mode 100644 index 7635a409..00000000 --- a/src/bdd/.extheader.mak +++ /dev/null @@ -1,13 +0,0 @@ -bdd.d: ../../include/bddMgrV.h ../../include/bddNodeV.h ../../include/bddCmd.h ../../include/myHash.h -../../include/bddMgrV.h: bddMgrV.h - @rm -f ../../include/bddMgrV.h - @ln -fs ../src/bdd/bddMgrV.h ../../include/bddMgrV.h -../../include/bddNodeV.h: bddNodeV.h - @rm -f ../../include/bddNodeV.h - @ln -fs ../src/bdd/bddNodeV.h ../../include/bddNodeV.h -../../include/bddCmd.h: bddCmd.h - @rm -f ../../include/bddCmd.h - @ln -fs ../src/bdd/bddCmd.h ../../include/bddCmd.h -../../include/myHash.h: myHash.h - @rm -f ../../include/myHash.h - @ln -fs ../src/bdd/myHash.h ../../include/myHash.h diff --git a/src/cad/Makefile b/src/cad/Makefile new file mode 100644 index 00000000..aacb4408 --- /dev/null +++ b/src/cad/Makefile @@ -0,0 +1,5 @@ +PKGFLAG = $(DEBUG_FLAG) +EXTHDRS = cadAlg.h + +include ../Makefile.in +include ../Makefile.lib diff --git a/src/cad/cadAlg.cpp b/src/cad/cadAlg.cpp new file mode 100644 index 00000000..8908b0a0 --- /dev/null +++ b/src/cad/cadAlg.cpp @@ -0,0 +1,4 @@ +#include "cadAlg.h" + +// Member Functions Implementation +// ... diff --git a/src/cad/cadAlg.h b/src/cad/cadAlg.h new file mode 100644 index 00000000..c0ccdc28 --- /dev/null +++ b/src/cad/cadAlg.h @@ -0,0 +1,11 @@ +#include "abcMgr.h" +#include "cirMgr.h" +#include "yosysMgr.h" + +class CADAlg { +public: + // Define your member funtions + // ... + +private: +}; diff --git a/src/cir/.depend.mak b/src/cir/.depend.mak deleted file mode 100644 index 1cd8017d..00000000 --- a/src/cir/.depend.mak +++ /dev/null @@ -1,140 +0,0 @@ -cirAig.o: cirAig.cpp cirGate.h cirDef.h ../../include/myHash.h \ - ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ - ../../include/SolverTypesV.h ../../include/GlobalV.h \ - ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ - ../../include/cirGate.h ../../include/cirMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/cirDef.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h cirMgr.h ../../include/abcMgr.h \ - ../../include/base/main/main.h ../../include/base/abc/abc.h \ - ../../include/base/main/abcapis.h ../../include/base/cmd/cmd.h \ - ../../include/base/io/ioAbc.h ../../include/misc/util/utilNam.h \ - ../../include/base/main/mainInt.h ../../include/base/main/main.h \ - ../../include/misc/tim/tim.h ../../include/map/if/if.h \ - ../../include/misc/vec/vecMem.h ../../include/misc/util/utilTruth.h \ - ../../include/opt/dau/dau.h ../../include/misc/vec/vecHash.h \ - ../../include/aig/aig/aig.h ../../include/proof/ssw/ssw.h \ - ../../include/proof/fra/fra.h ../../include/opt/dar/dar.h \ - ../../include/sat/bsat/satSolver.h ../../include/sat/bsat/satVec.h \ - ../../include/sat/bsat/satClause.h ../../include/misc/util/utilDouble.h \ - ../../include/aig/ioa/ioa.h ../../include/gvYosysMgr.h \ - ../../include/kernel/yosys.h /usr/include/tcl8.6/tcl.h \ - /usr/include/tcl8.6/tclDecls.h /usr/include/tcl8.6/tclPlatDecls.h \ - ../../include/kernel/hashlib.h ../../include/kernel/log.h \ - ../../include/kernel/yosys.h ../../include/kernel/rtlil.h \ - ../../include/kernel/constids.inc ../../include/kernel/register.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h -cirBdd.o: cirBdd.cpp ../../include/bddMgrV.h ../../include/myHash.h \ - ../../include/bddNodeV.h ../../include/bddNodeV.h cirGate.h cirDef.h \ - ../../include/myHash.h ../../include/gvSat.h ../../include/SolverV.h \ - ../../include/ProofV.h ../../include/SolverTypesV.h \ - ../../include/GlobalV.h ../../include/FileV.h ../../include/VarOrderV.h \ - ../../include/HeapV.h ../../include/cirGate.h ../../include/cirMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/cirDef.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h cirMgr.h ../../include/gvMsg.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h -cirCmd.o: cirCmd.cpp cirCmd.h ../../include/gvCmdMgr.h cirGate.h cirDef.h \ - ../../include/myHash.h ../../include/gvSat.h ../../include/SolverV.h \ - ../../include/ProofV.h ../../include/SolverTypesV.h \ - ../../include/GlobalV.h ../../include/FileV.h ../../include/VarOrderV.h \ - ../../include/HeapV.h ../../include/cirGate.h ../../include/cirMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/cirDef.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h cirMgr.h ../../include/gvModMgr.h \ - ../../include/gvCmdMgr.h ../../include/gvMsg.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h -cirFraig.o: cirFraig.cpp -cirGate.o: cirGate.cpp cirGate.h cirDef.h ../../include/myHash.h \ - ../../include/gvSat.h ../../include/SolverV.h ../../include/ProofV.h \ - ../../include/SolverTypesV.h ../../include/GlobalV.h \ - ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ - ../../include/cirGate.h ../../include/cirMgr.h \ - ../../include/base/abc/abc.h ../../include/misc/vec/vec.h \ - ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h \ - ../../include/cirDef.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h cirMgr.h ../../include/util.h \ - ../../include/rnGen.h ../../include/myUsage.h \ - ../../include/base/abc/abc.h -cirMgr.o: cirMgr.cpp cirMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirDef.h \ - ../../include/myHash.h cirGate.h ../../include/gvSat.h \ - ../../include/SolverV.h ../../include/ProofV.h \ - ../../include/SolverTypesV.h ../../include/GlobalV.h \ - ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ - ../../include/cirGate.h ../../include/cirMgr.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h -cirOpt.o: cirOpt.cpp cirMgr.h ../../include/base/abc/abc.h \ - ../../include/misc/vec/vec.h ../../include/misc/util/abc_global.h \ - ../../include/misc/util/abc_namespaces.h ../../include/misc/vec/vecInt.h \ - ../../include/misc/vec/vecFlt.h ../../include/misc/vec/vecStr.h \ - ../../include/misc/vec/vecPtr.h ../../include/misc/vec/vecVec.h \ - ../../include/misc/vec/vecAtt.h ../../include/misc/vec/vecWrd.h \ - ../../include/misc/vec/vecBit.h ../../include/misc/vec/vecMem.h \ - ../../include/misc/vec/vecWec.h ../../include/aig/hop/hop.h \ - ../../include/aig/gia/gia.h ../../include/misc/vec/vecWec.h \ - ../../include/misc/util/utilCex.h ../../include/misc/st/st.h \ - ../../include/misc/st/stmm.h ../../include/misc/nm/nm.h \ - ../../include/misc/mem/mem.h ../../include/misc/extra/extra.h cirDef.h \ - ../../include/myHash.h cirGate.h ../../include/gvSat.h \ - ../../include/SolverV.h ../../include/ProofV.h \ - ../../include/SolverTypesV.h ../../include/GlobalV.h \ - ../../include/FileV.h ../../include/VarOrderV.h ../../include/HeapV.h \ - ../../include/cirGate.h ../../include/cirMgr.h ../../include/gvBitVec.h \ - ../../include/gvIntType.h ../../include/util.h ../../include/rnGen.h \ - ../../include/myUsage.h -cirSim.o: cirSim.cpp diff --git a/src/cir/.extheader.mak b/src/cir/.extheader.mak deleted file mode 100644 index 09d0ee5b..00000000 --- a/src/cir/.extheader.mak +++ /dev/null @@ -1,16 +0,0 @@ -cir.d: ../../include/cirCmd.h ../../include/cirDef.h ../../include/cirFraig.h ../../include/cirGate.h ../../include/cirMgr.h -../../include/cirCmd.h: cirCmd.h - @rm -f ../../include/cirCmd.h - @ln -fs ../src/cir/cirCmd.h ../../include/cirCmd.h -../../include/cirDef.h: cirDef.h - @rm -f ../../include/cirDef.h - @ln -fs ../src/cir/cirDef.h ../../include/cirDef.h -../../include/cirFraig.h: cirFraig.h - @rm -f ../../include/cirFraig.h - @ln -fs ../src/cir/cirFraig.h ../../include/cirFraig.h -../../include/cirGate.h: cirGate.h - @rm -f ../../include/cirGate.h - @ln -fs ../src/cir/cirGate.h ../../include/cirGate.h -../../include/cirMgr.h: cirMgr.h - @rm -f ../../include/cirMgr.h - @ln -fs ../src/cir/cirMgr.h ../../include/cirMgr.h diff --git a/src/cir/cirAig.cpp b/src/cir/cirAig.cpp index 59b56500..28e30775 100644 --- a/src/cir/cirAig.cpp +++ b/src/cir/cirAig.cpp @@ -11,7 +11,7 @@ #include #include "abcMgr.h" -#include "gvYosysMgr.h" +#include "yosysMgr.h" #include "util.h" /** diff --git a/src/cmd/.depend.mak b/src/cmd/.depend.mak deleted file mode 100644 index 897d154b..00000000 --- a/src/cmd/.depend.mak +++ /dev/null @@ -1,5 +0,0 @@ -gvCmdComm.o: gvCmdComm.cpp gvCmdComm.h gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/gvUsage.h ../../include/gvIntType.h ../../include/gvMsg.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h -gvCmdMgr.o: gvCmdMgr.cpp gvCmdMgr.h ../../include/gvMsg.h \ - ../../include/util.h ../../include/rnGen.h ../../include/myUsage.h diff --git a/src/cmd/.extheader.mak b/src/cmd/.extheader.mak deleted file mode 100644 index 61bd2bab..00000000 --- a/src/cmd/.extheader.mak +++ /dev/null @@ -1,7 +0,0 @@ -cmd.d: ../../include/gvCmdComm.h ../../include/gvCmdMgr.h -../../include/gvCmdComm.h: gvCmdComm.h - @rm -f ../../include/gvCmdComm.h - @ln -fs ../src/cmd/gvCmdComm.h ../../include/gvCmdComm.h -../../include/gvCmdMgr.h: gvCmdMgr.h - @rm -f ../../include/gvCmdMgr.h - @ln -fs ../src/cmd/gvCmdMgr.h ../../include/gvCmdMgr.h diff --git a/src/ext/sim.so b/src/ext/sim.so index a2a96a590d22e10fde82c63e2a571eeb07b78eaf..93b49438900173bf8ad565ac8253269993482e96 100755 GIT binary patch delta 35053 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 delta 35801 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