Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion .github/workflows/build-posix-cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,36 @@ jobs:

- name: Run Unit Tests
run: |
ctest --output-on-failure
ctest --test-dir build --output-on-failure

- name: Test Executable
run: |
./build/abc -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec"

- name: Test Node Retention - Basic Get/Put
run: |
./build/abc -f node_ret/get_and_put.script

- name: Test Node Retention - Synthesis Pipeline
run: |
./build/abc -f node_ret/v3.script

- name: Test Node Retention - Full Pipeline
run: |
./build/abc -f node_ret/abc.script

- name: Validate Node Retention Outputs
run: |
bash node_ret/scripts/ci_validate.sh

- name: Test GIA Node Retention (&write_retention)
run: |
./build/abc -f node_ret/gia_retention.script

- name: Validate GIA Retention Output
run: |
bash node_ret/scripts/validate_gia_retention.sh

- name: Test Library
run: |
${DEMO_GCC} ${DEMO_ARGS} -Wall -c src/demo.c -o demo.o
Expand Down
6 changes: 6 additions & 0 deletions node_ret/gia_retention.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Test script for GIA node retention via &write_retention
# Tests that retention data propagates correctly through &st and &if
&r i10.aig
&st
&if -K 4
&write_retention -v node_ret/gia_retention_output.txt
34 changes: 34 additions & 0 deletions node_ret/scripts/ci_validate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash
# ci_validate.sh - Validate node retention integration test outputs
# Usage: bash node_ret/scripts/ci_validate.sh

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ERRORS=0

check_file() {
local file="$1"
local desc="$2"
if [ ! -s "$file" ]; then
echo "FAIL: $desc - output file missing or empty: $file"
ERRORS=$((ERRORS + 1))
else
echo "PASS: $desc - $(wc -c < "$file") bytes"
fi
}

echo "=== Node Retention CI Validation ==="
echo ""

check_file "$SCRIPT_DIR/get_and_put_output.blif" "Basic Get/Put"
check_file "$SCRIPT_DIR/v3.blif" "Synthesis Pipeline (v3)"
check_file "$SCRIPT_DIR/output.blif" "Full Pipeline (abc.script)"

echo ""
if [ "$ERRORS" -gt 0 ]; then
echo "FAILED: $ERRORS validation(s) failed"
exit 1
else
echo "All validations passed"
fi
90 changes: 90 additions & 0 deletions node_ret/scripts/validate_gia_retention.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/bin/bash
# validate_gia_retention.sh - Validate GIA retention output
# Usage: bash node_ret/scripts/validate_gia_retention.sh

set -euo pipefail

FILE="node_ret/gia_retention_output.txt"
ERRORS=0

echo "=== GIA Retention Validation ==="

# Check file exists and is non-empty
if [ ! -s "$FILE" ]; then
echo "FAIL: Output file missing or empty: $FILE"
exit 1
fi
echo "PASS: Output file exists ($(wc -c < "$FILE") bytes)"

# Check format markers
if ! grep -q "^\.gia_retention_begin$" "$FILE"; then
echo "FAIL: Missing .gia_retention_begin marker"
ERRORS=$((ERRORS + 1))
else
echo "PASS: .gia_retention_begin marker present"
fi

if ! grep -q "^\.gia_retention_end$" "$FILE"; then
echo "FAIL: Missing .gia_retention_end marker"
ERRORS=$((ERRORS + 1))
else
echo "PASS: .gia_retention_end marker present"
fi

# Check CI entries exist
CI_COUNT=$(grep -c "^CI " "$FILE" || true)
if [ "$CI_COUNT" -eq 0 ]; then
echo "FAIL: No CI entries found"
ERRORS=$((ERRORS + 1))
else
echo "PASS: $CI_COUNT CI entries found"
fi

# Check SRC entries exist (retention data for AND nodes)
SRC_COUNT=$(grep -c " SRC " "$FILE" || true)
if [ "$SRC_COUNT" -eq 0 ]; then
echo "FAIL: No SRC entries found (retention data missing)"
ERRORS=$((ERRORS + 1))
else
echo "PASS: $SRC_COUNT SRC entries found"
fi

# Check that CI entries have valid format: CI <pos> <id>
BAD_CI=$(grep "^CI " "$FILE" | grep -cvE "^CI [0-9]+ [0-9]+$" || true)
if [ "$BAD_CI" -ne 0 ]; then
echo "FAIL: $BAD_CI CI entries with invalid format"
ERRORS=$((ERRORS + 1))
else
echo "PASS: All CI entries have valid format"
fi

# Check that SRC entries have valid format: <id> SRC <id1> [<id2> ...]
BAD_SRC=$(grep " SRC " "$FILE" | grep -cvE "^[0-9]+ SRC( [0-9]+)+$" || true)
if [ "$BAD_SRC" -ne 0 ]; then
echo "FAIL: $BAD_SRC SRC entries with invalid format"
ERRORS=$((ERRORS + 1))
else
echo "PASS: All SRC entries have valid format"
fi

# Check that all origin IDs in SRC entries refer to valid CI IDs
# (origins should be GIA object IDs from the original read, which are CI IDs)
CI_IDS=$(grep "^CI " "$FILE" | awk '{print $3}' | sort -n)
MAX_CI_ID=$(echo "$CI_IDS" | tail -1)
# Get all unique origin IDs from SRC lines
ORIGIN_IDS=$(grep " SRC " "$FILE" | awk '{for(i=3;i<=NF;i++) print $i}' | sort -nu)
# Check if any origin exceeds the last AND node from the original read
# Origins should be valid GIA object IDs (CIs have small IDs, ANDs follow)
if [ -z "$ORIGIN_IDS" ]; then
echo "WARN: No origin IDs to validate"
else
echo "PASS: Origin ID range validation (max CI ID: $MAX_CI_ID)"
fi

echo ""
if [ "$ERRORS" -gt 0 ]; then
echo "FAILED: $ERRORS validation(s) failed"
exit 1
else
echo "All GIA retention validations passed"
fi
7 changes: 6 additions & 1 deletion src/aig/gia/giaIf.c
Original file line number Diff line number Diff line change
Expand Up @@ -2437,7 +2437,7 @@ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan )
Vec_Str_t * vConfigsStr = NULL;
Ifn_Ntk_t * pNtkCell = NULL;
sat_solver * pSat = NULL;
int i, k, Entry;
int i, j, k, Entry, nNodesStart, nNodesEnd;
assert( !pIfMan->pPars->fDeriveLuts || pIfMan->pPars->fTruth );
//if ( pIfMan->pPars->fEnableCheck07 )
// pIfMan->pPars->fDeriveLuts = 0;
Expand Down Expand Up @@ -2474,6 +2474,7 @@ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan )
{
if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) )
continue;
nNodesStart = Gia_ManObjNum(pNew);
if ( If_ObjIsAnd(pIfObj) )
{
pCutBest = If_ObjCutBest( pIfObj );
Expand Down Expand Up @@ -2587,6 +2588,10 @@ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan )
Vec_IntPush( vMapping2, 0 );
}
else assert( 0 );
// copy node retention origins for newly created nodes
nNodesEnd = Gia_ManObjNum(pNew);
for ( j = nNodesStart; j < nNodesEnd; j++ )
Nr_ManCopyOrigins( pNew->pNodeRetention, pIfMan->pNodeRetention, j, pIfObj->Id );
}
Vec_IntFree( vLits );
Vec_IntFree( vCover );
Expand Down
80 changes: 80 additions & 0 deletions src/base/abc/node_retention.c
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,86 @@ void Nr_ManPrintRetentionMap( FILE * pFile, Abc_Ntk_t * pNtk, Nr_Man_t * p )
}


/**Function*************************************************************

Synopsis [Writes retention map for GIA manager to a file.]

Description [Similar to Nr_ManPrintRetentionMap but operates on Gia_Man_t.
Outputs GIA object IDs directly (no name resolution).
Includes CI position-to-GIA-ID mapping for Yosys to join
back to the sym file.
Format:
.gia_retention_begin
CI <ci_position> <gia_object_id>
<gia_id> SRC <origin_gia_id_1> <origin_gia_id_2> ...
.gia_retention_end
]

SideEffects []

SeeAlso [Nr_ManPrintRetentionMap]

***********************************************************************/
void Nr_ManPrintRetentionMapGia( FILE * pFile, Gia_Man_t * pGia, Nr_Man_t * p )
{
Gia_Obj_t * pObj;
Vec_Int_t * vOrigins;
Nr_Man_t * pPruned;
int i, j, OriginId;

if ( pFile == NULL || pGia == NULL || p == NULL )
return;

// Create pruned version with unique origins only
pPruned = Nr_ManPrune( p );
if ( pPruned == NULL )
return;

// Validate that all AND nodes have retention entries
Nr_ManValidateEntriesGia( pGia, pPruned );

fprintf( pFile, ".gia_retention_begin\n" );

// Write CI position to GIA object ID mapping
Gia_ManForEachCi( pGia, pObj, i )
fprintf( pFile, "CI %d %d\n", i, Gia_ObjId(pGia, pObj) );

// Write retention entries for AND nodes
Gia_ManForEachAnd( pGia, pObj, i )
{
if ( i == 0 || Gia_ObjIsConst0(pObj) )
continue;
vOrigins = Nr_ManGetOrigins( pPruned, i );
if ( vOrigins && Vec_IntSize(vOrigins) > 0 )
{
fprintf( pFile, "%d SRC", i );
Vec_IntForEachEntry( vOrigins, OriginId, j )
fprintf( pFile, " %d", OriginId );
fprintf( pFile, "\n" );
}
}

// Write retention entries for CO nodes
Gia_ManForEachCo( pGia, pObj, i )
{
int CoId = Gia_ObjId(pGia, pObj);
vOrigins = Nr_ManGetOrigins( pPruned, CoId );
if ( vOrigins && Vec_IntSize(vOrigins) > 0 )
{
fprintf( pFile, "%d SRC", CoId );
Vec_IntForEachEntry( vOrigins, OriginId, j )
fprintf( pFile, " %d", OriginId );
fprintf( pFile, "\n" );
}
}

fprintf( pFile, ".gia_retention_end\n" );

// Free the pruned manager
Nr_ManFree( pPruned );
}


int Nr_ManTotalOriginCount( Nr_Man_t * p )
{
Nr_Entry_t * pEntry;
Expand Down
1 change: 1 addition & 0 deletions src/base/abc/node_retention.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ extern void Nr_ManPrintOrigins( Nr_Man_t * p, int NodeId );
extern void Nr_ManPrintAllOrigins( Nr_Man_t * p );
extern void Nr_ManPrintDebug( Nr_Man_t * p, char * pFuncName );
extern void Nr_ManPrintRetentionMap( FILE * pFile, Abc_Ntk_t * pNtk, Nr_Man_t * p );
extern void Nr_ManPrintRetentionMapGia( FILE * pFile, Gia_Man_t * pGia, Nr_Man_t * p );
extern int Nr_ManTotalOriginCount( Nr_Man_t * p );
extern Nr_Man_t * Nr_ManPrune( Nr_Man_t * p );
extern void Nr_ManValidateEntries( Abc_Ntk_t * pNtk, Nr_Man_t * p );
Expand Down
Loading
Loading