summaryrefslogtreecommitdiffstats
path: root/src/aig/miniaig/ndr.h
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2018-02-05 00:37:39 -0800
committerAlan Mishchenko <alanmi@berkeley.edu>2018-02-05 00:37:39 -0800
commit3202c2581e6e9020e754634f7f339a12713b1e49 (patch)
tree00e86f4f09657c4abc5f21750b0f57a36b258d47 /src/aig/miniaig/ndr.h
parent00fb1d706be8fa87623e1078103ff5f375785534 (diff)
downloadabc-3202c2581e6e9020e754634f7f339a12713b1e49.tar.gz
abc-3202c2581e6e9020e754634f7f339a12713b1e49.tar.bz2
abc-3202c2581e6e9020e754634f7f339a12713b1e49.zip
Improvements to NDR to represent hierarchical designs.
Diffstat (limited to 'src/aig/miniaig/ndr.h')
-rw-r--r--src/aig/miniaig/ndr.h245
1 files changed, 198 insertions, 47 deletions
diff --git a/src/aig/miniaig/ndr.h b/src/aig/miniaig/ndr.h
index 325cf5d9..fc5574bc 100644
--- a/src/aig/miniaig/ndr.h
+++ b/src/aig/miniaig/ndr.h
@@ -96,7 +96,7 @@ ABC_NAMESPACE_HEADER_START
(for example, the 16-bit constant 10 is represented as a string "4'b1010". This string contains 8 bytes,
including the char '\0' to denote the end of the string. It will take 2 unsigned ints, therefore
its record will look as follows { {NDR_FUNCTION, 2}, {"4'b1010"} }, but the user does not see these details.
- The user only gives "4'b1010" as an argument (char * pFunction) to the above procedure Ndr_ModuleAddObject().
+ The user only gives "4'b1010" as an argument (char * pFunction) to the above procedure Ndr_AddObject().
*/
////////////////////////////////////////////////////////////////////////
@@ -106,7 +106,7 @@ ABC_NAMESPACE_HEADER_START
// record types
typedef enum {
NDR_NONE = 0, // 0: unused
- NDR_DESIGN, // 1: design (or library of modules)
+ Ndr_, // 1: design (or library of modules)
NDR_MODULE, // 2: one module
NDR_OBJECT, // 3: object
NDR_INPUT, // 4: input
@@ -273,17 +273,29 @@ static inline int * Ndr_ObjReadBodyP( Ndr_Data_t * p, int Obj, int Type )
return Ndr_DataEntryP(p, Ent);
return NULL;
}
-static inline void Ndr_ObjWriteRange( Ndr_Data_t * p, int Obj, FILE * pFile )
+static inline void Ndr_ObjWriteRange( Ndr_Data_t * p, int Obj, FILE * pFile, int fSkipBin )
{
int * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_RANGE, &pArray );
- if ( nArray == 0 )
+ if ( (nArray == 0 || nArray == 1) && fSkipBin )
return;
- if ( nArray == 3 )
+ if ( nArray == 3 && fSkipBin )
fprintf( pFile, "signed " );
- if ( nArray == 1 )
- fprintf( pFile, "[%d] ", pArray[0] );
+ else if ( nArray == 1 )
+ {
+ if ( fSkipBin )
+ fprintf( pFile, "[%d:%d]", pArray[0], pArray[0] );
+ else
+ fprintf( pFile, "[%d]", pArray[0] );
+ }
+ else if ( nArray == 0 )
+ {
+ if ( fSkipBin )
+ fprintf( pFile, "[%d:%d]", 0, 0 );
+ else
+ fprintf( pFile, "[%d]", 0 );
+ }
else
- fprintf( pFile, "[%d:%d] ", pArray[0], pArray[1] );
+ fprintf( pFile, "[%d:%d]", pArray[0], pArray[1] );
}
static inline char * Ndr_ObjReadOutName( Ndr_Data_t * p, int Obj, char ** pNames )
{
@@ -317,15 +329,12 @@ static inline int Ndr_DataObjNum( Ndr_Data_t * p, int Mod )
}
// to write signal names, this procedure takes a mapping of name IDs into actual char-strings (pNames)
-static inline void Ndr_ModuleWriteVerilog( char * pFileName, void * pModule, char ** pNames )
+static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod, char ** pNames )
{
- Ndr_Data_t * p = (Ndr_Data_t *)pModule;
- int Mod = 0, Obj, nArray, * pArray, fFirst = 1;
+ Ndr_Data_t * p = (Ndr_Data_t *)pDesign;
+ int Obj, nArray, * pArray, fFirst = 1;
- FILE * pFile = pFileName ? fopen( pFileName, "wb" ) : stdout;
- if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; }
-
- fprintf( pFile, "\nmodule %s (\n ", pNames[Ndr_ObjReadEntry(p, 0, NDR_NAME)] );
+ fprintf( pFile, "\nmodule %s (\n ", pNames[Ndr_ObjReadEntry(p, Mod, NDR_NAME)] );
Ndr_ModForEachPi( p, Mod, Obj )
fprintf( pFile, "%s, ", Ndr_ObjReadOutName(p, Obj, pNames) );
@@ -340,45 +349,77 @@ static inline void Ndr_ModuleWriteVerilog( char * pFileName, void * pModule, cha
Ndr_ModForEachPi( p, Mod, Obj )
{
fprintf( pFile, " input " );
- Ndr_ObjWriteRange( p, Obj, pFile );
- fprintf( pFile, "%s;\n", Ndr_ObjReadOutName(p, Obj, pNames) );
+ Ndr_ObjWriteRange( p, Obj, pFile, 1 );
+ fprintf( pFile, " %s;\n", Ndr_ObjReadOutName(p, Obj, pNames) );
}
Ndr_ModForEachPo( p, Mod, Obj )
{
fprintf( pFile, " output " );
- Ndr_ObjWriteRange( p, Obj, pFile );
- fprintf( pFile, "%s;\n", Ndr_ObjReadInName(p, Obj, pNames) );
+ Ndr_ObjWriteRange( p, Obj, pFile, 1 );
+ fprintf( pFile, " %s;\n", Ndr_ObjReadInName(p, Obj, pNames) );
}
+ fprintf( pFile, "\n" );
+
Ndr_ModForEachNode( p, Mod, Obj )
{
fprintf( pFile, " wire " );
- Ndr_ObjWriteRange( p, Obj, pFile );
- fprintf( pFile, "%s;\n", Ndr_ObjReadOutName(p, Obj, pNames) );
+ Ndr_ObjWriteRange( p, Obj, pFile, 1 );
+ fprintf( pFile, " %s;\n", Ndr_ObjReadOutName(p, Obj, pNames) );
}
fprintf( pFile, "\n" );
Ndr_ModForEachNode( p, Mod, Obj )
{
+ int i, Type = Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE);
+ if ( Type >= 256 )
+ {
+ fprintf( pFile, " %s ", pNames[Ndr_ObjReadEntry(p, Type-256, NDR_NAME)] );
+ if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) )
+ fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] );
+ fprintf( pFile, "( ", pNames[Ndr_ObjReadEntry(p, Type-256, NDR_NAME)] );
+ nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
+ for ( i = 0; i < nArray; i++ )
+ fprintf( pFile, "%s%s ", pNames[pArray[i]], i==nArray-1 ? "":"," );
+ fprintf( pFile, ");\n" );
+ continue;
+ }
fprintf( pFile, " assign %s = ", Ndr_ObjReadOutName(p, Obj, pNames) );
nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
if ( nArray == 0 )
fprintf( pFile, "%s;\n", (char *)Ndr_ObjReadBodyP(p, Obj, NDR_FUNCTION) );
else if ( nArray == 1 && Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE) == ABC_OPER_BIT_BUF )
fprintf( pFile, "%s;\n", pNames[pArray[0]] );
+ else if ( Type == ABC_OPER_SLICE )
+ fprintf( pFile, "%s", pNames[pArray[0]] ),
+ Ndr_ObjWriteRange( p, Obj, pFile, 0 ),
+ fprintf( pFile, ";\n" );
else if ( nArray == 1 )
fprintf( pFile, "%s %s;\n", Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)), pNames[pArray[0]] );
else if ( nArray == 2 )
fprintf( pFile, "%s %s %s;\n", pNames[pArray[0]], Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)), pNames[pArray[1]] );
- else if ( Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE) == ABC_OPER_BIT_MUX )
+ else if ( Type == ABC_OPER_BIT_MUX )
fprintf( pFile, "%s ? %s : %s;\n", pNames[pArray[0]], pNames[pArray[1]], pNames[pArray[2]] );
else
fprintf( pFile, "<cannot write operation %s>;\n", Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)) );
}
fprintf( pFile, "\nendmodule\n\n" );
+}
+
+// to write signal names, this procedure takes a mapping of name IDs into actual char-strings (pNames)
+static inline void Ndr_WriteVerilog( char * pFileName, void * pDesign, char ** pNames )
+{
+ Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int Mod;
+
+ FILE * pFile = pFileName ? fopen( pFileName, "wb" ) : stdout;
+ if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; }
+
+ Ndr_DesForEachMod( p, Mod )
+ Ndr_WriteVerilogModule( pFile, p, Mod, pNames );
+
if ( pFileName ) fclose( pFile );
}
@@ -388,14 +429,14 @@ static inline void Ndr_ModuleWriteVerilog( char * pFileName, void * pModule, cha
////////////////////////////////////////////////////////////////////////
// creating a new module (returns pointer to the memory buffer storing the module info)
-static inline void * Ndr_ModuleCreate( int Name )
+static inline void * Ndr_Create( int Name )
{
Ndr_Data_t * p = ABC_ALLOC( Ndr_Data_t, 1 );
p->nSize = 0;
p->nCap = 16;
p->pHead = ABC_ALLOC( unsigned char, p->nCap );
p->pBody = ABC_ALLOC( unsigned int, p->nCap * 4 );
- Ndr_DataPush( p, NDR_MODULE, 0 );
+ Ndr_DataPush( p, Ndr_, 0 );
Ndr_DataPush( p, NDR_NAME, Name );
Ndr_DataAddTo( p, 0, p->nSize );
assert( p->nSize == 2 );
@@ -403,18 +444,37 @@ static inline void * Ndr_ModuleCreate( int Name )
return p;
}
-// adding a new object (input/output/flop/intenal node) to an already module module
-static inline void Ndr_ModuleAddObject( void * pModule, int Type, int InstName,
- int RangeLeft, int RangeRight, int fSignedness,
- int nInputs, int * pInputs,
- int nOutputs, int * pOutputs,
- char * pFunction )
+// creating a new module in an already started design
+// returns module ID to be used when adding objects to the module
+static inline int Ndr_AddModule( void * pDesign, int Name )
+{
+ Ndr_Data_t * p = (Ndr_Data_t *)pDesign;
+ int Mod = p->nSize;
+ Ndr_DataResize( p, 6 );
+ Ndr_DataPush( p, NDR_MODULE, 0 );
+ Ndr_DataPush( p, NDR_NAME, Name );
+ Ndr_DataAddTo( p, Mod, p->nSize - Mod );
+ Ndr_DataAddTo( p, 0, p->nSize - Mod );
+ assert( (int)p->pBody[0] == p->nSize );
+ return Mod + 256;
+}
+
+// adding a new object (input/output/flop/intenal node) to an already started module
+// this procedure takes the design, the module ID, and the parameters of the boject
+// (please note that all objects should be added to a given module before starting a new module)
+static inline void Ndr_AddObject( void * pDesign, int ModuleId,
+ int ObjType, int InstName,
+ int RangeLeft, int RangeRight, int fSignedness,
+ int nInputs, int * pInputs,
+ int nOutputs, int * pOutputs,
+ char * pFunction )
{
- Ndr_Data_t * p = (Ndr_Data_t *)pModule;
- int Obj = p->nSize; assert( Type != 0 );
+ Ndr_Data_t * p = (Ndr_Data_t *)pDesign;
+ int Mod = ModuleId - 256;
+ int Obj = p->nSize; assert( ObjType != 0 );
Ndr_DataResize( p, 6 );
Ndr_DataPush( p, NDR_OBJECT, 0 );
- Ndr_DataPush( p, NDR_OPERTYPE, Type );
+ Ndr_DataPush( p, NDR_OPERTYPE, ObjType );
Ndr_DataPushRange( p, RangeLeft, RangeRight, fSignedness );
if ( InstName )
Ndr_DataPush( p, NDR_NAME, InstName );
@@ -422,14 +482,15 @@ static inline void Ndr_ModuleAddObject( void * pModule, int Type, int InstName,
Ndr_DataPushArray( p, NDR_OUTPUT, nOutputs, pOutputs );
Ndr_DataPushString( p, NDR_FUNCTION, pFunction );
Ndr_DataAddTo( p, Obj, p->nSize - Obj );
+ Ndr_DataAddTo( p, Mod, p->nSize - Obj );
Ndr_DataAddTo( p, 0, p->nSize - Obj );
assert( (int)p->pBody[0] == p->nSize );
}
// deallocate the memory buffer
-static inline void Ndr_ModuleDelete( void * pModule )
+static inline void Ndr_Delete( void * pDesign )
{
- Ndr_Data_t * p = (Ndr_Data_t *)pModule;
+ Ndr_Data_t * p = (Ndr_Data_t *)pDesign;
if ( !p ) return;
free( p->pHead );
free( p->pBody );
@@ -442,7 +503,7 @@ static inline void Ndr_ModuleDelete( void * pModule )
////////////////////////////////////////////////////////////////////////
// file reading/writing
-static inline void * Ndr_ModuleRead( char * pFileName )
+static inline void * Ndr_Read( char * pFileName )
{
Ndr_Data_t * p; int nFileSize, RetValue;
FILE * pFile = fopen( pFileName, "rb" );
@@ -461,16 +522,18 @@ static inline void * Ndr_ModuleRead( char * pFileName )
RetValue = (int)fread( p->pHead, 1, p->nCap, pFile );
assert( p->nSize == (int)p->pBody[0] );
fclose( pFile );
+ //printf( "Read the design from file \"%s\".\n", pFileName );
return p;
}
-static inline void Ndr_ModuleWrite( char * pFileName, void * pModule )
+static inline void Ndr_Write( char * pFileName, void * pDesign )
{
- Ndr_Data_t * p = (Ndr_Data_t *)pModule; int RetValue;
+ Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int RetValue;
FILE * pFile = fopen( pFileName, "wb" );
if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; }
RetValue = (int)fwrite( p->pBody, 4, p->pBody[0], pFile );
RetValue = (int)fwrite( p->pHead, 1, p->pBody[0], pFile );
fclose( pFile );
+ //printf( "Dumped the design into file \"%s\".\n", pFileName );
}
@@ -478,7 +541,8 @@ static inline void Ndr_ModuleWrite( char * pFileName, void * pModule )
/// TESTING PROCEDURE ///
////////////////////////////////////////////////////////////////////////
-// This testing procedure creates and writes into a Verilog file the following module
+// This testing procedure creates and writes into a Verilog file
+// for the following design composed of one module
// module add10 ( input [3:0] a, output [3:0] s );
// wire [3:0] const10 = 4'b1010;
@@ -497,18 +561,105 @@ static inline void Ndr_ModuleTest()
char * ppNames[5] = { NULL, "add10", "a", "s", "const10" };
// create a new module
- void * pModule = Ndr_ModuleCreate( 1 );
+ void * pDesign = Ndr_Create( 1 );
+
+ int ModuleID = Ndr_AddModule( pDesign, 1 );
// add objects to the modele
- Ndr_ModuleAddObject( pModule, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdA, NULL ); // no fanins
- Ndr_ModuleAddObject( pModule, ABC_OPER_CONST, 0, 3, 0, 0, 0, NULL, 1, &NameIdC, "4'b1010" ); // no fanins
- Ndr_ModuleAddObject( pModule, ABC_OPER_ARI_ADD, 0, 3, 0, 0, 2, Fanins, 1, &NameIdS, NULL ); // fanins are a and const10
- Ndr_ModuleAddObject( pModule, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdS, 0, NULL, NULL ); // fanin is a
+ Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdA, NULL ); // no fanins
+ Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONST, 0, 3, 0, 0, 0, NULL, 1, &NameIdC, "4'b1010" ); // no fanins
+ Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADD, 0, 3, 0, 0, 2, Fanins, 1, &NameIdS, NULL ); // fanins are a and const10
+ Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdS, 0, NULL, NULL ); // fanin is a
+
+ // write Verilog for verification
+ Ndr_WriteVerilog( NULL, pDesign, ppNames );
+ Ndr_Write( "add4.ndr", pDesign );
+ Ndr_Delete( pDesign );
+}
+
+// This testing procedure creates and writes into a Verilog file
+// for the following hierarchical design composed of three modules
+
+// module mux21w ( input sel, input [3:0] d1, input [3:0] d0, output [3:0] out );
+// assign out = sel ? d1 : d0;
+// endmodule
+
+// module mux41w ( input [1:0] sel, input [15:0] d, output [3:0] out );
+// wire [3:0] t0, t1;
+// wire [3:0] d0 = d[3:0];
+// wire [3:0] d1 = d[7:4];
+// wire [3:0] d2 = d[11:8];
+// wire [3:0] d3 = d[15:12];
+// wire sel0 = sel[0];
+// wire sel1 = sel[1];
+// mux21w i0 ( sel0, d1, d0, t0 );
+// mux21w i1 ( sel0, d3, d2, t1 );
+// mux21w i2 ( sel1, t1, t0, out );
+// endmodule
+
+static inline void Ndr_ModuleTestHierarchy()
+{
+ // map name IDs into char strings
+ char * ppNames[20] = { NULL,
+ "mux21w", "mux41w", // 1, 2
+ "sel", "d", "out", // 3, 4, 5
+ "d0", "d1", "d2", "d3", // 6, 7, 8, 9
+ "sel0", "sel1", // 10, 11,
+ "t0", "t1", // 12, 13
+ "i0", "i1", "i2" // 14, 15, 16
+ };
+ // fanins
+ int FaninSel = 3;
+ int FaninSel0 = 10;
+ int FaninSel1 = 11;
+ int FaninD = 4;
+ int FaninD0 = 6;
+ int FaninD1 = 7;
+ int FaninD2 = 8;
+ int FaninD3 = 9;
+ int FaninT0 = 12;
+ int FaninT1 = 13;
+ int FaninOut = 5;
+ int Fanins1[3] = { FaninSel, FaninD1, FaninD0 };
+ int Fanins3[3][3] = { {FaninSel0, FaninD1, FaninD0 },
+ {FaninSel0, FaninD3, FaninD2 },
+ {FaninSel1, FaninT1, FaninT0 } };
+
+ // create a new module
+ void * pDesign = Ndr_Create( 2 );
+
+ int Module21, Module41;
+
+ Module21 = Ndr_AddModule( pDesign, 1 );
+
+ Ndr_AddObject( pDesign, Module21, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &FaninSel, NULL );
+ Ndr_AddObject( pDesign, Module21, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &FaninD1, NULL );
+ Ndr_AddObject( pDesign, Module21, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &FaninD0, NULL );
+ Ndr_AddObject( pDesign, Module21, ABC_OPER_BIT_MUX, 0, 3, 0, 0, 3, Fanins1, 1, &FaninOut, NULL );
+ Ndr_AddObject( pDesign, Module21, ABC_OPER_CO, 0, 3, 0, 0, 1, &FaninOut, 0, NULL, NULL );
+
+ Module41 = Ndr_AddModule( pDesign, 2 );
+
+ Ndr_AddObject( pDesign, Module41, ABC_OPER_CI, 0, 1, 0, 0, 0, NULL, 1, &FaninSel, NULL );
+ Ndr_AddObject( pDesign, Module41, ABC_OPER_CI, 0, 15,0, 0, 0, NULL, 1, &FaninD, NULL );
+
+ Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 3, 0, 0, 1, &FaninD, 1, &FaninD0, NULL );
+ Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 7, 4, 0, 1, &FaninD, 1, &FaninD1, NULL );
+ Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 11,8, 0, 1, &FaninD, 1, &FaninD2, NULL );
+ Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 15,12,0, 1, &FaninD, 1, &FaninD3, NULL );
+
+ Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 0, 0, 0, 1, &FaninSel, 1, &FaninSel0, NULL );
+ Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 1, 1, 0, 1, &FaninSel, 1, &FaninSel1, NULL );
+
+ Ndr_AddObject( pDesign, Module41, Module21, 14, 3, 0, 0, 3, Fanins3[0], 1, &FaninT0, NULL );
+ Ndr_AddObject( pDesign, Module41, Module21, 15, 3, 0, 0, 3, Fanins3[1], 1, &FaninT1, NULL );
+ Ndr_AddObject( pDesign, Module41, Module21, 16, 3, 0, 0, 3, Fanins3[2], 1, &FaninOut, NULL );
+ Ndr_AddObject( pDesign, Module41, ABC_OPER_CO, 0, 3, 0, 0, 1, &FaninOut, 0, NULL, NULL );
// write Verilog for verification
- Ndr_ModuleWriteVerilog( NULL, pModule, ppNames );
- Ndr_ModuleWrite( "add4.ndr", pModule );
- Ndr_ModuleDelete( pModule );
+ Ndr_WriteVerilog( NULL, pDesign, ppNames );
+ Ndr_Write( "mux41w.ndr", pDesign );
+ Ndr_Delete( pDesign );
}