Experiments with LUT mapping.

This commit is contained in:
Alan Mishchenko 2025-11-17 21:37:51 -08:00
parent b319f57dde
commit 309282601e
3 changed files with 78 additions and 125 deletions

View File

@ -1583,11 +1583,11 @@ void Gia_AigerWriteS( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, in
{
unsigned char CellId = (unsigned char)Vec_StrEntry(p->vConfigs2, i);
if ( CellId == 0 )
i += 4; // 1 byte CellId + 2 bytes truth table + 1 padding
i += 7; // 1 byte CellId + 4 bytes mapping + 2 bytes truth table
else if ( CellId == 1 )
i += 12; // 1 byte CellId + 4 bytes mapping + 4 bytes truth tables + 3 padding
i += 12; // 1 byte CellId + 7 bytes mapping + 4 bytes truth tables
else if ( CellId == 2 )
i += 12; // 1 byte CellId + 5 bytes mapping + 4 bytes truth tables + 2 padding
i += 14; // 1 byte CellId + 9 bytes mapping + 4 bytes truth tables
else
assert( 0 ); // Unknown cell type
nInstances++;
@ -1619,15 +1619,15 @@ void Gia_AigerWriteS( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, in
// Write cell type 0 (LUT4)
Gia_FileWriteBufferSize( pFile, 0 ); // CellId
fwrite( pCell0, 1, strlen(pCell0) + 1, pFile );
Gia_FileWriteBufferSize( pFile, 4 ); // 1 byte CellId + 2 bytes truth table, rounded to 4
Gia_FileWriteBufferSize( pFile, 7 ); // 1 byte CellId + 4 bytes mapping + 2 bytes truth table
// Write cell type 1 (S44)
Gia_FileWriteBufferSize( pFile, 1 ); // CellId
fwrite( pCell1, 1, strlen(pCell1) + 1, pFile );
Gia_FileWriteBufferSize( pFile, 12 ); // 1 byte CellId + 4 bytes mapping + 4 bytes truth tables, rounded to 12
Gia_FileWriteBufferSize( pFile, 12 ); // 1 byte CellId + 7 bytes mapping + 4 bytes truth tables
// Write cell type 2 (9-input)
Gia_FileWriteBufferSize( pFile, 2 ); // CellId
fwrite( pCell2, 1, strlen(pCell2) + 1, pFile );
Gia_FileWriteBufferSize( pFile, 12 ); // 1 byte CellId + 5 bytes mapping + 4 bytes truth tables (LUT4s only), rounded to 12
Gia_FileWriteBufferSize( pFile, 14 ); // 1 byte CellId + 9 bytes mapping + 4 bytes truth tables
// Write total instances
Gia_FileWriteBufferSize( pFile, nInstances );
// Write instance data as raw bytes

View File

@ -2016,73 +2016,73 @@ void Gia_ManConfigPrint( word Truth4, word z, int nLeaves )
***********************************************************************/
void Gia_ManFromIfGetConfig2( Vec_Str_t * vConfigs2, If_Man_t * pIfMan, word * pTruth, int nLeaves )
{
int i, CellId, nBytes;
int i, CellId;
int startPos = Vec_StrSize(vConfigs2);
// Determine cell type based on the number of leaves and configuration
if ( nLeaves <= 4 )
if ( nLeaves <= 4 ) // 7 bytes = 1 byte CellId + 4 bytes mapping + 2 bytes truth table
{
// Cell type 0: Simple LUT4
CellId = 0;
nBytes = 3; // 1 byte CellId + 2 bytes truth table (16 bits)
// Write CellId
Vec_StrPush( vConfigs2, (char)CellId );
// Write mapping
for ( i = 0; i < nLeaves; i++ )
Vec_StrPush( vConfigs2, 2+i );
for ( ; i < 4; i++ )
Vec_StrPush( vConfigs2, 0 );
// Write truth table (16 bits for LUT4)
word Truth = pTruth[0];
Vec_StrPush( vConfigs2, (char)(Truth & 0xFF) );
Vec_StrPush( vConfigs2, (char)((Truth >> 8) & 0xFF) );
// Pad to 4-byte boundary
while ( (Vec_StrSize(vConfigs2) - startPos) % 4 != 0 )
Vec_StrPush( vConfigs2, 0 );
//Gia_ManConfigPrint( Truth, 0, pCutBest->nLeaves );
Vec_StrPush( vConfigs2, (char)(Truth & 0xFF) );
assert( startPos + 7 == Vec_StrSize(vConfigs2) );
//Gia_ManConfigPrint( Truth, 0, nLeaves );
}
else
else // 12 bytes = 1 byte CellId + 7 bytes mapping + 4 bytes truth tables
{
word z = If_CutPerformDeriveJ( pIfMan, (unsigned *)pTruth, nLeaves, nLeaves, NULL, 1 );
//Gia_ManConfigPrint( 0, z, pCutBest->nLeaves );
//Gia_ManConfigPrint( 0, z, nLeaves );
if ( ((z >> 63) & 1) == 0 )
{
CellId = 1;
unsigned char mappingBytes[4] = {0};
// Write CellId
Vec_StrPush( vConfigs2, (char)CellId );
// Write input mappings for first LUT4 (4 inputs)
// Write input mapping
for ( i = 0; i < 4; i++ )
{
int v = (int)((z >> (16 + (i << 2))) & 7);
if ( v == 6 && nLeaves == 5 )
mappingBytes[i / 2] |= (0 << ((i % 2) * 4)); // constant 0
Vec_StrPush( vConfigs2, 0 );
else
mappingBytes[i / 2] |= ((v+2) << ((i % 2) * 4)); // leaf v (direct mapping)
Vec_StrPush( vConfigs2, 2+v );
}
Vec_StrPush( vConfigs2, (char)mappingBytes[0] );
Vec_StrPush( vConfigs2, (char)mappingBytes[1] );
// Write input mappings for second LUT4 (4 inputs)
mappingBytes[0] = mappingBytes[1] = 0;
int iSpecial = -1;
for ( i = 0; i < 4; i++ )
{
int v = (int)((z >> (48 + (i << 2))) & 7);
if ( v == 6 && nLeaves == 5 )
mappingBytes[i / 2] |= (0 << ((i % 2) * 4)); // constant 0
Vec_StrPush( vConfigs2, 0 );
else if ( v != 7 )
Vec_StrPush( vConfigs2, 2+v );
else if ( v == 7 )
mappingBytes[i / 2] |= ((7+2) << ((i % 2) * 4)); // output of first LUT at index N+2 where N=7
else
mappingBytes[i / 2] |= ((v+2) << ((i % 2) * 4)); // leaf v (direct mapping)
iSpecial = i;
}
Vec_StrPush( vConfigs2, (char)mappingBytes[0] );
Vec_StrPush( vConfigs2, (char)mappingBytes[1] );
// Transform the truth table
assert( iSpecial >= 0 );
word Truth = (z >> 32) & 0xFFFF;
Truth = Abc_Tt6Stretch( Truth, 4 );
for ( int v = iSpecial; v < 3; v++ )
Truth = Abc_Tt6SwapAdjacent( Truth, v );
// Write truth tables
word Truth1 = z & 0xFFFF;
word Truth2 = (z >> 32) & 0xFFFF;
Vec_StrPush( vConfigs2, (char)(Truth1 & 0xFF) );
//word Truth2 = (z >> 32) & 0xFFFF;
word Truth2 = Truth & 0xFFFF;
Vec_StrPush( vConfigs2, (char)((Truth1 >> 8) & 0xFF) );
Vec_StrPush( vConfigs2, (char)(Truth2 & 0xFF) );
Vec_StrPush( vConfigs2, (char)(Truth1 & 0xFF) );
Vec_StrPush( vConfigs2, (char)((Truth2 >> 8) & 0xFF) );
// Pad to 4-byte boundary
while ( (Vec_StrSize(vConfigs2) - startPos) % 4 != 0 )
Vec_StrPush( vConfigs2, 0 );
Vec_StrPush( vConfigs2, (char)(Truth2 & 0xFF) );
assert( startPos + 12 == Vec_StrSize(vConfigs2) );
}
else
else // 14 bytes = 1 byte CellId + 9 bytes mapping + 4 bytes truth tables
{
CellId = 2;
int Pla2Var[9];
@ -2090,39 +2090,22 @@ void Gia_ManFromIfGetConfig2( Vec_Str_t * vConfigs2, If_Man_t * pIfMan, word * p
If_PermUnpack( (unsigned)(z >> 32), Pla2Var );
// Write CellId
Vec_StrPush( vConfigs2, (char)CellId );
// Write input mappings (9 inputs, 4 bits each, packed)
unsigned char mappingByte = 0;
int bitPos = 0;
// Write input mapping
for ( i = 0; i < 9; i++ )
{
int v;
if ( Pla2Var[i] == 9 ) // constant 0
v = 0;
else // leaf index
v = Pla2Var[i] + 2;
if ( bitPos == 0 ) {
mappingByte = v & 0xF;
bitPos = 4;
}
else {
mappingByte |= (v & 0xF) << 4;
Vec_StrPush( vConfigs2, (char)mappingByte );
bitPos = 0;
}
}
// Push last byte if needed
if ( bitPos != 0 )
Vec_StrPush( vConfigs2, (char)mappingByte );
if ( Pla2Var[i] == 9 )
Vec_StrPush( vConfigs2, 0 );
else
Vec_StrPush( vConfigs2, Pla2Var[i] + 2 );
}
// Write truth tables for the two LUT4s only (MUX is structural, not a LUT)
word Truth1 = z & 0xFFFF;
word Truth2 = (z >> 16) & 0xFFFF;
Vec_StrPush( vConfigs2, (char)(Truth1 & 0xFF) );
Vec_StrPush( vConfigs2, (char)((Truth1 >> 8) & 0xFF) );
Vec_StrPush( vConfigs2, (char)(Truth2 & 0xFF) );
Vec_StrPush( vConfigs2, (char)(Truth1 & 0xFF) );
Vec_StrPush( vConfigs2, (char)((Truth2 >> 8) & 0xFF) );
// Pad to 4-byte boundary
while ( (Vec_StrSize(vConfigs2) - startPos) % 4 != 0 )
Vec_StrPush( vConfigs2, 0 );
Vec_StrPush( vConfigs2, (char)(Truth2 & 0xFF) );
assert( startPos + 14 == Vec_StrSize(vConfigs2) );
}
}
}

View File

@ -911,12 +911,15 @@ void If_ManConfigPrint( unsigned char * pConfigData, int nLeaves )
printf( "[%4d] ", Count++ ); // Print instance number
if ( CellId == 0 )
{
assert( nLeaves <= 4 );
// Extract 16-bit truth table
word Truth = ((word)pConfigData[2] << 8) | pConfigData[1];
word Truth = ((word)pConfigData[5] << 8) | pConfigData[6];
printf( "%04lX{", (unsigned long)Truth );
// Print as simple {abcd} since it's just a direct LUT4
for ( i = 0; i < nLeaves && i < 4; i++ )
for ( i = 0; i < nLeaves; i++ )
printf( "%c", 'a' + i );
for ( ; i < 4; i++ )
printf( "%c", '0' );
printf( "}" );
// Pad with spaces if less than 4 inputs
for ( i = nLeaves; i < 4; i++ )
@ -926,11 +929,11 @@ void If_ManConfigPrint( unsigned char * pConfigData, int nLeaves )
else if ( CellId == 1 )
{
// First LUT4
word Truth1 = ((word)pConfigData[6] << 8) | pConfigData[5];
word Truth1 = ((word)pConfigData[8] << 8) | pConfigData[9];
printf( "h=%04lX{", (unsigned long)Truth1 );
for ( i = 0; i < 4; i++ )
{
int v = (pConfigData[1 + i/2] >> ((i%2) * 4)) & 0xF;
int v = pConfigData[1+i];
if ( v == 0 )
printf( "0");
else if ( v == 1 )
@ -942,11 +945,11 @@ void If_ManConfigPrint( unsigned char * pConfigData, int nLeaves )
}
printf( "} ");
// Second LUT4
word Truth2 = ((word)pConfigData[8] << 8) | pConfigData[7];
word Truth2 = ((word)pConfigData[10] << 8) | pConfigData[11];
printf( "i=%04lX{", (unsigned long)Truth2 );
for ( i = 0; i < 4; i++ )
for ( i = 4; i < 7; i++ )
{
int v = (pConfigData[3 + i/2] >> ((i%2) * 4)) & 0xF;
int v = pConfigData[1+i];
if ( v == 0 )
printf( "0");
else if ( v == 1 )
@ -958,32 +961,16 @@ void If_ManConfigPrint( unsigned char * pConfigData, int nLeaves )
else
printf( "?");
}
printf( "} [Cell %d, %d leaves]\n", CellId, nLeaves );
printf( "h} [Cell %d, %d leaves]\n", CellId, nLeaves );
}
else if ( CellId == 2 )
{
// Extract 9 input mappings
int inputs[9];
int bitPos = 0;
for ( i = 0; i < 9; i++ )
{
if ( bitPos == 0 )
{
inputs[i] = pConfigData[1 + i/2] & 0xF;
bitPos = 4;
}
else
{
inputs[i] = (pConfigData[1 + i/2] >> 4) & 0xF;
bitPos = 0;
}
}
// First LUT4
word Truth1 = ((word)pConfigData[7] << 8) | pConfigData[6];
word Truth1 = ((word)pConfigData[10] << 8) | pConfigData[11];
printf( "j=%04lX{", (unsigned long)Truth1 );
for ( i = 0; i < 4; i++ )
{
int v = inputs[i];
int v = pConfigData[1+i];
if ( v == 0 )
printf( "0");
else if ( v == 1 )
@ -995,11 +982,11 @@ void If_ManConfigPrint( unsigned char * pConfigData, int nLeaves )
}
printf( "} ");
// Second LUT4
word Truth2 = ((word)pConfigData[9] << 8) | pConfigData[8];
word Truth2 = ((word)pConfigData[12] << 8) | pConfigData[13];
printf( "k=%04lX{", (unsigned long)Truth2 );
for ( i = 4; i < 8; i++ )
{
int v = inputs[i];
int v = pConfigData[1+i];
if ( v == 0 )
printf( "0");
else if ( v == 1 )
@ -1012,7 +999,7 @@ void If_ManConfigPrint( unsigned char * pConfigData, int nLeaves )
printf( "} ");
// final node
printf( "l=<");
int v = inputs[8];
int v = pConfigData[1+8];
if ( v == 0 )
printf( "0");
else if ( v == 1 )
@ -1087,11 +1074,11 @@ void * If_ManDeriveGiaFromCells2( void * pGia )
if ( CellId == 0 )
{
// Extract 16-bit truth table
word Truth = ((word)pConfigData[2] << 8) | pConfigData[1];
word Truth = ((word)pConfigData[5] << 8) | pConfigData[6];
Truth = Abc_Tt6Stretch( Truth, 4 );
extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );
Gia_ManObj(p, iLut)->Value = Kit_TruthToGia( pNew, (unsigned *)&Truth, Vec_IntSize(vLeaves), vCover, vLeaves, 1 );
bytePos += 4; // 1 byte CellId + 2 bytes truth table + 1 padding
bytePos += 7; // 1 byte CellId + 4 bytes mapping + 2 bytes truth table
}
else if ( CellId == 1 )
{
@ -1101,7 +1088,7 @@ void * If_ManDeriveGiaFromCells2( void * pGia )
Vec_IntClear( vLeavesTemp );
for ( i = 0; i < 4; i++ )
{
int v = (pConfigData[1 + i/2] >> ((i%2) * 4)) & 0xF;
int v = pConfigData[1+i];
if ( v == 0 )
Vec_IntPush( vLeavesTemp, 0 ); // constant 0
else if ( v == 1 )
@ -1111,58 +1098,41 @@ void * If_ManDeriveGiaFromCells2( void * pGia )
else
assert( 0 ); // Invalid value
}
word Truth1 = ((word)pConfigData[6] << 8) | pConfigData[5];
word Truth1 = ((word)pConfigData[8] << 8) | pConfigData[9];
Truth1 = Abc_Tt6Stretch( Truth1, 4 );
extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );
iObjLit1 = Kit_TruthToGia( pNew, (unsigned *)&Truth1, Vec_IntSize(vLeavesTemp), vCover, vLeavesTemp, 1 );
// Second LUT4 - extract inputs and truth table
Vec_IntClear( vLeavesTemp );
for ( i = 0; i < 4; i++ )
for ( i = 4; i < 7; i++ )
{
int v = (pConfigData[3 + i/2] >> ((i%2) * 4)) & 0xF;
int v = pConfigData[1+i];
if ( v == 0 )
Vec_IntPush( vLeavesTemp, 0 ); // constant 0
else if ( v == 1 )
Vec_IntPush( vLeavesTemp, 1 ); // constant 1
else if ( v >= 2 && v < 2 + Vec_IntSize(vLeaves) )
Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, v - 2) ); // leaf (v-2)
else if ( v == 9 ) // N+2 where N=7 (number of S44 inputs)
Vec_IntPush( vLeavesTemp, iObjLit1 ); // output of first LUT (internal connection)
else
assert( 0 ); // Invalid value
}
word Truth2 = ((word)pConfigData[8] << 8) | pConfigData[7];
Vec_IntPush( vLeavesTemp, iObjLit1 ); // output of first LUT (internal connection)
word Truth2 = ((word)pConfigData[10] << 8) | pConfigData[11];
Truth2 = Abc_Tt6Stretch( Truth2, 4 );
iObjLit2 = Kit_TruthToGia( pNew, (unsigned *)&Truth2, Vec_IntSize(vLeavesTemp), vCover, vLeavesTemp, 1 );
Gia_ManObj(p, iLut)->Value = iObjLit2;
Vec_IntFree( vLeavesTemp );
bytePos += 12; // 1 byte CellId + 4 bytes mapping + 4 bytes truth tables + 3 padding
bytePos += 12; // 1 byte CellId + 7 bytes mapping + 4 bytes truth tables
}
else if ( CellId == 2 )
{
Vec_Int_t * vLeavesTemp = Vec_IntAlloc( 4 );
int iObjLit1, iObjLit2, iObjLit3;
// Extract 9 input mappings (4 bits each, packed)
int inputs[9];
int bitPos = 0;
for ( i = 0; i < 9; i++ )
{
if ( bitPos == 0 )
{
inputs[i] = pConfigData[1 + i/2] & 0xF;
bitPos = 4;
}
else
{
inputs[i] = (pConfigData[1 + i/2] >> 4) & 0xF;
bitPos = 0;
}
}
// First LUT4 (inputs 0-3)
Vec_IntClear( vLeavesTemp );
for ( i = 0; i < 4; i++ )
{
int v = inputs[i];
int v = pConfigData[1+i];
if ( v == 0 )
Vec_IntPush( vLeavesTemp, 0 ); // constant 0
else if ( v == 1 )
@ -1172,7 +1142,7 @@ void * If_ManDeriveGiaFromCells2( void * pGia )
else
assert( 0 ); // Invalid value
}
word Truth1 = ((word)pConfigData[7] << 8) | pConfigData[6];
word Truth1 = ((word)pConfigData[10] << 8) | pConfigData[11];
Truth1 = Abc_Tt6Stretch( Truth1, 4 );
extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );
iObjLit1 = Kit_TruthToGia( pNew, (unsigned *)&Truth1, Vec_IntSize(vLeavesTemp), vCover, vLeavesTemp, 1 );
@ -1180,7 +1150,7 @@ void * If_ManDeriveGiaFromCells2( void * pGia )
Vec_IntClear( vLeavesTemp );
for ( i = 4; i < 8; i++ )
{
int v = inputs[i];
int v = pConfigData[1+i];
if ( v == 0 )
Vec_IntPush( vLeavesTemp, 0 ); // constant 0
else if ( v == 1 )
@ -1190,12 +1160,12 @@ void * If_ManDeriveGiaFromCells2( void * pGia )
else
assert( 0 ); // Invalid value
}
word Truth2 = ((word)pConfigData[9] << 8) | pConfigData[8];
word Truth2 = ((word)pConfigData[12] << 8) | pConfigData[13];
Truth2 = Abc_Tt6Stretch( Truth2, 4 );
iObjLit2 = Kit_TruthToGia( pNew, (unsigned *)&Truth2, Vec_IntSize(vLeavesTemp), vCover, vLeavesTemp, 1 );
// MUX (select is input 8) - structural implementation
int iSelectLit;
int v = inputs[8];
int v = pConfigData[1+8];
if ( v == 0 )
iSelectLit = 0; // constant 0 select
else if ( v == 1 )
@ -1207,7 +1177,7 @@ void * If_ManDeriveGiaFromCells2( void * pGia )
iObjLit3 = Gia_ManHashMux( pNew, iSelectLit, iObjLit2, iObjLit1 );
Gia_ManObj(p, iLut)->Value = iObjLit3;
Vec_IntFree( vLeavesTemp );
bytePos += 12; // 1 byte CellId + 5 bytes mapping + 4 bytes truth tables + 2 padding
bytePos += 14; // 1 byte CellId + 9 bytes mapping + 4 bytes truth tables
}
else
{