Experiments with multipliers.

This commit is contained in:
Alan Mishchenko 2025-11-27 19:46:16 -08:00
parent 53edce3382
commit 9b0786fe89
7 changed files with 338 additions and 16 deletions

View File

@ -1419,6 +1419,8 @@ typedef struct Gia_ChMan_t_ Gia_ChMan_t;
extern Gia_ChMan_t * Gia_ManDupChoicesStart( Gia_Man_t * pGia );
extern void Gia_ManDupChoicesAdd( Gia_ChMan_t * pMan, Gia_Man_t * pGia );
extern Gia_Man_t * Gia_ManDupChoicesFinish( Gia_ChMan_t * pMan );
extern Vec_Int_t * Gia_ManComputeMffc( Gia_Man_t * p, Vec_Int_t * vLits, Vec_Int_t * vOuts );
extern Gia_Man_t * Gia_ManDupExtractMffc( Gia_Man_t * p, Vec_Int_t * vLits, Vec_Int_t * vAnds, Vec_Int_t * vCos );
/*=== giaEdge.c ==========================================================*/
extern void Gia_ManEdgeFromArray( Gia_Man_t * p, Vec_Int_t * vArray );
extern Vec_Int_t * Gia_ManEdgeToArray( Gia_Man_t * p );

View File

@ -292,8 +292,8 @@ static inline int Gia_CutCompare2( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1 )
}
static inline int Gia_CutCompare( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1 )
{
if ( pCut0->CostF > pCut1->CostF ) return -1;
if ( pCut0->CostF < pCut1->CostF ) return 1;
if ( pCut0->CostF > pCut1->CostF ) return -1;
if ( pCut0->CostF < pCut1->CostF ) return 1;
if ( pCut0->nLeaves < pCut1->nLeaves ) return -1;
if ( pCut0->nLeaves > pCut1->nLeaves ) return 1;
return 0;
@ -1230,7 +1230,7 @@ void Gia_ManComputeCutsCore( Gia_Man_t * pGia, int nCutSize, int nCutNum, int fT
Vec_Wec_t * Gia_ManCompute54Cuts( Gia_Man_t * pGia, int fVerbose )
{
Gia_Sto_t * pSto = Gia_ManMatchCutsInt( pGia, 5, 16, 0, fVerbose );
Gia_Sto_t * pSto = Gia_ManMatchCutsInt( pGia, 5, 8, 0, fVerbose );
Vec_Wec_t * vRes = Vec_WecAlloc( 1000 );
Vec_Int_t * vLevel; int i, k, c, * pCut;
Vec_WecForEachLevel( pSto->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) {

View File

@ -6609,6 +6609,64 @@ Gia_Man_t * Gia_ManDupChoicesFinish( Gia_ChMan_t * p )
return pTemp;
}
/**Function*************************************************************
Synopsis [Extracting MFFC of the nodes supported by a set of literals.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
// collecting internal nodes and outputs in the MFF of a given set of literals
Vec_Int_t * Gia_ManComputeMffc( Gia_Man_t * p, Vec_Int_t * vLits, Vec_Int_t * vOuts )
{
Vec_Int_t * vTfo = Vec_IntAlloc( 100 );
Gia_Obj_t * pObj; int i, Lit;
Vec_IntClear( vOuts );
Gia_ManIncrementTravId( p );
Vec_IntForEachEntry( vLits, Lit, i )
Gia_ObjSetTravIdCurrentId( p, Abc_Lit2Var(Lit) );
Gia_ManForEachAnd( p, pObj, i ) {
if ( Gia_ObjIsTravIdCurrentId(p, i) )
continue;
if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) && Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) )
Gia_ObjSetTravIdCurrentId( p, i ), Vec_IntPush( vTfo, i );
else if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) )
Vec_IntPushUniqueOrder( vOuts, Gia_ObjFaninId0(pObj, i) );
else if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) )
Vec_IntPushUniqueOrder( vOuts, Gia_ObjFaninId1(pObj, i) );
}
Gia_ManForEachCo( p, pObj, i )
if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0p(p, pObj)) )
Vec_IntPushUniqueOrder( vOuts, Gia_ObjFaninId0p(p, pObj) );
Vec_IntTwoFilter( vOuts, vTfo );
return vTfo;
}
// extracting the AIG of the MFFC defined by a given set of literals
Gia_Man_t * Gia_ManDupExtractMffc( Gia_Man_t * p, Vec_Int_t * vLits, Vec_Int_t * vAnds, Vec_Int_t * vCos )
{
Gia_Man_t * pNew;
Gia_Obj_t * pObj;
int i, Lit;
pNew = Gia_ManStart( 5000 );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
pNew->fGiaSimple = 1;
Gia_ManConst0(p)->Value = 0;
Vec_IntForEachEntry( vLits, Lit, i )
Gia_ManObj(p, Abc_Lit2Var(Lit))->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), Abc_LitIsCompl(Lit) );
Gia_ManForEachObjVec( vAnds, p, pObj, i )
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
Gia_ManForEachObjVec( vCos, p, pObj, i )
pObj->Value = Gia_ManAppendCo( pNew, pObj->Value );
return pNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////

View File

@ -726,8 +726,16 @@ Vec_Wrd_t * Gia_ManMulFindSim( Vec_Wrd_t * vSim0, Vec_Wrd_t * vSim1, int fSigned
}
return vRes;
}
void Gia_ManMulFindOutputs( Gia_Man_t * p, Vec_Wec_t * vTerms, int fLits, int fVerbose )
Vec_Wrd_t * Gia_ManMulFindSim2( Vec_Wrd_t * vSim0, Vec_Wrd_t * vSim1, int fSigned )
{
extern word * product_many(word *pInfo1, int nBits1, word *pInfo2, int nBits2, int fSigned );
word * pRes = product_many( Vec_WrdArray(vSim0), Vec_WrdSize(vSim0), Vec_WrdArray(vSim1), Vec_WrdSize(vSim1), fSigned );
return Vec_WrdAllocArray( pRes, Vec_WrdSize(vSim0) + Vec_WrdSize(vSim1) );
}
int Gia_ManMulFindOutputs( Gia_Man_t * p, Vec_Wec_t * vTerms, int fLits, int fVerbose )
{
//abctime clkTotal = Abc_Clock();
int nDetected = 0;
Abc_Random(1);
for ( int m = 0; m < Vec_WecSize(vTerms)/3; m++ ) {
Vec_Int_t * vIn0 = Vec_WecEntry(vTerms, 3*m+0);
@ -735,8 +743,8 @@ void Gia_ManMulFindOutputs( Gia_Man_t * p, Vec_Wec_t * vTerms, int fLits, int fV
Vec_Int_t * vOut = Vec_WecEntry(vTerms, 3*m+2);
Vec_Wrd_t * vSim0 = Vec_WrdStartRandom( Vec_IntSize(vIn0) );
Vec_Wrd_t * vSim1 = Vec_WrdStartRandom( Vec_IntSize(vIn1) );
Vec_Wrd_t * vSimU = Gia_ManMulFindSim( vSim0, vSim1, 0 );
Vec_Wrd_t * vSimS = Gia_ManMulFindSim( vSim0, vSim1, 1 );
Vec_Wrd_t * vSimU = Gia_ManMulFindSim2( vSim0, vSim1, 0 );
Vec_Wrd_t * vSimS = Gia_ManMulFindSim2( vSim0, vSim1, 1 );
Vec_Int_t * vTfo = Gia_ManMulFindTfo( p, vIn0, vIn1, fLits );
Vec_Wrd_t * vSims = Gia_ManMulFindSimCone( p, vIn0, vIn1, vSim0, vSim1, vTfo, fLits );
Vec_Int_t * vOutU = Vec_IntAlloc( 100 );
@ -762,10 +770,14 @@ void Gia_ManMulFindOutputs( Gia_Man_t * p, Vec_Wec_t * vTerms, int fLits, int fV
if ( Vec_IntCountEntry(vOutU, -1) < Vec_IntSize(vOutU) ||
Vec_IntCountEntry(vOutS, -1) < Vec_IntSize(vOutS) )
{
if ( Vec_IntCountEntry(vOutU, -1) < Vec_IntCountEntry(vOutS, -1) )
if ( Vec_IntCountEntry(vOutU, -1) < Vec_IntCountEntry(vOutS, -1) ) {
Vec_IntAppend( vOut, vOutU ), Vec_IntPush(vOut, 0);
else
nDetected = Vec_IntSize(vOutU) - Vec_IntCountEntry(vOutU, -1);
}
else {
Vec_IntAppend( vOut, vOutS ), Vec_IntPush(vOut, 1);
nDetected = Vec_IntSize(vOutS) - Vec_IntCountEntry(vOutS, -1);
}
}
else
{
@ -782,6 +794,8 @@ void Gia_ManMulFindOutputs( Gia_Man_t * p, Vec_Wec_t * vTerms, int fLits, int fV
Vec_IntFree( vOutS );
}
Vec_WecRemoveEmpty( vTerms );
//Abc_PrintTime( 1, "Output detection time", Abc_Clock() - clkTotal );
return nDetected;
}
/**Function*************************************************************
@ -831,11 +845,28 @@ void Gia_ManMulFindPrintSet( Vec_Int_t * vSet, int fLit, int fSkipLast )
{
int i, Temp, Limit = Vec_IntSize(vSet) - fSkipLast;
printf( "{" );
Vec_IntForEachEntryStop( vSet, Temp, i, Limit ) {
if ( Temp == -1 )
printf( "n/a%s", i < Limit-1 ? " ":"" );
else
printf( "%s%d%s", (fLit & Abc_LitIsCompl(Temp)) ? "~":"", fLit ? Abc_Lit2Var(Temp) : Temp, i < Limit-1 ? " ":"" );
if ( Vec_IntSize(vSet) > 16 ) {
Vec_IntForEachEntryStop( vSet, Temp, i, 4 ) {
if ( Temp == -1 )
printf( "n/a%s", i < Limit-1 ? " ":"" );
else
printf( "%s%d%s", (fLit & Abc_LitIsCompl(Temp)) ? "~":"", fLit ? Abc_Lit2Var(Temp) : Temp, i < Limit-1 ? " ":"" );
}
printf( "... " );
Vec_IntForEachEntryStartStop( vSet, Temp, i, Limit-4, Limit ) {
if ( Temp == -1 )
printf( "n/a%s", i < Limit-1 ? " ":"" );
else
printf( "%s%d%s", (fLit & Abc_LitIsCompl(Temp)) ? "~":"", fLit ? Abc_Lit2Var(Temp) : Temp, i < Limit-1 ? " ":"" );
}
}
else {
Vec_IntForEachEntryStop( vSet, Temp, i, Limit ) {
if ( Temp == -1 )
printf( "n/a%s", i < Limit-1 ? " ":"" );
else
printf( "%s%d%s", (fLit & Abc_LitIsCompl(Temp)) ? "~":"", fLit ? Abc_Lit2Var(Temp) : Temp, i < Limit-1 ? " ":"" );
}
}
printf( "}" );
}

View File

@ -7,6 +7,7 @@ SRC += src/misc/util/utilBridge.c \
src/misc/util/utilIsop.c \
src/misc/util/utilLinear.c \
src/misc/util/utilMiniver.c \
src/misc/util/utilMulSim.c \
src/misc/util/utilNam.c \
src/misc/util/utilPrefix.cpp \
src/misc/util/utilPth.c \

230
src/misc/util/utilMulSim.c Normal file
View File

@ -0,0 +1,230 @@
/**CFile****************************************************************
FileName [utilMulSim.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Generating multiplier simulation info.]
Synopsis [Generating multiplier simulation info.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - Feburary 13, 2011.]
Revision [$Id: utilMulSim.c,v 1.00 2011/02/11 00:00:00 alanmi Exp $]
***********************************************************************/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "misc/util/abc_global.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#define SIG_WIDTH 64 // 64 simulation patterns in each signature word
// ----------------------------------------------------------------------
// Core 32-bit-limb big integer unsigned multiply
// ----------------------------------------------------------------------
uint32_t * product(const uint32_t *pArg1, int nInts1,
const uint32_t *pArg2, int nInts2)
{
assert( pArg1 && pArg2 && nInts1 > 0 && nInts2 > 0 );
int nRes = nInts1 + nInts2;
uint32_t *pRes = (uint32_t *)calloc((size_t)nRes, sizeof(uint32_t));
if (!pRes) return NULL;
// Schoolbook multiplication in base 2^32
for (int i = 0; i < nInts1; ++i) {
uint64_t a = pArg1[i];
if (a == 0) continue;
uint64_t carry = 0;
for (int j = 0; j < nInts2; ++j) {
uint64_t t = (uint64_t)pRes[i + j] + a * (uint64_t)pArg2[j] + carry;
pRes[i + j] = (uint32_t)t;
carry = t >> 32;
}
pRes[i + nInts2] = (uint32_t)carry;
}
return pRes;
}
// ----------------------------------------------------------------------
// Bit-matrix helpers: signatures <-> per-pattern 32-bit-limb big ints
// ----------------------------------------------------------------------
static void transpose_signatures_to_pattern(const uint64_t *sigs,
int nBits,
uint32_t *dst,
int nInts,
int patternIdx)
{
memset(dst, 0, (size_t)nInts * sizeof(uint32_t));
for (int bit = 0; bit < nBits; ++bit) {
uint64_t sigWord = sigs[bit];
uint64_t bitVal = (sigWord >> patternIdx) & 1ULL;
if (!bitVal) continue;
int word = bit / 32;
int offset = bit & 31;
dst[word] |= (uint32_t)(1u << offset);
}
}
static void transpose_pattern_to_signatures(const uint32_t *src,
int nIntsRes,
int nBitsRes,
uint64_t *outSigs,
int patternIdx)
{
for (int bit = 0; bit < nBitsRes; ++bit) {
int word = bit / 32;
int offset = bit & 31;
if (word >= nIntsRes)
break;
uint32_t bitVal = (src[word] >> offset) & 1u;
if (bitVal)
outSigs[bit] |= (uint64_t)1ULL << patternIdx;
}
}
// ----------------------------------------------------------------------
// Signed helpers for 32-bit-limb big ints (two's complement on nBits)
// ----------------------------------------------------------------------
static int is_negative(const uint32_t *x, int nBits)
{
int bitPos = nBits - 1;
int word = bitPos / 32;
int offset = bitPos & 31;
return (x[word] >> offset) & 1u;
}
static void mask_to_nBits(uint32_t *x, int nInts, int nBits)
{
if (nBits <= 0) {
for (int i = 0; i < nInts; ++i)
x[i] = 0;
return;
}
int lastWord = (nBits - 1) / 32; // index of last used word
int usedBitsInLast = nBits - lastWord * 32; // 1..32
// Zero any words above the last used word
for (int i = lastWord + 1; i < nInts; ++i)
x[i] = 0;
// If nBits is not a multiple of 32, mask off the high bits of last word
if (usedBitsInLast < 32) {
uint32_t mask = ((uint32_t)1u << usedBitsInLast) - 1u;
x[lastWord] &= mask;
}
}
static void twos_complement_inplace(uint32_t *x, int nInts, int nBits)
{
// Invert
for (int i = 0; i < nInts; ++i)
x[i] = ~x[i];
mask_to_nBits(x, nInts, nBits);
// Add 1
uint64_t carry = 1;
for (int i = 0; i < nInts; ++i) {
uint64_t sum = (uint64_t)x[i] + carry;
x[i] = (uint32_t)sum;
carry = sum >> 32;
if (!carry)
break;
}
mask_to_nBits(x, nInts, nBits);
}
// ----------------------------------------------------------------------
// product_many: unsigned and signed (two's-complement) versions
// ----------------------------------------------------------------------
uint64_t * product_many_unsigned(uint64_t *pInfo1, int nBits1,
uint64_t *pInfo2, int nBits2)
{
assert( pInfo1 && pInfo2 && nBits1 > 0 && nBits2 > 0 );
int nInts1 = (nBits1 + 31) / 32;
int nInts2 = (nBits2 + 31) / 32;
int nBitsRes = nBits1 + nBits2;
int nIntsRes = nInts1 + nInts2;
uint64_t *outSigs = (uint64_t *)calloc((size_t)nBitsRes, sizeof(uint64_t));
if (!outSigs) return NULL;
uint32_t *tmp1 = (uint32_t *)calloc((size_t)nInts1, sizeof(uint32_t));
uint32_t *tmp2 = (uint32_t *)calloc((size_t)nInts2, sizeof(uint32_t));
assert( tmp1 && tmp2 );
for (int pattern = 0; pattern < SIG_WIDTH; ++pattern) {
transpose_signatures_to_pattern(pInfo1, nBits1, tmp1, nInts1, pattern);
transpose_signatures_to_pattern(pInfo2, nBits2, tmp2, nInts2, pattern);
uint32_t *tmpRes = product(tmp1, nInts1, tmp2, nInts2); assert( tmpRes );
transpose_pattern_to_signatures(tmpRes, nIntsRes, nBitsRes, outSigs, pattern);
free(tmpRes);
}
free(tmp1);
free(tmp2);
return outSigs;
}
uint64_t * product_many_signed(uint64_t *pInfo1, int nBits1,
uint64_t *pInfo2, int nBits2)
{
assert( pInfo1 && pInfo2 && nBits1 > 0 && nBits2 > 0 );
int nInts1 = (nBits1 + 31) / 32;
int nInts2 = (nBits2 + 31) / 32;
int nBitsRes = nBits1 + nBits2;
int nIntsRes = nInts1 + nInts2;
uint64_t *outSigs = (uint64_t *)calloc((size_t)nBitsRes, sizeof(uint64_t));
if (!outSigs) return NULL;
uint32_t *op1 = (uint32_t *)calloc((size_t)nInts1, sizeof(uint32_t));
uint32_t *op2 = (uint32_t *)calloc((size_t)nInts2, sizeof(uint32_t));
assert( op1 && op2 );
for (int pattern = 0; pattern < SIG_WIDTH; ++pattern) {
transpose_signatures_to_pattern(pInfo1, nBits1, op1, nInts1, pattern);
transpose_signatures_to_pattern(pInfo2, nBits2, op2, nInts2, pattern);
int neg1 = is_negative(op1, nBits1);
int neg2 = is_negative(op2, nBits2);
int negRes = neg1 ^ neg2;
if (neg1) twos_complement_inplace(op1, nInts1, nBits1);
if (neg2) twos_complement_inplace(op2, nInts2, nBits2);
uint32_t *tmpRes = product(op1, nInts1, op2, nInts2); assert( tmpRes );
if (negRes)
twos_complement_inplace(tmpRes, nIntsRes, nBitsRes);
else
mask_to_nBits(tmpRes, nIntsRes, nBitsRes);
transpose_pattern_to_signatures(tmpRes, nIntsRes, nBitsRes, outSigs, pattern);
free(tmpRes);
}
free(op1);
free(op2);
return outSigs;
}
word * product_many(word *pInfo1, int nBits1, word *pInfo2, int nBits2, int fSigned )
{
if ( fSigned )
return (word *)product_many_signed((uint64_t *)pInfo1, nBits1, (uint64_t *)pInfo2, nBits2);
else
return (word *)product_many_unsigned((uint64_t *)pInfo1, nBits1, (uint64_t *)pInfo2, nBits2);
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

View File

@ -1947,16 +1947,16 @@ static inline int Vec_IntTwoRemove( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
/**Function*************************************************************
Synopsis [Returns the result of merging the two vectors.]
Synopsis [Keeps only those entries in vArr1, which are in vArr2.]
Description [Keeps only those entries of vArr1, which are in vArr2.]
Description [Assumes that the vectors are sorted in the increasing order.]
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntTwoMerge1( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
static inline void Vec_IntTwoFilter( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
{
int * pBeg = vArr1->pArray;
int * pBeg1 = vArr1->pArray;