Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
abc
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
abc
Commits
f2d096c9
Commit
f2d096c9
authored
Feb 10, 2017
by
Alan Mishchenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improving CEX minimization.
parent
d335ee09
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
196 additions
and
104 deletions
+196
-104
src/base/io/io.c
+1
-1
src/misc/util/utilCex.c
+18
-7
src/sat/bmc/bmc.h
+2
-2
src/sat/bmc/bmcCexCare.c
+172
-91
src/sat/bmc/bmcCexTools.c
+3
-3
No files found.
src/base/io/io.c
View file @
f2d096c9
...
@@ -2420,7 +2420,7 @@ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv )
...
@@ -2420,7 +2420,7 @@ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv )
Bmc_CexCareVerify
(
pAig
,
pCex
,
pCare
,
fVerbose
);
Bmc_CexCareVerify
(
pAig
,
pCex
,
pCare
,
fVerbose
);
}
}
else
else
pCare
=
Bmc_CexCareMinimize
(
pAig
,
pCex
,
fCheckCex
,
fVerbose
);
pCare
=
Bmc_CexCareMinimize
(
pAig
,
0
,
pCex
,
fCheckCex
,
fVerbose
);
Aig_ManStop
(
pAig
);
Aig_ManStop
(
pAig
);
}
}
// output flop values (unaffected by the minimization)
// output flop values (unaffected by the minimization)
...
...
src/misc/util/utilCex.c
View file @
f2d096c9
...
@@ -272,9 +272,9 @@ void Abc_CexPrintStats( Abc_Cex_t * p )
...
@@ -272,9 +272,9 @@ void Abc_CexPrintStats( Abc_Cex_t * p )
p
->
iPo
,
p
->
iFrame
,
p
->
nRegs
,
p
->
nPis
,
p
->
nBits
,
p
->
iPo
,
p
->
iFrame
,
p
->
nRegs
,
p
->
nPis
,
p
->
nBits
,
Counter
,
100
.
0
*
Counter
/
(
p
->
nBits
-
p
->
nRegs
)
);
Counter
,
100
.
0
*
Counter
/
(
p
->
nBits
-
p
->
nRegs
)
);
}
}
void
Abc_CexPrintStatsInputs
(
Abc_Cex_t
*
p
,
int
n
Input
s
)
void
Abc_CexPrintStatsInputs
(
Abc_Cex_t
*
p
,
int
n
RealPi
s
)
{
{
int
k
,
Counter
=
0
,
Counter
2
=
0
;
int
k
,
Counter
=
0
,
Counter
Pi
=
0
,
CounterPpi
=
0
;
if
(
p
==
NULL
)
if
(
p
==
NULL
)
{
{
printf
(
"The counter example is NULL.
\n
"
);
printf
(
"The counter example is NULL.
\n
"
);
...
@@ -285,16 +285,27 @@ void Abc_CexPrintStatsInputs( Abc_Cex_t * p, int nInputs )
...
@@ -285,16 +285,27 @@ void Abc_CexPrintStatsInputs( Abc_Cex_t * p, int nInputs )
printf
(
"The counter example is present but not available (pointer has value
\"
1
\"
).
\n
"
);
printf
(
"The counter example is present but not available (pointer has value
\"
1
\"
).
\n
"
);
return
;
return
;
}
}
assert
(
nRealPis
<=
p
->
nPis
);
for
(
k
=
0
;
k
<
p
->
nBits
;
k
++
)
for
(
k
=
0
;
k
<
p
->
nBits
;
k
++
)
{
{
Counter
+=
Abc_InfoHasBit
(
p
->
pData
,
k
);
Counter
+=
Abc_InfoHasBit
(
p
->
pData
,
k
);
if
(
(
k
-
p
->
nRegs
)
%
p
->
nPis
<
nInputs
)
if
(
nRealPis
==
p
->
nPis
)
Counter2
+=
Abc_InfoHasBit
(
p
->
pData
,
k
);
continue
;
if
(
(
k
-
p
->
nRegs
)
%
p
->
nPis
<
nRealPis
)
CounterPi
+=
Abc_InfoHasBit
(
p
->
pData
,
k
);
else
CounterPpi
+=
Abc_InfoHasBit
(
p
->
pData
,
k
);
}
}
printf
(
"CEX: Po =%4d Fr
ame =%4d FF = %d PI = %d Bit =%8d 1s =%8d (%5.2f %%) 1sIn =%8d (%5.2f %%)
\n
"
,
printf
(
"CEX: Po =%4d Fr
=%4d FF = %d PI = %d Bit =%7d 1 =%8d (%5.2f %%)
"
,
p
->
iPo
,
p
->
iFrame
,
p
->
nRegs
,
p
->
nPis
,
p
->
nBits
,
p
->
iPo
,
p
->
iFrame
,
p
->
nRegs
,
p
->
nPis
,
p
->
nBits
,
Counter
,
100
.
0
*
Counter
/
(
p
->
nBits
-
p
->
nRegs
),
Counter
,
100
.
0
*
Counter
/
((
p
->
iFrame
+
1
)
*
p
->
nPis
)
);
Counter2
,
100
.
0
*
Counter2
/
(
p
->
nBits
-
p
->
nRegs
-
(
p
->
iFrame
+
1
)
*
(
p
->
nPis
-
nInputs
))
);
if
(
nRealPis
<
p
->
nPis
)
{
printf
(
" 1pi =%8d (%5.2f %%) 1ppi =%8d (%5.2f %%)"
,
CounterPi
,
100
.
0
*
CounterPi
/
((
p
->
iFrame
+
1
)
*
nRealPis
),
CounterPpi
,
100
.
0
*
CounterPpi
/
((
p
->
iFrame
+
1
)
*
(
p
->
nPis
-
nRealPis
))
);
}
printf
(
"
\n
"
);
}
}
/**Function*************************************************************
/**Function*************************************************************
...
...
src/sat/bmc/bmc.h
View file @
f2d096c9
...
@@ -164,7 +164,7 @@ extern int Saig_ManBmcScalable( Aig_Man_t * pAig, Saig_ParBmc_t *
...
@@ -164,7 +164,7 @@ extern int Saig_ManBmcScalable( Aig_Man_t * pAig, Saig_ParBmc_t *
extern
int
Gia_ManBmcPerform
(
Gia_Man_t
*
p
,
Bmc_AndPar_t
*
pPars
);
extern
int
Gia_ManBmcPerform
(
Gia_Man_t
*
p
,
Bmc_AndPar_t
*
pPars
);
/*=== bmcCexCare.c ==========================================================*/
/*=== bmcCexCare.c ==========================================================*/
extern
Abc_Cex_t
*
Bmc_CexCareExtendToObjects
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
Abc_Cex_t
*
pCexCare
);
extern
Abc_Cex_t
*
Bmc_CexCareExtendToObjects
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
Abc_Cex_t
*
pCexCare
);
extern
Abc_Cex_t
*
Bmc_CexCareMinimize
(
Aig_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
int
fCheck
,
int
fVerbose
);
extern
Abc_Cex_t
*
Bmc_CexCareMinimize
(
Aig_Man_t
*
p
,
int
nPPis
,
Abc_Cex_t
*
pCex
,
int
fCheck
,
int
fVerbose
);
extern
void
Bmc_CexCareVerify
(
Aig_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
Abc_Cex_t
*
pCexMin
,
int
fVerbose
);
extern
void
Bmc_CexCareVerify
(
Aig_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
Abc_Cex_t
*
pCexMin
,
int
fVerbose
);
/*=== bmcCexCut.c ==========================================================*/
/*=== bmcCexCut.c ==========================================================*/
extern
Gia_Man_t
*
Bmc_GiaTargetStates
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
int
iFrBeg
,
int
iFrEnd
,
int
fCombOnly
,
int
fGenAll
,
int
fAllFrames
,
int
fVerbose
);
extern
Gia_Man_t
*
Bmc_GiaTargetStates
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
int
iFrBeg
,
int
iFrEnd
,
int
fCombOnly
,
int
fGenAll
,
int
fAllFrames
,
int
fVerbose
);
...
@@ -172,7 +172,7 @@ extern Aig_Man_t * Bmc_AigTargetStates( Aig_Man_t * p, Abc_Cex_t * pCex, i
...
@@ -172,7 +172,7 @@ extern Aig_Man_t * Bmc_AigTargetStates( Aig_Man_t * p, Abc_Cex_t * pCex, i
/*=== bmcCexMin.c ==========================================================*/
/*=== bmcCexMin.c ==========================================================*/
extern
Abc_Cex_t
*
Saig_ManCexMinPerform
(
Aig_Man_t
*
pAig
,
Abc_Cex_t
*
pCex
);
extern
Abc_Cex_t
*
Saig_ManCexMinPerform
(
Aig_Man_t
*
pAig
,
Abc_Cex_t
*
pCex
);
/*=== bmcCexTool.c ==========================================================*/
/*=== bmcCexTool.c ==========================================================*/
extern
void
Bmc_CexPrint
(
Abc_Cex_t
*
pCex
,
int
n
Input
s
,
int
fVerbose
);
extern
void
Bmc_CexPrint
(
Abc_Cex_t
*
pCex
,
int
n
RealPi
s
,
int
fVerbose
);
extern
int
Bmc_CexVerify
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
Abc_Cex_t
*
pCexCare
);
extern
int
Bmc_CexVerify
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
Abc_Cex_t
*
pCexCare
);
/*=== bmcICheck.c ==========================================================*/
/*=== bmcICheck.c ==========================================================*/
extern
void
Bmc_PerformICheck
(
Gia_Man_t
*
p
,
int
nFramesMax
,
int
nTimeOut
,
int
fEmpty
,
int
fVerbose
);
extern
void
Bmc_PerformICheck
(
Gia_Man_t
*
p
,
int
nFramesMax
,
int
nTimeOut
,
int
fEmpty
,
int
fVerbose
);
...
...
src/sat/bmc/bmcCexCare.c
View file @
f2d096c9
...
@@ -88,7 +88,7 @@ Abc_Cex_t * Bmc_CexCareExtendToObjects( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex
...
@@ -88,7 +88,7 @@ Abc_Cex_t * Bmc_CexCareExtendToObjects( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex
/**Function*************************************************************
/**Function*************************************************************
Synopsis [
Back
ward propagation.]
Synopsis [
For
ward propagation.]
Description []
Description []
...
@@ -97,21 +97,14 @@ Abc_Cex_t * Bmc_CexCareExtendToObjects( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex
...
@@ -97,21 +97,14 @@ Abc_Cex_t * Bmc_CexCareExtendToObjects( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex
SeeAlso []
SeeAlso []
***********************************************************************/
***********************************************************************/
void
Bmc_CexCarePropagateFwdOne
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
int
f
,
int
fGrow
)
void
Bmc_CexCarePropagateFwdOne
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
int
f
,
Vec_Int_t
*
vPriosIn
)
{
{
Gia_Obj_t
*
pObj
;
Gia_Obj_t
*
pObj
;
int
Prio
,
Prio0
,
Prio1
;
int
Prio
,
Prio0
,
Prio1
;
int
i
,
Phase0
,
Phase1
;
int
i
,
Phase0
,
Phase1
;
if
(
(
fGrow
&
2
)
)
assert
(
Vec_IntSize
(
vPriosIn
)
==
pCex
->
nPis
*
(
pCex
->
iFrame
+
1
)
);
{
Gia_ManForEachPi
(
p
,
pObj
,
i
)
Gia_ManForEachPi
(
p
,
pObj
,
i
)
pObj
->
Value
=
Vec_IntEntry
(
vPriosIn
,
f
*
pCex
->
nPis
+
i
);
pObj
->
Value
=
Abc_Var2Lit
(
f
*
pCex
->
nPis
+
(
pCex
->
nPis
-
1
-
i
)
+
1
,
Abc_InfoHasBit
(
pCex
->
pData
,
pCex
->
nRegs
+
pCex
->
nPis
*
f
+
i
)
);
}
else
{
Gia_ManForEachPi
(
p
,
pObj
,
i
)
pObj
->
Value
=
Abc_Var2Lit
(
f
*
pCex
->
nPis
+
i
+
1
,
Abc_InfoHasBit
(
pCex
->
pData
,
pCex
->
nRegs
+
pCex
->
nPis
*
f
+
i
)
);
}
Gia_ManForEachAnd
(
p
,
pObj
,
i
)
Gia_ManForEachAnd
(
p
,
pObj
,
i
)
{
{
Prio0
=
Abc_Lit2Var
(
Gia_ObjFanin0
(
pObj
)
->
Value
);
Prio0
=
Abc_Lit2Var
(
Gia_ObjFanin0
(
pObj
)
->
Value
);
...
@@ -119,37 +112,38 @@ void Bmc_CexCarePropagateFwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, int fGr
...
@@ -119,37 +112,38 @@ void Bmc_CexCarePropagateFwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, int fGr
Phase0
=
Abc_LitIsCompl
(
Gia_ObjFanin0
(
pObj
)
->
Value
)
^
Gia_ObjFaninC0
(
pObj
);
Phase0
=
Abc_LitIsCompl
(
Gia_ObjFanin0
(
pObj
)
->
Value
)
^
Gia_ObjFaninC0
(
pObj
);
Phase1
=
Abc_LitIsCompl
(
Gia_ObjFanin1
(
pObj
)
->
Value
)
^
Gia_ObjFaninC1
(
pObj
);
Phase1
=
Abc_LitIsCompl
(
Gia_ObjFanin1
(
pObj
)
->
Value
)
^
Gia_ObjFaninC1
(
pObj
);
if
(
Phase0
&&
Phase1
)
if
(
Phase0
&&
Phase1
)
Prio
=
(
fGrow
&
1
)
?
Abc_MinInt
(
Prio0
,
Prio1
)
:
Abc_Max
Int
(
Prio0
,
Prio1
);
Prio
=
Abc_Min
Int
(
Prio0
,
Prio1
);
else
if
(
Phase0
&&
!
Phase1
)
else
if
(
Phase0
)
Prio
=
Prio1
;
Prio
=
Prio1
;
else
if
(
!
Phase0
&&
Phase1
)
else
if
(
Phase1
)
Prio
=
Prio0
;
Prio
=
Prio0
;
else
// if ( !Phase0 && !Phase1 )
else
// if ( !Phase0 && !Phase1 )
Prio
=
(
fGrow
&
1
)
?
Abc_MaxInt
(
Prio0
,
Prio1
)
:
Abc_MinInt
(
Prio0
,
Prio1
);
Prio
=
Abc_MaxInt
(
Prio0
,
Prio1
);
pObj
->
Value
=
Abc_Var2Lit
(
Prio
,
Phase0
&
Phase1
);
pObj
->
Value
=
Abc_Var2Lit
(
Prio
,
Phase0
&&
Phase1
);
pObj
->
fPhase
=
0
;
}
}
Gia_ManForEachCo
(
p
,
pObj
,
i
)
Gia_ManForEachCo
(
p
,
pObj
,
i
)
pObj
->
Value
=
Abc_LitNotCond
(
Gia_ObjFanin0
(
pObj
)
->
Value
,
Gia_ObjFaninC0
(
pObj
)
);
pObj
->
Value
=
Abc_LitNotCond
(
Gia_ObjFanin0
(
pObj
)
->
Value
,
Gia_ObjFaninC0
(
pObj
)
);
}
}
void
Bmc_CexCarePropagateFwd
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
int
fGrow
,
Vec_Int_t
*
vPrios
)
void
Bmc_CexCarePropagateFwd
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
Vec_Int_t
*
vPriosIn
,
Vec_Int_t
*
vPriosFf
)
{
{
Gia_Obj_t
*
pObj
,
*
pObj
Ro
,
*
pObjRi
;
Gia_Obj_t
*
pObjRo
,
*
pObjRi
;
int
f
,
i
;
int
i
,
f
,
ValueMax
=
Abc_Var2Lit
(
pCex
->
nPis
*
(
pCex
->
iFrame
+
1
),
0
)
;
Gia_ManConst0
(
p
)
->
Value
=
0
;
Gia_ManConst0
(
p
)
->
Value
=
ValueMax
;
Gia_ManForEachRi
(
p
,
pObj
,
i
)
Gia_ManForEachRi
(
p
,
pObj
Ri
,
i
)
pObj
->
Value
=
0
;
pObj
Ri
->
Value
=
ValueMax
;
Vec_IntClear
(
vPrios
);
Vec_IntClear
(
vPrios
Ff
);
for
(
f
=
0
;
f
<=
pCex
->
iFrame
;
f
++
)
for
(
f
=
0
;
f
<=
pCex
->
iFrame
;
f
++
)
{
{
Gia_ManForEachRiRo
(
p
,
pObjRi
,
pObjRo
,
i
)
Gia_ManForEachRiRo
(
p
,
pObjRi
,
pObjRo
,
i
)
Vec_IntPush
(
vPrios
,
(
pObjRo
->
Value
=
pObjRi
->
Value
)
);
Vec_IntPush
(
vPrios
Ff
,
(
pObjRo
->
Value
=
pObjRi
->
Value
)
);
Bmc_CexCarePropagateFwdOne
(
p
,
pCex
,
f
,
fGrow
);
Bmc_CexCarePropagateFwdOne
(
p
,
pCex
,
f
,
vPriosIn
);
}
}
}
}
/**Function*************************************************************
/**Function*************************************************************
Synopsis [
For
ward propagation.]
Synopsis [
Back
ward propagation.]
Description []
Description []
...
@@ -158,11 +152,11 @@ void Bmc_CexCarePropagateFwd( Gia_Man_t * p, Abc_Cex_t * pCex, int fGrow, Vec_In
...
@@ -158,11 +152,11 @@ void Bmc_CexCarePropagateFwd( Gia_Man_t * p, Abc_Cex_t * pCex, int fGrow, Vec_In
SeeAlso []
SeeAlso []
***********************************************************************/
***********************************************************************/
void
Bmc_CexCarePropagateBwdOne
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
int
f
,
int
fGrow
,
Abc_Cex_t
*
pCexMin
)
void
Bmc_CexCarePropagateBwdOne
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
int
f
,
Abc_Cex_t
*
pCexMin
)
{
{
Gia_Obj_t
*
pObj
;
Gia_Obj_t
*
pObj
,
*
pFan0
,
*
pFan1
;
int
i
,
Phase0
,
Phase1
;
int
i
,
Phase0
,
Phase1
;
Gia_ManForEachC
and
(
p
,
pObj
,
i
)
Gia_ManForEachC
i
(
p
,
pObj
,
i
)
pObj
->
fPhase
=
0
;
pObj
->
fPhase
=
0
;
Gia_ManForEachCo
(
p
,
pObj
,
i
)
Gia_ManForEachCo
(
p
,
pObj
,
i
)
if
(
pObj
->
fPhase
)
if
(
pObj
->
fPhase
)
...
@@ -171,45 +165,37 @@ void Bmc_CexCarePropagateBwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, int fGr
...
@@ -171,45 +165,37 @@ void Bmc_CexCarePropagateBwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, int fGr
{
{
if
(
!
pObj
->
fPhase
)
if
(
!
pObj
->
fPhase
)
continue
;
continue
;
Phase0
=
Abc_LitIsCompl
(
Gia_ObjFanin0
(
pObj
)
->
Value
)
^
Gia_ObjFaninC0
(
pObj
);
pFan0
=
Gia_ObjFanin0
(
pObj
);
Phase1
=
Abc_LitIsCompl
(
Gia_ObjFanin1
(
pObj
)
->
Value
)
^
Gia_ObjFaninC1
(
pObj
);
pFan1
=
Gia_ObjFanin1
(
pObj
);
Phase0
=
Abc_LitIsCompl
(
pFan0
->
Value
)
^
Gia_ObjFaninC0
(
pObj
);
Phase1
=
Abc_LitIsCompl
(
pFan1
->
Value
)
^
Gia_ObjFaninC1
(
pObj
);
if
(
Phase0
&&
Phase1
)
if
(
Phase0
&&
Phase1
)
{
{
Gia_ObjFanin0
(
pObj
)
->
fPhase
=
1
;
pFan0
->
fPhase
=
1
;
Gia_ObjFanin1
(
pObj
)
->
fPhase
=
1
;
pFan1
->
fPhase
=
1
;
}
}
else
if
(
Phase0
&&
!
Phase1
)
else
if
(
Phase0
)
Gia_ObjFanin1
(
pObj
)
->
fPhase
=
1
;
pFan1
->
fPhase
=
1
;
else
if
(
!
Phase0
&&
Phase1
)
else
if
(
Phase1
)
Gia_ObjFanin0
(
pObj
)
->
fPhase
=
1
;
pFan0
->
fPhase
=
1
;
else
// if ( !Phase0 && !Phase1 )
else
// if ( !Phase0 && !Phase1 )
{
{
if
(
Gia_ObjFanin0
(
pObj
)
->
fPhase
||
Gia_ObjFanin1
(
pObj
)
->
fPhase
)
if
(
pFan0
->
fPhase
||
pFan1
->
fPhase
)
continue
;
continue
;
if
(
Gia_ObjIsPi
(
p
,
Gia_ObjFanin0
(
pObj
)
)
)
if
(
Gia_ObjIsPi
(
p
,
pFan0
)
)
Gia_ObjFanin0
(
pObj
)
->
fPhase
=
1
;
pFan0
->
fPhase
=
1
;
else
if
(
Gia_ObjIsPi
(
p
,
Gia_ObjFanin1
(
pObj
)
)
)
else
if
(
Gia_ObjIsPi
(
p
,
pFan1
)
)
Gia_ObjFanin1
(
pObj
)
->
fPhase
=
1
;
pFan1
->
fPhase
=
1
;
// else if ( Gia_ObjIsAnd(
Gia_ObjFanin0(pObj)) && Txs_ObjIsJust(p, Gia_ObjFanin0(pObj)
) )
// else if ( Gia_ObjIsAnd(
pFan0) && Txs_ObjIsJust(p, pFan0
) )
//
Gia_ObjFanin0(pObj)
->fPhase = 1;
//
pFan0
->fPhase = 1;
// else if ( Gia_ObjIsAnd(
Gia_ObjFanin1(pObj)) && Txs_ObjIsJust(p, Gia_ObjFanin1(pObj)
) )
// else if ( Gia_ObjIsAnd(
pFan1) && Txs_ObjIsJust(p, pFan1
) )
//
Gia_ObjFanin1(pObj)
->fPhase = 1;
//
pFan1
->fPhase = 1;
else
else
{
{
if
(
fGrow
&
1
)
if
(
Abc_Lit2Var
(
pFan0
->
Value
)
>
Abc_Lit2Var
(
pFan1
->
Value
)
)
{
pFan0
->
fPhase
=
1
;
if
(
Abc_Lit2Var
(
Gia_ObjFanin0
(
pObj
)
->
Value
)
>=
Abc_Lit2Var
(
Gia_ObjFanin1
(
pObj
)
->
Value
)
)
Gia_ObjFanin0
(
pObj
)
->
fPhase
=
1
;
else
Gia_ObjFanin1
(
pObj
)
->
fPhase
=
1
;
}
else
else
{
pFan1
->
fPhase
=
1
;
if
(
Abc_Lit2Var
(
Gia_ObjFanin0
(
pObj
)
->
Value
)
<=
Abc_Lit2Var
(
Gia_ObjFanin1
(
pObj
)
->
Value
)
)
Gia_ObjFanin0
(
pObj
)
->
fPhase
=
1
;
else
Gia_ObjFanin1
(
pObj
)
->
fPhase
=
1
;
}
}
}
}
}
}
}
...
@@ -217,23 +203,23 @@ void Bmc_CexCarePropagateBwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, int fGr
...
@@ -217,23 +203,23 @@ void Bmc_CexCarePropagateBwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, int fGr
if
(
pObj
->
fPhase
)
if
(
pObj
->
fPhase
)
Abc_InfoSetBit
(
pCexMin
->
pData
,
pCexMin
->
nRegs
+
pCexMin
->
nPis
*
f
+
i
);
Abc_InfoSetBit
(
pCexMin
->
pData
,
pCexMin
->
nRegs
+
pCexMin
->
nPis
*
f
+
i
);
}
}
Abc_Cex_t
*
Bmc_CexCarePropagateBwd
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
Vec_Int_t
*
vPrios
,
int
fGrow
)
Abc_Cex_t
*
Bmc_CexCarePropagateBwd
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
Vec_Int_t
*
vPrios
In
,
Vec_Int_t
*
vPriosFf
)
{
{
Abc_Cex_t
*
pCexMin
;
Abc_Cex_t
*
pCexMin
;
Gia_Obj_t
*
pObj
,
*
pObj
Ro
,
*
pObjRi
;
Gia_Obj_t
*
pObjRo
,
*
pObjRi
;
int
f
,
i
;
int
f
,
i
;
pCexMin
=
Abc_CexAlloc
(
pCex
->
nRegs
,
pCex
->
nPis
,
pCex
->
iFrame
+
1
);
pCexMin
=
Abc_CexAlloc
(
pCex
->
nRegs
,
pCex
->
nPis
,
pCex
->
iFrame
+
1
);
pCexMin
->
iPo
=
pCex
->
iPo
;
pCexMin
->
iPo
=
pCex
->
iPo
;
pCexMin
->
iFrame
=
pCex
->
iFrame
;
pCexMin
->
iFrame
=
pCex
->
iFrame
;
Gia_ManForEachCo
(
p
,
pObj
,
i
)
Gia_ManForEachCo
(
p
,
pObj
Ri
,
i
)
pObj
->
fPhase
=
0
;
pObj
Ri
->
fPhase
=
0
;
for
(
f
=
pCex
->
iFrame
;
f
>=
0
;
f
--
)
for
(
f
=
pCex
->
iFrame
;
f
>=
0
;
f
--
)
{
{
Gia_ManPo
(
p
,
pCex
->
iPo
)
->
fPhase
=
(
int
)(
f
==
pCex
->
iFrame
);
Gia_ManPo
(
p
,
pCex
->
iPo
)
->
fPhase
=
(
int
)(
f
==
pCex
->
iFrame
);
Gia_ManForEachRo
(
p
,
pObj
,
i
)
Gia_ManForEachRo
(
p
,
pObj
Ro
,
i
)
pObj
->
Value
=
Vec_IntEntry
(
vPrios
,
f
*
pCex
->
nRegs
+
i
);
pObj
Ro
->
Value
=
Vec_IntEntry
(
vPriosFf
,
f
*
pCex
->
nRegs
+
i
);
Bmc_CexCarePropagateFwdOne
(
p
,
pCex
,
f
,
fGrow
);
Bmc_CexCarePropagateFwdOne
(
p
,
pCex
,
f
,
vPriosIn
);
Bmc_CexCarePropagateBwdOne
(
p
,
pCex
,
f
,
fGrow
,
pCexMin
);
Bmc_CexCarePropagateBwdOne
(
p
,
pCex
,
f
,
pCexMin
);
Gia_ManForEachRiRo
(
p
,
pObjRi
,
pObjRo
,
i
)
Gia_ManForEachRiRo
(
p
,
pObjRi
,
pObjRo
,
i
)
pObjRi
->
fPhase
=
pObjRo
->
fPhase
;
pObjRi
->
fPhase
=
pObjRo
->
fPhase
;
}
}
...
@@ -265,12 +251,12 @@ Abc_Cex_t * Bmc_CexCareTotal( Abc_Cex_t ** pCexes, int nCexes )
...
@@ -265,12 +251,12 @@ Abc_Cex_t * Bmc_CexCareTotal( Abc_Cex_t ** pCexes, int nCexes )
}
}
return
pCexMin
;
return
pCexMin
;
}
}
Abc_Cex_t
*
Bmc_CexCareMinimizeAig
(
Gia_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
int
fCheck
,
int
fVerbose
)
Abc_Cex_t
*
Bmc_CexCareMinimizeAig
(
Gia_Man_t
*
p
,
int
nPPis
,
Abc_Cex_t
*
pCex
,
int
fCheck
,
int
fVerbose
)
{
{
int
nTryCexes
=
4
;
// belongs to range [1;4]
int
nTryCexes
=
4
;
// belongs to range [1;4]
Abc_Cex_t
*
pCexBest
,
*
pCexMin
[
4
]
=
{
NULL
};
Abc_Cex_t
*
pCexBest
,
*
pCexMin
[
4
]
=
{
NULL
};
int
k
,
nOnesBest
,
nOnesCur
;
int
k
,
f
,
i
,
nOnesBest
,
nOnesCur
,
Counter
=
0
;
Vec_Int_t
*
vPrios
;
Vec_Int_t
*
vPrios
In
,
*
vPriosFf
;
if
(
pCex
->
nPis
!=
Gia_ManPiNum
(
p
)
)
if
(
pCex
->
nPis
!=
Gia_ManPiNum
(
p
)
)
{
{
printf
(
"Given CEX does to have same number of inputs as the AIG.
\n
"
);
printf
(
"Given CEX does to have same number of inputs as the AIG.
\n
"
);
...
@@ -292,30 +278,118 @@ Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fCheck,
...
@@ -292,30 +278,118 @@ Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fCheck,
if
(
fVerbose
)
if
(
fVerbose
)
{
{
printf
(
"Original : "
);
printf
(
"Original : "
);
Bmc_CexPrint
(
pCex
,
Gia_ManPiNum
(
p
),
0
);
Bmc_CexPrint
(
pCex
,
Gia_ManPiNum
(
p
)
-
nPPis
,
0
);
}
}
vPrios
=
Vec_IntAlloc
(
pCex
->
nRegs
*
(
pCex
->
iFrame
+
1
)
);
vPriosIn
=
Vec_IntAlloc
(
pCex
->
nPis
*
(
pCex
->
iFrame
+
1
)
);
vPriosFf
=
Vec_IntAlloc
(
pCex
->
nRegs
*
(
pCex
->
iFrame
+
1
)
);
for
(
k
=
0
;
k
<
nTryCexes
;
k
++
)
for
(
k
=
0
;
k
<
nTryCexes
;
k
++
)
{
{
Bmc_CexCarePropagateFwd
(
p
,
pCex
,
k
,
vPrios
);
Counter
=
0
;
assert
(
Vec_IntSize
(
vPrios
)
==
pCex
->
nRegs
*
(
pCex
->
iFrame
+
1
)
);
Vec_IntFill
(
vPriosIn
,
pCex
->
nPis
*
(
pCex
->
iFrame
+
1
),
0
);
/*
if ( k == 0 )
{
for ( f = 0; f <= pCex->iFrame; f++ )
for ( i = nPPis; i < Gia_ManPiNum(p); i++ )
Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) );
for ( f = 0; f <= pCex->iFrame; f++ )
for ( i = 0; i < nPPis; i++ )
Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) );
}
else if ( k == 1 )
{
for ( f = pCex->iFrame; f >= 0; f-- )
for ( i = nPPis; i < Gia_ManPiNum(p); i++ )
Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) );
for ( f = pCex->iFrame; f >= 0; f-- )
for ( i = 0; i < nPPis; i++ )
Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) );
}
else if ( k == 2 )
{
for ( f = 0; f <= pCex->iFrame; f++ )
for ( i = Gia_ManPiNum(p) - 1; i >= nPPis; i-- )
Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) );
for ( f = 0; f <= pCex->iFrame; f++ )
for ( i = nPPis - 1; i >= 0; i-- )
Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) );
}
else if ( k == 3 )
{
for ( f = pCex->iFrame; f >= 0; f-- )
for ( i = Gia_ManPiNum(p) - 1; i >= nPPis; i-- )
Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) );
for ( f = pCex->iFrame; f >= 0; f-- )
for ( i = nPPis - 1; i >= 0; i-- )
Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) );
}
else assert( 0 );
*/
if
(
k
==
0
)
{
for
(
f
=
pCex
->
iFrame
;
f
>=
0
;
f
--
)
for
(
i
=
nPPis
;
i
<
Gia_ManPiNum
(
p
);
i
++
)
Vec_IntWriteEntry
(
vPriosIn
,
f
*
pCex
->
nPis
+
i
,
Abc_Var2Lit
(
Counter
++
,
Abc_InfoHasBit
(
pCex
->
pData
,
pCex
->
nRegs
+
pCex
->
nPis
*
f
+
i
))
);
for
(
f
=
pCex
->
iFrame
;
f
>=
0
;
f
--
)
for
(
i
=
0
;
i
<
nPPis
;
i
++
)
Vec_IntWriteEntry
(
vPriosIn
,
f
*
pCex
->
nPis
+
i
,
Abc_Var2Lit
(
Counter
++
,
Abc_InfoHasBit
(
pCex
->
pData
,
pCex
->
nRegs
+
pCex
->
nPis
*
f
+
i
))
);
}
else
if
(
k
==
1
)
{
for
(
f
=
pCex
->
iFrame
;
f
>=
0
;
f
--
)
for
(
i
=
nPPis
;
i
<
Gia_ManPiNum
(
p
);
i
++
)
Vec_IntWriteEntry
(
vPriosIn
,
f
*
pCex
->
nPis
+
i
,
Abc_Var2Lit
(
Counter
++
,
Abc_InfoHasBit
(
pCex
->
pData
,
pCex
->
nRegs
+
pCex
->
nPis
*
f
+
i
))
);
for
(
f
=
pCex
->
iFrame
;
f
>=
0
;
f
--
)
for
(
i
=
nPPis
-
1
;
i
>=
0
;
i
--
)
Vec_IntWriteEntry
(
vPriosIn
,
f
*
pCex
->
nPis
+
i
,
Abc_Var2Lit
(
Counter
++
,
Abc_InfoHasBit
(
pCex
->
pData
,
pCex
->
nRegs
+
pCex
->
nPis
*
f
+
i
))
);
}
else
if
(
k
==
2
)
{
for
(
f
=
pCex
->
iFrame
;
f
>=
0
;
f
--
)
for
(
i
=
Gia_ManPiNum
(
p
)
-
1
;
i
>=
nPPis
;
i
--
)
Vec_IntWriteEntry
(
vPriosIn
,
f
*
pCex
->
nPis
+
i
,
Abc_Var2Lit
(
Counter
++
,
Abc_InfoHasBit
(
pCex
->
pData
,
pCex
->
nRegs
+
pCex
->
nPis
*
f
+
i
))
);
for
(
f
=
pCex
->
iFrame
;
f
>=
0
;
f
--
)
for
(
i
=
0
;
i
<
nPPis
;
i
++
)
Vec_IntWriteEntry
(
vPriosIn
,
f
*
pCex
->
nPis
+
i
,
Abc_Var2Lit
(
Counter
++
,
Abc_InfoHasBit
(
pCex
->
pData
,
pCex
->
nRegs
+
pCex
->
nPis
*
f
+
i
))
);
}
else
if
(
k
==
3
)
{
for
(
f
=
pCex
->
iFrame
;
f
>=
0
;
f
--
)
for
(
i
=
Gia_ManPiNum
(
p
)
-
1
;
i
>=
nPPis
;
i
--
)
Vec_IntWriteEntry
(
vPriosIn
,
f
*
pCex
->
nPis
+
i
,
Abc_Var2Lit
(
Counter
++
,
Abc_InfoHasBit
(
pCex
->
pData
,
pCex
->
nRegs
+
pCex
->
nPis
*
f
+
i
))
);
for
(
f
=
pCex
->
iFrame
;
f
>=
0
;
f
--
)
for
(
i
=
nPPis
-
1
;
i
>=
0
;
i
--
)
Vec_IntWriteEntry
(
vPriosIn
,
f
*
pCex
->
nPis
+
i
,
Abc_Var2Lit
(
Counter
++
,
Abc_InfoHasBit
(
pCex
->
pData
,
pCex
->
nRegs
+
pCex
->
nPis
*
f
+
i
))
);
}
else
assert
(
0
);
assert
(
Counter
==
pCex
->
nPis
*
(
pCex
->
iFrame
+
1
)
);
Bmc_CexCarePropagateFwd
(
p
,
pCex
,
vPriosIn
,
vPriosFf
);
assert
(
Vec_IntSize
(
vPriosFf
)
==
pCex
->
nRegs
*
(
pCex
->
iFrame
+
1
)
);
if
(
!
Abc_LitIsCompl
(
Gia_ManPo
(
p
,
pCex
->
iPo
)
->
Value
)
)
if
(
!
Abc_LitIsCompl
(
Gia_ManPo
(
p
,
pCex
->
iPo
)
->
Value
)
)
{
{
printf
(
"Counter-example is invalid.
\n
"
);
printf
(
"Counter-example is invalid.
\n
"
);
Vec_IntFree
(
vPrios
);
Vec_IntFree
(
vPriosIn
);
Vec_IntFree
(
vPriosFf
);
return
NULL
;
return
NULL
;
}
}
pCexMin
[
k
]
=
Bmc_CexCarePropagateBwd
(
p
,
pCex
,
vPrios
,
k
);
pCexMin
[
k
]
=
Bmc_CexCarePropagateBwd
(
p
,
pCex
,
vPrios
In
,
vPriosFf
);
if
(
fVerbose
)
if
(
fVerbose
)
{
{
if
(
(
k
&
1
)
)
if
(
k
==
0
)
printf
(
"Decrease : "
);
printf
(
"PiUp FrUp: "
);
else
else
if
(
k
==
1
)
printf
(
"Increase : "
);
printf
(
"PiUp FrDn: "
);
Bmc_CexPrint
(
pCexMin
[
k
],
Gia_ManPiNum
(
p
),
0
);
else
if
(
k
==
2
)
printf
(
"PiDn FrUp: "
);
else
if
(
k
==
3
)
printf
(
"PiDn FrDn: "
);
else
assert
(
0
);
Bmc_CexPrint
(
pCexMin
[
k
],
Gia_ManPiNum
(
p
)
-
nPPis
,
0
);
}
}
}
}
Vec_IntFree
(
vPrios
);
Vec_IntFree
(
vPriosIn
);
Vec_IntFree
(
vPriosFf
);
// select the best one
// select the best one
pCexBest
=
pCexMin
[
0
];
pCexBest
=
pCexMin
[
0
];
nOnesBest
=
Abc_CexCountOnes
(
pCexMin
[
0
]);
nOnesBest
=
Abc_CexCountOnes
(
pCexMin
[
0
]);
...
@@ -330,12 +404,12 @@ Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fCheck,
...
@@ -330,12 +404,12 @@ Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fCheck,
}
}
if
(
fVerbose
)
if
(
fVerbose
)
{
{
Abc_Cex_t
*
pTotal
=
Bmc_CexCareTotal
(
pCexMin
,
nTryCexes
);
//
Abc_Cex_t * pTotal = Bmc_CexCareTotal( pCexMin, nTryCexes );
printf
(
"Final : "
);
printf
(
"Final : "
);
Bmc_CexPrint
(
pCexBest
,
Gia_ManPiNum
(
p
),
0
);
Bmc_CexPrint
(
pCexBest
,
Gia_ManPiNum
(
p
)
-
nPPis
,
0
);
printf
(
"Total : "
);
//
printf( "Total : " );
Bmc_CexPrint
(
pTotal
,
Gia_ManPiNum
(
p
)
,
0
);
//Bmc_CexPrint( pTotal, Gia_ManPiNum(p) - nPPis
, 0 );
Abc_CexFreeP
(
&
pTotal
);
//
Abc_CexFreeP( &pTotal );
}
}
for
(
k
=
0
;
k
<
nTryCexes
;
k
++
)
for
(
k
=
0
;
k
<
nTryCexes
;
k
++
)
if
(
pCexBest
!=
pCexMin
[
k
]
)
if
(
pCexBest
!=
pCexMin
[
k
]
)
...
@@ -347,10 +421,10 @@ Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fCheck,
...
@@ -347,10 +421,10 @@ Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fCheck,
printf
(
"Counter-example verification succeeded.
\n
"
);
printf
(
"Counter-example verification succeeded.
\n
"
);
return
pCexBest
;
return
pCexBest
;
}
}
Abc_Cex_t
*
Bmc_CexCareMinimize
(
Aig_Man_t
*
p
,
Abc_Cex_t
*
pCex
,
int
fCheck
,
int
fVerbose
)
Abc_Cex_t
*
Bmc_CexCareMinimize
(
Aig_Man_t
*
p
,
int
nPPis
,
Abc_Cex_t
*
pCex
,
int
fCheck
,
int
fVerbose
)
{
{
Gia_Man_t
*
pGia
=
Gia_ManFromAigSimple
(
p
);
Gia_Man_t
*
pGia
=
Gia_ManFromAigSimple
(
p
);
Abc_Cex_t
*
pCexMin
=
Bmc_CexCareMinimizeAig
(
pGia
,
pCex
,
fCheck
,
fVerbose
);
Abc_Cex_t
*
pCexMin
=
Bmc_CexCareMinimizeAig
(
pGia
,
nPPis
,
pCex
,
fCheck
,
fVerbose
);
Gia_ManStop
(
pGia
);
Gia_ManStop
(
pGia
);
return
pCexMin
;
return
pCexMin
;
}
}
...
@@ -382,7 +456,14 @@ void Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, in
...
@@ -382,7 +456,14 @@ void Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, in
printf
(
"Counter-example verification succeeded.
\n
"
);
printf
(
"Counter-example verification succeeded.
\n
"
);
Gia_ManStop
(
pGia
);
Gia_ManStop
(
pGia
);
}
}
/*
{
Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 );
Abc_Cex_t * pCex = Bmc_CexCareMinimize( pAig, 3*Saig_ManPiNum(pAig)/4, pAbc->pCex, 1, 1 );
Aig_ManStop( pAig );
Abc_CexFree( pCex );
}
*/
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
/// END OF FILE ///
...
...
src/sat/bmc/bmcCexTools.c
View file @
f2d096c9
...
@@ -304,10 +304,10 @@ void Bmc_CexBuildNetworkTest( Gia_Man_t * p, Abc_Cex_t * pCex )
...
@@ -304,10 +304,10 @@ void Bmc_CexBuildNetworkTest( Gia_Man_t * p, Abc_Cex_t * pCex )
SeeAlso []
SeeAlso []
***********************************************************************/
***********************************************************************/
void
Bmc_CexPrint
(
Abc_Cex_t
*
pCex
,
int
n
Input
s
,
int
fVerbose
)
void
Bmc_CexPrint
(
Abc_Cex_t
*
pCex
,
int
n
RealPi
s
,
int
fVerbose
)
{
{
int
i
,
k
,
Count
,
iBit
=
pCex
->
nRegs
;
int
i
,
k
,
Count
,
iBit
=
pCex
->
nRegs
;
Abc_CexPrintStatsInputs
(
pCex
,
n
Input
s
);
Abc_CexPrintStatsInputs
(
pCex
,
n
RealPi
s
);
if
(
!
fVerbose
)
if
(
!
fVerbose
)
return
;
return
;
...
@@ -315,7 +315,7 @@ void Bmc_CexPrint( Abc_Cex_t * pCex, int nInputs, int fVerbose )
...
@@ -315,7 +315,7 @@ void Bmc_CexPrint( Abc_Cex_t * pCex, int nInputs, int fVerbose )
{
{
Count
=
0
;
Count
=
0
;
printf
(
"%3d : "
,
i
);
printf
(
"%3d : "
,
i
);
for
(
k
=
0
;
k
<
n
Input
s
;
k
++
)
for
(
k
=
0
;
k
<
n
RealPi
s
;
k
++
)
{
{
Count
+=
Abc_InfoHasBit
(
pCex
->
pData
,
iBit
);
Count
+=
Abc_InfoHasBit
(
pCex
->
pData
,
iBit
);
printf
(
"%d"
,
Abc_InfoHasBit
(
pCex
->
pData
,
iBit
++
)
);
printf
(
"%d"
,
Abc_InfoHasBit
(
pCex
->
pData
,
iBit
++
)
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment