Commit f23ea8e3 by Alan Mishchenko

Updates to NDR format (flops, memories, signed mult, etc).

parent 89c981c6
...@@ -138,8 +138,8 @@ typedef enum { ...@@ -138,8 +138,8 @@ typedef enum {
ABC_OPER_LATCH, // 86 ABC_OPER_LATCH, // 86
ABC_OPER_LATCHRS, // 87 ABC_OPER_LATCHRS, // 87
ABC_OPER_DFF, // 88 ABC_OPER_DFF, // 88
ABC_OPER_DFFCPL, // 89 ABC_OPER_DFFRSE, // 89
ABC_OPER_DFFRS, // 90 ABC_OPER_DFFLAST, // 90
ABC_OPER_SLICE, // 91 ABC_OPER_SLICE, // 91
ABC_OPER_CONCAT, // 92 ABC_OPER_CONCAT, // 92
......
...@@ -42,61 +42,51 @@ ABC_NAMESPACE_HEADER_START ...@@ -42,61 +42,51 @@ ABC_NAMESPACE_HEADER_START
/* /*
For the lack of a better name, this format is called New Data Representation (NDR). For the lack of a better name, this format is called New Data Representation (NDR).
NDR is based on the following principles: NDR is designed as an interchange format to pass hierarchical word-level designs between the tools.
- complex data is composed of individual records It is relatively simple, uses little memory, and can be easily converted into other ABC data-structures.
- a record has one of several known types (module, name, range, fanins, etc)
- a record can be atomic, for example, a name or an operator type This tutorial discusses how to construct the NDR representation of a hierarchical word-level design.
- a record can be composed of other records (for example, a module is composed of objects, etc)
- the stored data should be easy to write into and read from a file, or pass around as a memory buffer First, all names used in the design (including the design name, module names, port names, net names,
- the format should be simple, easy to use, low-memory, and extensible instance names, etc) are hashed into 1-based integers called "name IDs". Nets are not explicitly represented.
- new record types can be added by the user as needed The connectivity of a design object is established by specifying name IDs of the nets connected to the object.
Object inputs are name IDs of the driving nets; object outputs are name IDs of the driven nets.
The implementation is based on the following ideas:
- a record is composed of two parts (the header followed by the body) The design is initialized using procedure Ndr_Create(), which takes the design name as an argument.
- the header contains two items (the record type and the body size, measured in terms of 4-byte integers) A module in the design is initialized using procedure Ndr_AddModule(), which take the design and
- the body contains as many entries as stated in the record size the module name as arguments. Objects are added to a module in any order using procedure Ndr_AddObject().
- if a record is composed of other records, its body contains these records
Primary input and primary output objects should be explicitly created, as shown in the examples below.
As an example, consider a name. It can be a module name, an object name, or a net name.
A record storing one name has a header {NDR_NAME, 1} containing record type (NDR_NAME) and size (1), Instances of known operators listed in file "abcOper.h" are assumed to have one output. The only known
The body of the record is composed of one unsigned integer representing the name (say, 357). issue due to this restriction concerns an adder, which produces a sum and a carry-out. To make sure the
So the complete record looks as follows: { <header>, <body> } = { {NDR_NAME, 1}, {357} }. adder instance has only one output, the carry-out has to be concatenated with the sum before the adder
instance is created in the NDR format.
As another example, consider a two-input AND-gate. In this case, the recent is composed
of a header {NDR_OBJECT, 4} containing record type (NDR_OBJECT) and the body size (4), followed Instances of hierarchical modules defined by the user can have multiple outputs.
by an array of records creating the AND-gate: (a) name, (b) operation type, (c) fanins.
The complete record looks as follows: { {NDR_OBJECT, 5}, {{{NDR_NAME, 1}, 357}, {{NDR_OPERTYPE, 1}, ABC_OPER_LOGIC_AND}, Bit-slice and concatenation operators should be represented as separate objects.
{{NDR_INPUT, 2}, {<id_fanin1>, <id_fanin2>}}} }. Please note that only body entries are counted towards size.
In the case of one name, there is only one body entry. In the case of the AND-gate, there are 4 body entries If the ordering of inputs/outputs/flops of a module is not provided as a separate record in NDR format,
(name ID, gate type, first fanin, second fanin). their ordering is determined by the order of their appearance of their records in the body of the module.
Headers and bodies of all objects are stored differently. Headers are stored in an array of unsigned chars, If left limit and right limit of a range are equal, it is assumed that the range contains one bit
while bodies are stored in the array of 4-byte unsigned integers. This is important for memory efficiency. If range limits and signedness are all 0, it is assumed that it is the bit-width is equal to 1.
However, the user does not see these details.
Word-level constants are represented as char-strings given in the same way as they would appear in a Verilog
To estimate memory usage, we can assume that each header takes 1 byte and each body entry contains 4 bytes. file. For example, the 16-bit constant 10 is represented as a string "4'b1010" and is given as an argument
A name takes 5 bytes, and an AND-gate takes 1 * NumHeaders + 4 * NumBodyEntries = 1 * 4 + 4 * 4 = 20 bytes. (char * pFunction) to the procedure Ndr_AddObject().
Not bad. The same as memory usage in a well-designed AIG package with structural hashing.
Currently two types of flops are supported: a simple flop with implicit clock with two fanins (data and init)
Comments: and a complex flop with 7 fanins (clock, data, reset, set, enable, async, init), as shown in the examples below.
- it is assumed that all port names, net names, and instance names are hashed into 1-based integer numbers called name IDs
- nets are not explicitly represented but their name ID are used to establish connectivity between the objects The initial value of a flop is represented by input "init", which can be driven by a constant or by a primary
- primary input and primary output objects have to be explicitly created (as shown in the example below) input of the module. If it is a primary input, is it assumed that the flop is not initialized. If the input
- object inputs are name IDs of the driving nets; object outputs are name IDs of the driven nets "init" is not driven, it is assumed that the flop is initialized to 0.
- objects can be added to a module in any order
- if the ordering of inputs/outputs/flops of a module is not provided as a separate record, Memory read and write ports are supported, as shown in the example below.
their ordering is determined by the order of their appearance of their records in the body of the module
- if range limits and signedness are all 0, it is assumed that it is a Boolean object (to be continued)
- if left limit and right limit of a range are equal, it is assumed that the range contains one bit
- instances of known operators can have types defined by Wlc_ObjType_t below
- instances of user modules have type equal to the name ID of the module plus 1000
- initial states of the flops are given as char-strings containing 0, 1, and 'x'
(for example, "4'b10XX" is an init state of a 4-bit flop with bit-level init states const1, const0, unknown, unknown)
- word-level constants are represented as char-strings given in the same way as they would appear in a Verilog file
(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_AddObject().
*/ */
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
...@@ -377,7 +367,7 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod ...@@ -377,7 +367,7 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod
if ( Type >= 256 ) if ( Type >= 256 )
{ {
fprintf( pFile, " %s ", pNames[Ndr_ObjReadEntry(p, Type-256, NDR_NAME)] ); fprintf( pFile, " %s ", pNames[Ndr_ObjReadEntry(p, Type-256, NDR_NAME)] );
if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) ) if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 )
fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] ); fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] );
fprintf( pFile, "( " ); fprintf( pFile, "( " );
nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
...@@ -386,6 +376,64 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod ...@@ -386,6 +376,64 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod
fprintf( pFile, ");\n" ); fprintf( pFile, ");\n" );
continue; continue;
} }
if ( Type == ABC_OPER_DFF )
{
fprintf( pFile, " %s ", "ABC_DFF" );
if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 )
fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] );
fprintf( pFile, "( " );
nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
fprintf( pFile, ".q(%s), ", Ndr_ObjReadOutName(p, Obj, pNames) );
fprintf( pFile, ".d(%s), ", pNames[pArray[0]] );
fprintf( pFile, ".init(%s) ", pNames[pArray[1]] );
fprintf( pFile, ");\n" );
continue;
}
if ( Type == ABC_OPER_DFFRSE )
{
fprintf( pFile, " %s ", "ABC_DFFRSE" );
if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 )
fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] );
fprintf( pFile, "( " );
nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
fprintf( pFile, ".q(%s), ", Ndr_ObjReadOutName(p, Obj, pNames) );
fprintf( pFile, ".d(%s), ", pNames[pArray[0]] );
fprintf( pFile, ".clk(%s), ", pNames[pArray[1]] );
fprintf( pFile, ".reset(%s), ", pNames[pArray[2]] );
fprintf( pFile, ".set(%s), ", pNames[pArray[3]] );
fprintf( pFile, ".enable(%s), ", pNames[pArray[4]] );
fprintf( pFile, ".async(%s), ", pNames[pArray[5]] );
fprintf( pFile, ".init(%s) ", pNames[pArray[6]] );
fprintf( pFile, ");\n" );
continue;
}
if ( Type == ABC_OPER_RAMR )
{
fprintf( pFile, " %s ", "ABC_READ" );
if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 )
fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] );
fprintf( pFile, "( " );
nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
fprintf( pFile, ".data(%s), ", Ndr_ObjReadOutName(p, Obj, pNames) );
fprintf( pFile, ".mem_in(%s), ", pNames[pArray[0]] );
fprintf( pFile, ".addr(%s) ", pNames[pArray[1]] );
fprintf( pFile, ");\n" );
continue;
}
if ( Type == ABC_OPER_RAMW )
{
fprintf( pFile, " %s ", "ABC_WRITE" );
if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 )
fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] );
fprintf( pFile, "( " );
nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
fprintf( pFile, ".mem_out(%s), ", Ndr_ObjReadOutName(p, Obj, pNames) );
fprintf( pFile, ".mem_in(%s), ", pNames[pArray[0]] );
fprintf( pFile, ".addr(%s), ", pNames[pArray[1]] );
fprintf( pFile, ".data(%s) ", pNames[pArray[2]] );
fprintf( pFile, ");\n" );
continue;
}
fprintf( pFile, " assign %s = ", Ndr_ObjReadOutName(p, Obj, pNames) ); fprintf( pFile, " assign %s = ", Ndr_ObjReadOutName(p, Obj, pNames) );
nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
if ( nArray == 0 ) if ( nArray == 0 )
...@@ -551,7 +599,7 @@ static inline void Ndr_Write( char * pFileName, void * pDesign ) ...@@ -551,7 +599,7 @@ static inline void Ndr_Write( char * pFileName, void * pDesign )
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// This testing procedure creates and writes into a Verilog file // This testing procedure creates and writes into a Verilog file
// for the following design composed of one module // the following design composed of one module
// module add10 ( input [3:0] a, output [3:0] s ); // module add10 ( input [3:0] a, output [3:0] s );
// wire [3:0] const10 = 4'b1010; // wire [3:0] const10 = 4'b1010;
...@@ -589,7 +637,7 @@ static inline void Ndr_ModuleTest() ...@@ -589,7 +637,7 @@ static inline void Ndr_ModuleTest()
// This testing procedure creates and writes into a Verilog file // This testing procedure creates and writes into a Verilog file
// for the following design composed of one adder divided into two // the following design composed of one adder divided into two
// module add8 ( input [7:0] a, input [7:0] b, output [7:0] s, output co ); // module add8 ( input [7:0] a, input [7:0] b, output [7:0] s, output co );
// wire [3:0] a0 = a[3:0]; // wire [3:0] a0 = a[3:0];
...@@ -676,7 +724,7 @@ static inline void Ndr_ModuleTestAdder() ...@@ -676,7 +724,7 @@ static inline void Ndr_ModuleTestAdder()
} }
// This testing procedure creates and writes into a Verilog file // This testing procedure creates and writes into a Verilog file
// for the following hierarchical design composed of three modules // the following hierarchical design composed of two modules
// module mux21w ( input sel, input [3:0] d1, input [3:0] d0, output [3:0] out ); // module mux21w ( input sel, input [3:0] d1, input [3:0] d0, output [3:0] out );
// assign out = sel ? d1 : d0; // assign out = sel ? d1 : d0;
...@@ -761,6 +809,141 @@ static inline void Ndr_ModuleTestHierarchy() ...@@ -761,6 +809,141 @@ static inline void Ndr_ModuleTestHierarchy()
} }
// This testing procedure creates and writes into a Verilog file
// the following design with read/write memory ports
// module test ( input clk, input [8:0] raddr, input [8:0] waddr, input [31:0] data, input [16383:0] mem_init, output out );
//
// wire [31:0] read1, read2;
//
// wire [16383:0] mem_fo1, mem_fo2, mem_fi1, mem_fi2;
//
// ABC_FF i_reg1 ( .q(mem_fo1), .d(mem_fi1), .init(mem_init) );
// ABC_FF i_reg2 ( .q(mem_fo2), .d(mem_fi2), .init(mem_init) );
//
// ABC_WRITE i_write1 ( .mem_out(mem_fi1), .mem_in(mem_fo1), .addr(waddr), .data(data) );
// ABC_WRITE i_write2 ( .mem_out(mem_fi2), .mem_in(mem_fo2), .addr(waddr), .data(data) );
//
// ABC_READ i_read1 ( .data(read1), .mem_in(mem_fi1), .addr(raddr) );
// ABC_READ i_read2 ( .data(read2), .mem_in(mem_fi2), .addr(raddr) );
//
// assign out = read1 != read2;
//endmodule
static inline void Ndr_ModuleTestMemory()
{
// map name IDs into char strings
char * ppNames[20] = { NULL,
"clk", "raddr", "waddr", "data", "mem_init", "out", // 1, 2, 3, 4, 5, 6
"read1", "read2", // 7. 8
"mem_fo1", "mem_fo2", "mem_fi1", "mem_fi2", // 9, 10, 11, 12
"i_reg1", "i_reg2", // 13, 14
"i_read1", "i_read2", // 15, 16
"i_write1", "i_write2", "memtest" // 17, 18, 19
};
// inputs
int NameIdClk = 1;
int NameIdRaddr = 2;
int NameIdWaddr = 3;
int NameIdData = 4;
int NameIdMemInit = 5;
// flops
int NameIdFF1 = 9;
int NameIdFF2 = 10;
int FaninsFF1[2] = { 11, 5 };
int FaninsFF2[2] = { 12, 5 };
// writes
int NameIdWrite1 = 11;
int NameIdWrite2 = 12;
int FaninsWrite1[3] = { 9, 3, 4 };
int FaninsWrite2[3] = { 10, 3, 4 };
// reads
int NameIdRead1 = 7;
int NameIdRead2 = 8;
int FaninsRead1[2] = { 11, 2 };
int FaninsRead2[2] = { 12, 2 };
// compare
int NameIdComp = 6;
int FaninsComp[2] = { 7, 8 };
// create a new module
void * pDesign = Ndr_Create( 19 ); // create design named "memtest"
int ModuleID = Ndr_AddModule( pDesign, 19 ); // create module named "memtest"
// add objects to the module
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdClk, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 8, 0, 0, 0, NULL, 1, &NameIdRaddr, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 8, 0, 0, 0, NULL, 1, &NameIdWaddr, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 31, 0, 0, 0, NULL, 1, &NameIdData, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 16383, 0, 0, 0, NULL, 1, &NameIdMemInit, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 0, 0, 0, 1, &NameIdComp, 0, NULL, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_DFF, 13, 16383, 0, 0, 2, FaninsFF1, 1, &NameIdFF1, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_DFF, 14, 16383, 0, 0, 2, FaninsFF2, 1, &NameIdFF2, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMW, 17, 16383, 0, 0, 3, FaninsWrite1, 1, &NameIdWrite1, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMW, 18, 16383, 0, 0, 3, FaninsWrite2, 1, &NameIdWrite2, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMR, 15, 31, 0, 0, 2, FaninsRead1, 1, &NameIdRead1, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMR, 16, 31, 0, 0, 2, FaninsRead2, 1, &NameIdRead2, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_COMP_NOTEQU, 0, 0, 0, 0, 2, FaninsComp, 1, &NameIdComp, NULL );
// write Verilog for verification
Ndr_WriteVerilog( NULL, pDesign, ppNames );
Ndr_Write( "memtest.ndr", pDesign );
Ndr_Delete( pDesign );
}
// This testing procedure creates and writes into a Verilog file
// the following design composed of one word-level flop
// module flop ( input [3:0] data, input clk, input reset, input set, input enable, input async, input [3:0] init, output [3:0] q );
// ABC_DFFRSE reg1 ( .d(data), .clk(clk), .reset(reset), .set(set), .enable(enable), .async(async), .init(init), .q(q) ) ;
// endmodule
static inline void Ndr_ModuleTestFlop()
{
// map name IDs into char strings
char * ppNames[10] = { NULL, "flop", "data", "clk", "reset", "set", "enable", "async", "init", "q" };
// name IDs
int NameIdData = 2;
int NameIdClk = 3;
int NameIdReset = 4;
int NameIdSet = 5;
int NameIdEnable = 6;
int NameIdAsync = 7;
int NameIdInit = 8;
int NameIdQ = 9;
// array of fanins of node s
int Fanins[7] = { NameIdData, NameIdClk, NameIdReset, NameIdSet, NameIdEnable, NameIdAsync, NameIdInit };
// create a new module
void * pDesign = Ndr_Create( 1 );
int ModuleID = Ndr_AddModule( pDesign, 1 );
// add objects to the modele
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdData, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdClk, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdReset, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdSet, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdEnable, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdAsync, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdInit, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_DFFRSE, 0, 3, 0, 0, 7, Fanins, 1, &NameIdQ, NULL );
Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdQ, 0, NULL, NULL );
// write Verilog for verification
Ndr_WriteVerilog( NULL, pDesign, ppNames );
Ndr_Write( "flop.ndr", pDesign );
Ndr_Delete( pDesign );
}
ABC_NAMESPACE_HEADER_END ABC_NAMESPACE_HEADER_END
#endif #endif
......
...@@ -237,7 +237,7 @@ static inline void Acb_NtkFreeObjCnfs( Acb_Ntk_t * p ) { V ...@@ -237,7 +237,7 @@ static inline void Acb_NtkFreeObjCnfs( Acb_Ntk_t * p ) { V
static inline Acb_ObjType_t Acb_ObjType( Acb_Ntk_t * p, int i ) { assert(i>0); return (Acb_ObjType_t)(int)(unsigned char)Vec_StrEntry(&p->vObjType, i); } static inline Acb_ObjType_t Acb_ObjType( Acb_Ntk_t * p, int i ) { assert(i>0); return (Acb_ObjType_t)(int)(unsigned char)Vec_StrEntry(&p->vObjType, i); }
static inline void Acb_ObjCleanType( Acb_Ntk_t * p, int i ) { assert(i>0); Vec_StrWriteEntry( &p->vObjType, i, (char)ABC_OPER_NONE ); } static inline void Acb_ObjCleanType( Acb_Ntk_t * p, int i ) { assert(i>0); Vec_StrWriteEntry( &p->vObjType, i, (char)ABC_OPER_NONE ); }
static inline int Acb_TypeIsSeq( Acb_ObjType_t Type ) { return Type >= ABC_OPER_RAM && Type <= ABC_OPER_DFFRS; } static inline int Acb_TypeIsSeq( Acb_ObjType_t Type ) { return Type >= ABC_OPER_RAM && Type <= ABC_OPER_DFFLAST; }
static inline int Acb_TypeIsUnary( Acb_ObjType_t Type ) { return Type == ABC_OPER_BIT_BUF || Type == ABC_OPER_BIT_INV || Type == ABC_OPER_LOGIC_NOT || Type == ABC_OPER_ARI_MIN || Type == ABC_OPER_ARI_SQRT || Type == ABC_OPER_ARI_ABS || (Type >= ABC_OPER_RED_AND && Type <= ABC_OPER_RED_NXOR); } static inline int Acb_TypeIsUnary( Acb_ObjType_t Type ) { return Type == ABC_OPER_BIT_BUF || Type == ABC_OPER_BIT_INV || Type == ABC_OPER_LOGIC_NOT || Type == ABC_OPER_ARI_MIN || Type == ABC_OPER_ARI_SQRT || Type == ABC_OPER_ARI_ABS || (Type >= ABC_OPER_RED_AND && Type <= ABC_OPER_RED_NXOR); }
static inline int Acb_TypeIsMux( Acb_ObjType_t Type ) { return Type == ABC_OPER_BIT_MUX || Type == ABC_OPER_SEL_NMUX || Type == ABC_OPER_SEL_SEL || Type == ABC_OPER_SEL_PSEL; } static inline int Acb_TypeIsMux( Acb_ObjType_t Type ) { return Type == ABC_OPER_BIT_MUX || Type == ABC_OPER_SEL_NMUX || Type == ABC_OPER_SEL_SEL || Type == ABC_OPER_SEL_PSEL; }
......
...@@ -44,10 +44,10 @@ ABC_NAMESPACE_HEADER_START ...@@ -44,10 +44,10 @@ ABC_NAMESPACE_HEADER_START
typedef enum { typedef enum {
WLC_OBJ_NONE = 0, // 00: unknown WLC_OBJ_NONE = 0, // 00: unknown
WLC_OBJ_PI, // 01: primary input WLC_OBJ_PI, // 01: primary input
WLC_OBJ_PO, // 02: primary output (unused) WLC_OBJ_PO, // 02: primary output
WLC_OBJ_FO, // 03: flop output WLC_OBJ_FO, // 03: flop output
WLC_OBJ_FI, // 04: flop input (unused) WLC_OBJ_FI, // 04: flop input (unused)
WLC_OBJ_FF, // 05: flop (unused) WLC_OBJ_FF, // 05: flop
WLC_OBJ_CONST, // 06: constant WLC_OBJ_CONST, // 06: constant
WLC_OBJ_BUF, // 07: buffer WLC_OBJ_BUF, // 07: buffer
WLC_OBJ_MUX, // 08: multiplexer WLC_OBJ_MUX, // 08: multiplexer
...@@ -98,7 +98,8 @@ typedef enum { ...@@ -98,7 +98,8 @@ typedef enum {
WLC_OBJ_TABLE, // 53: bit table WLC_OBJ_TABLE, // 53: bit table
WLC_OBJ_READ, // 54: read port WLC_OBJ_READ, // 54: read port
WLC_OBJ_WRITE, // 55: write port WLC_OBJ_WRITE, // 55: write port
WLC_OBJ_NUMBER // 56: unused WLC_OBJ_ARI_ADDSUB, // 56: adder-subtractor
WLC_OBJ_NUMBER // 57: unused
} Wlc_ObjType_t; } Wlc_ObjType_t;
// when adding new types, remember to update table Wlc_Names in "wlcNtk.c" // when adding new types, remember to update table Wlc_Names in "wlcNtk.c"
...@@ -142,6 +143,8 @@ struct Wlc_Ntk_t_ ...@@ -142,6 +143,8 @@ struct Wlc_Ntk_t_
int nObjs[WLC_OBJ_NUMBER]; // counter of objects of each type int nObjs[WLC_OBJ_NUMBER]; // counter of objects of each type
int nAnds[WLC_OBJ_NUMBER]; // counter of AND gates after blasting int nAnds[WLC_OBJ_NUMBER]; // counter of AND gates after blasting
int fSmtLib; // the network comes from an SMT-LIB file int fSmtLib; // the network comes from an SMT-LIB file
int fMemPorts; // the network contains memory ports
int fEasyFfs; // the network contains simple flops
int nAssert; // the number of asserts int nAssert; // the number of asserts
// memory for objects // memory for objects
Wlc_Obj_t * pObjs; Wlc_Obj_t * pObjs;
......
...@@ -1642,7 +1642,7 @@ usage: ...@@ -1642,7 +1642,7 @@ usage:
int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
{ {
extern void Wlc_NtkSimulateTest( Wlc_Ntk_t * p ); extern void Wlc_NtkSimulateTest( Wlc_Ntk_t * p );
Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); //Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc);
int c, fVerbose = 0; int c, fVerbose = 0;
Extra_UtilGetoptReset(); Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
...@@ -1658,11 +1658,12 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) ...@@ -1658,11 +1658,12 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage; goto usage;
} }
} }
if ( pNtk == NULL ) // if ( pNtk == NULL )
{ // {
Abc_Print( 1, "Abc_CommandTest(): There is no current design.\n" ); // Abc_Print( 1, "Abc_CommandTest(): There is no current design.\n" );
return 0; // return 0;
} // }
// transform // transform
//pNtk = Wlc_NtkUifNodePairs( pNtk, NULL ); //pNtk = Wlc_NtkUifNodePairs( pNtk, NULL );
//pNtk = Wlc_NtkAbstractNodes( pNtk, NULL ); //pNtk = Wlc_NtkAbstractNodes( pNtk, NULL );
...@@ -1671,9 +1672,9 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) ...@@ -1671,9 +1672,9 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
//Wlc_NtkSimulateTest( (Wlc_Ntk_t *)pAbc->pAbcWlc ); //Wlc_NtkSimulateTest( (Wlc_Ntk_t *)pAbc->pAbcWlc );
//pNtk = Wlc_NtkDupSingleNodes( pNtk ); //pNtk = Wlc_NtkDupSingleNodes( pNtk );
//Wlc_AbcUpdateNtk( pAbc, pNtk ); //Wlc_AbcUpdateNtk( pAbc, pNtk );
//Wlc_ReadNdrTest( pNtk ); Ndr_ModuleTestMemory();
pNtk = Wlc_NtkMemAbstractTest( pNtk ); //pNtk = Wlc_NtkMemAbstractTest( pNtk );
Wlc_AbcUpdateNtk( pAbc, pNtk ); //Wlc_AbcUpdateNtk( pAbc, pNtk );
return 0; return 0;
usage: usage:
Abc_Print( -2, "usage: %%test [-vh]\n" ); Abc_Print( -2, "usage: %%test [-vh]\n" );
......
...@@ -366,6 +366,8 @@ Wlc_Ntk_t * Wlc_NtkAbstractMemory( Wlc_Ntk_t * p, Vec_Int_t * vMemObjs, Vec_Int_ ...@@ -366,6 +366,8 @@ Wlc_Ntk_t * Wlc_NtkAbstractMemory( Wlc_Ntk_t * p, Vec_Int_t * vMemObjs, Vec_Int_
Wlc_NtkCleanCopy( p ); Wlc_NtkCleanCopy( p );
pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc + 1000 ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc + 1000 );
pNew->fSmtLib = p->fSmtLib; pNew->fSmtLib = p->fSmtLib;
pNew->fMemPorts = p->fMemPorts;
pNew->fEasyFfs = p->fEasyFfs;
pNew->vInits = Vec_IntAlloc( 100 ); pNew->vInits = Vec_IntAlloc( 100 );
// duplicate PIs // duplicate PIs
......
...@@ -91,6 +91,12 @@ int Ndr_TypeNdr2Wlc( int Type ) ...@@ -91,6 +91,12 @@ int Ndr_TypeNdr2Wlc( int Type )
if ( Type == ABC_OPER_ARI_MIN ) return WLC_OBJ_ARI_MINUS; // 50: arithmetic minus if ( Type == ABC_OPER_ARI_MIN ) return WLC_OBJ_ARI_MINUS; // 50: arithmetic minus
if ( Type == ABC_OPER_ARI_SQRT ) return WLC_OBJ_ARI_SQRT; // 51: integer square root if ( Type == ABC_OPER_ARI_SQRT ) return WLC_OBJ_ARI_SQRT; // 51: integer square root
if ( Type == ABC_OPER_ARI_SQUARE ) return WLC_OBJ_ARI_SQUARE; // 52: integer square if ( Type == ABC_OPER_ARI_SQUARE ) return WLC_OBJ_ARI_SQUARE; // 52: integer square
if ( Type == ABC_OPER_ARI_ADDSUB ) return WLC_OBJ_ARI_ADDSUB; // 56: adder-subtractor
if ( Type == ABC_OPER_ARI_SMUL ) return WLC_OBJ_ARI_MULTI; // 45: signed multiplier
if ( Type == ABC_OPER_DFF ) return WLC_OBJ_FO; // 03: flop
if ( Type == ABC_OPER_DFFRSE ) return WLC_OBJ_FF; // 05: flop
if ( Type == ABC_OPER_RAMR ) return WLC_OBJ_READ; // 54: read port
if ( Type == ABC_OPER_RAMW ) return WLC_OBJ_WRITE; // 55: write port
return -1; return -1;
} }
int Ndr_TypeWlc2Ndr( int Type ) int Ndr_TypeWlc2Ndr( int Type )
...@@ -142,6 +148,12 @@ int Ndr_TypeWlc2Ndr( int Type ) ...@@ -142,6 +148,12 @@ int Ndr_TypeWlc2Ndr( int Type )
if ( Type == WLC_OBJ_ARI_MINUS ) return ABC_OPER_ARI_MIN; // 50: arithmetic minus if ( Type == WLC_OBJ_ARI_MINUS ) return ABC_OPER_ARI_MIN; // 50: arithmetic minus
if ( Type == WLC_OBJ_ARI_SQRT ) return ABC_OPER_ARI_SQRT; // 51: integer square root if ( Type == WLC_OBJ_ARI_SQRT ) return ABC_OPER_ARI_SQRT; // 51: integer square root
if ( Type == WLC_OBJ_ARI_SQUARE ) return ABC_OPER_ARI_SQUARE; // 52: integer square if ( Type == WLC_OBJ_ARI_SQUARE ) return ABC_OPER_ARI_SQUARE; // 52: integer square
if ( Type == WLC_OBJ_ARI_ADDSUB ) return ABC_OPER_ARI_ADDSUB; // 56: adder-subtractor
if ( Type == WLC_OBJ_ARI_MULTI ) return ABC_OPER_ARI_SMUL; // 45: signed multiplier
if ( Type == WLC_OBJ_FO ) return ABC_OPER_DFF; // 03: flop
if ( Type == WLC_OBJ_FF ) return ABC_OPER_DFFRSE; // 05: flop
if ( Type == WLC_OBJ_READ ) return ABC_OPER_RAMR; // 54: read port
if ( Type == WLC_OBJ_WRITE ) return ABC_OPER_RAMW; // 55: write port
return -1; return -1;
} }
...@@ -337,6 +349,7 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) ...@@ -337,6 +349,7 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData )
int Mod = 2, i, k, Obj, * pArray, nDigits, fFound, NameId, NameIdMax; int Mod = 2, i, k, Obj, * pArray, nDigits, fFound, NameId, NameIdMax;
Wlc_Ntk_t * pTemp, * pNtk = Wlc_NtkAlloc( "top", Ndr_DataObjNum(p, Mod)+1 ); Wlc_Ntk_t * pTemp, * pNtk = Wlc_NtkAlloc( "top", Ndr_DataObjNum(p, Mod)+1 );
Wlc_NtkCheckIntegrity( pData ); Wlc_NtkCheckIntegrity( pData );
Vec_IntClear( &pNtk->vFfs );
//pNtk->pSpec = Abc_UtilStrsav( pFileName ); //pNtk->pSpec = Abc_UtilStrsav( pFileName );
// construct network and save name IDs // construct network and save name IDs
Wlc_NtkCleanNameId( pNtk ); Wlc_NtkCleanNameId( pNtk );
...@@ -357,6 +370,25 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) ...@@ -357,6 +370,25 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData )
int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT );
Vec_IntClear( vFanins ); Vec_IntClear( vFanins );
Vec_IntAppend( vFanins, vTemp ); Vec_IntAppend( vFanins, vTemp );
if ( Type == ABC_OPER_DFF )
{
// save init state
if ( pNtk->vInits == NULL )
pNtk->vInits = Vec_IntAlloc( 100 );
if ( Vec_IntSize(vFanins) == 2 )
Vec_IntPush( pNtk->vInits, Vec_IntPop(vFanins) );
else // assume const0 if init is not given
Vec_IntPush( pNtk->vInits, -(End-Beg+1) );
// save flop output
pObj = Wlc_NtkObj(pNtk, iObj);
assert( Wlc_ObjType(pObj) == WLC_OBJ_FO );
Wlc_ObjSetNameId( pNtk, iObj, NameId );
Vec_IntPush( &pNtk->vFfs, NameId );
// save flop input
assert( Vec_IntSize(vFanins) == 1 );
Vec_IntPush( &pNtk->vFfs, Vec_IntEntry(vFanins, 0) );
continue;
}
if ( Type == ABC_OPER_SLICE ) if ( Type == ABC_OPER_SLICE )
Vec_IntPushTwo( vFanins, End, Beg ); Vec_IntPushTwo( vFanins, End, Beg );
else if ( Type == ABC_OPER_CONST ) else if ( Type == ABC_OPER_CONST )
...@@ -365,6 +397,13 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) ...@@ -365,6 +397,13 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData )
ABC_SWAP( int, Vec_IntEntryP(vFanins, 1)[0], Vec_IntEntryP(vFanins, 2)[0] ); ABC_SWAP( int, Vec_IntEntryP(vFanins, 1)[0], Vec_IntEntryP(vFanins, 2)[0] );
Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), vFanins ); Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), vFanins );
Wlc_ObjSetNameId( pNtk, iObj, NameId ); Wlc_ObjSetNameId( pNtk, iObj, NameId );
if ( Type == ABC_OPER_ARI_SMUL )
{
pObj = Wlc_NtkObj(pNtk, iObj);
assert( Wlc_ObjFaninNum(pObj) == 2 );
Wlc_ObjFanin0(pNtk, pObj)->Signed = 1;
Wlc_ObjFanin1(pNtk, pObj)->Signed = 1;
}
} }
// mark primary outputs // mark primary outputs
Ndr_ModForEachPo( p, Mod, Obj ) Ndr_ModForEachPo( p, Mod, Obj )
...@@ -388,6 +427,27 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) ...@@ -388,6 +427,27 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData )
for ( k = 0; k < Wlc_ObjFaninNum(pObj); k++ ) for ( k = 0; k < Wlc_ObjFaninNum(pObj); k++ )
pFanins[k] = Vec_IntEntry(vName2Obj, pFanins[k]); pFanins[k] = Vec_IntEntry(vName2Obj, pFanins[k]);
} }
if ( pNtk->vInits )
{
Vec_IntForEachEntry( &pNtk->vFfs, NameId, i )
Vec_IntWriteEntry( &pNtk->vFfs, i, Vec_IntEntry(vName2Obj, NameId) );
Vec_IntForEachEntry( pNtk->vInits, NameId, i )
if ( NameId > 0 )
Vec_IntWriteEntry( pNtk->vInits, i, Vec_IntEntry(vName2Obj, NameId) );
// move FO/FI to be part of CI/CO
assert( (Vec_IntSize(&pNtk->vFfs) & 1) == 0 );
assert( Vec_IntSize(&pNtk->vFfs) == 2 * Vec_IntSize(pNtk->vInits) );
Wlc_NtkForEachFf( pNtk, pObj, i )
if ( i & 1 )
Wlc_ObjSetCo( pNtk, pObj, 1 );
//else
// Wlc_ObjSetCi( pNtk, pObj );
Vec_IntClear( &pNtk->vFfs );
// convert init values into binary string
//Vec_IntPrint( &p->pNtk->vInits );
pNtk->pInits = Wlc_PrsConvertInitValues( pNtk );
//printf( "%s", p->pNtk->pInits );
}
Vec_IntFree(vName2Obj); Vec_IntFree(vName2Obj);
// create fake object names // create fake object names
NameIdMax = Vec_IntFindMax(&pNtk->vNameIds); NameIdMax = Vec_IntFindMax(&pNtk->vNameIds);
...@@ -395,14 +455,17 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) ...@@ -395,14 +455,17 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData )
pNtk->pManName = Abc_NamStart( NameIdMax+1, 10 ); pNtk->pManName = Abc_NamStart( NameIdMax+1, 10 );
for ( i = 1; i <= NameIdMax; i++ ) for ( i = 1; i <= NameIdMax; i++ )
{ {
char pName[20]; sprintf( pName, "n%0*d", nDigits, i ); char pName[20]; sprintf( pName, "s%0*d", nDigits, i );
NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound ); NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound );
assert( !fFound && i == NameId ); assert( !fFound && i == NameId );
} }
//Ndr_NtkPrintNodes( pNtk );
// derive topological order // derive topological order
pNtk = Wlc_NtkDupDfs( pTemp = pNtk, 0, 1 ); pNtk = Wlc_NtkDupDfs( pTemp = pNtk, 0, 1 );
Wlc_NtkFree( pTemp ); Wlc_NtkFree( pTemp );
//Ndr_NtkPrintNodes( pNtk ); //Ndr_NtkPrintNodes( pNtk );
pNtk->fMemPorts = 1; // the network contains memory ports
pNtk->fEasyFfs = 1; // the network contains simple flops
return pNtk; return pNtk;
} }
......
...@@ -860,6 +860,7 @@ void Wlc_NtkDupDfs_rec( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, int iObj, Vec_Int_t * v ...@@ -860,6 +860,7 @@ void Wlc_NtkDupDfs_rec( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, int iObj, Vec_Int_t * v
int i, iFanin; int i, iFanin;
if ( Wlc_ObjCopy(p, iObj) ) if ( Wlc_ObjCopy(p, iObj) )
return; return;
//printf( "Visiting node %d\n", iObj );
pObj = Wlc_NtkObj( p, iObj ); pObj = Wlc_NtkObj( p, iObj );
Wlc_ObjForEachFanin( pObj, iFanin, i ) Wlc_ObjForEachFanin( pObj, iFanin, i )
Wlc_NtkDupDfs_rec( pNew, p, iFanin, vFanins ); Wlc_NtkDupDfs_rec( pNew, p, iFanin, vFanins );
...@@ -876,6 +877,8 @@ Wlc_Ntk_t * Wlc_NtkDupDfsSimple( Wlc_Ntk_t * p ) ...@@ -876,6 +877,8 @@ Wlc_Ntk_t * Wlc_NtkDupDfsSimple( Wlc_Ntk_t * p )
vFanins = Vec_IntAlloc( 100 ); vFanins = Vec_IntAlloc( 100 );
pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc );
pNew->fSmtLib = p->fSmtLib; pNew->fSmtLib = p->fSmtLib;
pNew->fMemPorts = p->fMemPorts;
pNew->fEasyFfs = p->fEasyFfs;
Wlc_NtkForEachCi( p, pObj, i ) Wlc_NtkForEachCi( p, pObj, i )
Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins ); Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins );
Wlc_NtkForEachCo( p, pObj, i ) Wlc_NtkForEachCo( p, pObj, i )
...@@ -902,6 +905,8 @@ Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p, int fMarked, int fSeq ) ...@@ -902,6 +905,8 @@ Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p, int fMarked, int fSeq )
Wlc_NtkCleanCopy( p ); Wlc_NtkCleanCopy( p );
pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc );
pNew->fSmtLib = p->fSmtLib; pNew->fSmtLib = p->fSmtLib;
pNew->fMemPorts = p->fMemPorts;
pNew->fEasyFfs = p->fEasyFfs;
Wlc_NtkForEachCi( p, pObj, i ) Wlc_NtkForEachCi( p, pObj, i )
if ( !fMarked || pObj->Mark ) if ( !fMarked || pObj->Mark )
{ {
...@@ -951,6 +956,8 @@ Wlc_Ntk_t * Wlc_NtkDupDfsAbs( Wlc_Ntk_t * p, Vec_Int_t * vPisOld, Vec_Int_t * vP ...@@ -951,6 +956,8 @@ Wlc_Ntk_t * Wlc_NtkDupDfsAbs( Wlc_Ntk_t * p, Vec_Int_t * vPisOld, Vec_Int_t * vP
Wlc_NtkCleanCopy( p ); Wlc_NtkCleanCopy( p );
pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc );
pNew->fSmtLib = p->fSmtLib; pNew->fSmtLib = p->fSmtLib;
pNew->fMemPorts = p->fMemPorts;
pNew->fEasyFfs = p->fEasyFfs;
// duplicate marked PIs // duplicate marked PIs
vFanins = Vec_IntAlloc( 100 ); vFanins = Vec_IntAlloc( 100 );
...@@ -1132,6 +1139,8 @@ Wlc_Ntk_t * Wlc_NtkDupSingleNodes( Wlc_Ntk_t * p ) ...@@ -1132,6 +1139,8 @@ Wlc_Ntk_t * Wlc_NtkDupSingleNodes( Wlc_Ntk_t * p )
vFanins = Vec_IntAlloc( 100 ); vFanins = Vec_IntAlloc( 100 );
pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc );
pNew->fSmtLib = p->fSmtLib; pNew->fSmtLib = p->fSmtLib;
pNew->fMemPorts = p->fMemPorts;
pNew->fEasyFfs = p->fEasyFfs;
Wlc_NtkForEachObj( p, pObj, i ) Wlc_NtkForEachObj( p, pObj, i )
{ {
if ( Wlc_ObjIsCi(pObj) ) if ( Wlc_ObjIsCi(pObj) )
......
...@@ -1275,6 +1275,123 @@ startword: ...@@ -1275,6 +1275,123 @@ startword:
// printf( "Created flop %s with range %d and init value %d (nameId = %d)\n", // printf( "Created flop %s with range %d and init value %d (nameId = %d)\n",
// Abc_NamStr(p->pNtk->pManName, NameIdOut), Wlc_ObjRange(pObj), nBits, NameId ); // Abc_NamStr(p->pNtk->pManName, NameIdOut), Wlc_ObjRange(pObj), nBits, NameId );
} }
else if ( Wlc_PrsStrCmp( pStart, "ABC_DFFRSE" ) )
{
int NameId[8], fFound, nBits = 1, fFlopIn, fFlopOut, fFlopClk, fFlopRst, fFlopSet, fFlopEna, fFlopAsync, fFlopInit;
pStart += strlen("ABC_DFF");
while ( 1 )
{
pStart = Wlc_PrsFindSymbol( pStart, '.' );
if ( pStart == NULL )
break;
pStart = Wlc_PrsSkipSpaces( pStart+1 );
fFlopIn = (pStart[0] == 'd');
fFlopOut = (pStart[0] == 'q');
fFlopClk = (pStart[0] == 'c');
fFlopRst = (pStart[0] == 'r');
fFlopSet = (pStart[0] == 's');
fFlopEna = (pStart[0] == 'e');
fFlopAsync = (pStart[0] == 'a');
fFlopInit = (pStart[0] == 'i');
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." );
if ( fFlopIn )
NameId[0] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopOut )
NameId[7] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopClk )
NameId[1] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopRst )
NameId[2] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopSet )
NameId[3] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopEna )
NameId[4] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopAsync )
NameId[5] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopInit )
NameId[6] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else
assert( 0 );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
}
if ( NameId[0] == -1 || NameId[7] == -1 )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name of flop input or flop output is missing." );
// create output
pObj = Wlc_NtkObj( p->pNtk, NameId[7] );
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_FF );
Vec_IntClear( p->vFanins );
Vec_IntPush( p->vFanins, NameId[0] );
Vec_IntPush( p->vFanins, NameId[1] );
Vec_IntPush( p->vFanins, NameId[2] );
Vec_IntPush( p->vFanins, NameId[3] );
Vec_IntPush( p->vFanins, NameId[4] );
Vec_IntPush( p->vFanins, NameId[5] );
Vec_IntPush( p->vFanins, NameId[6] );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
}
else if ( Wlc_PrsStrCmp( pStart, "ABC_DFF" ) )
{
int NameId = -1, NameIdIn = -1, NameIdOut = -1, fFound, nBits = 1, fFlopIn, fFlopOut;
pStart += strlen("ABC_DFFRSE");
while ( 1 )
{
pStart = Wlc_PrsFindSymbol( pStart, '.' );
if ( pStart == NULL )
break;
pStart = Wlc_PrsSkipSpaces( pStart+1 );
fFlopIn = (pStart[0] == 'd');
fFlopOut = (pStart[0] == 'q');
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." );
if ( fFlopIn )
NameIdIn = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopOut )
NameIdOut = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else
NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
}
if ( NameIdIn == -1 || NameIdOut == -1 )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name of flop input or flop output is missing." );
// create flop output
pObj = Wlc_NtkObj( p->pNtk, NameIdOut );
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_FO );
Vec_IntPush( &p->pNtk->vFfs, NameIdOut );
nBits = Wlc_ObjRange(Wlc_NtkObj(p->pNtk, NameIdOut));
// create flop input
pObj = Wlc_NtkObj( p->pNtk, NameIdIn );
Vec_IntPush( &p->pNtk->vFfs, NameIdIn );
// compare bit-width
if ( Wlc_ObjRange(Wlc_NtkObj(p->pNtk, NameIdIn)) != nBits )
printf( "Warning! Flop input \"%s\" bit-width (%d) is different from that of flop output (%d)\n",
Abc_NamStr(p->pNtk->pManName, NameId), Wlc_ObjRange(Wlc_NtkObj(p->pNtk, NameIdIn)), nBits );
// save flop init value
if ( NameId == -1 )
printf( "Initial value of flop \"%s\" is not specified. Zero is assumed.\n", Abc_NamStr(p->pNtk->pManName, NameIdOut) );
else
{
if ( Wlc_ObjRange(Wlc_NtkObj(p->pNtk, NameId)) != nBits )
printf( "Warning! Flop init signal \"%s\" bit-width (%d) is different from that of flop output (%d)\n",
Abc_NamStr(p->pNtk->pManName, NameId), Wlc_ObjRange(Wlc_NtkObj(p->pNtk, NameId)), nBits );
}
if ( p->pNtk->vInits == NULL )
p->pNtk->vInits = Vec_IntAlloc( 100 );
Vec_IntPush( p->pNtk->vInits, NameId > 0 ? NameId : -Wlc_ObjRange(Wlc_NtkObj(p->pNtk, NameIdOut)) );
// printf( "Created flop %s with range %d and init value %d (nameId = %d)\n",
// Abc_NamStr(p->pNtk->pManName, NameIdOut), Wlc_ObjRange(pObj), nBits, NameId );
p->pNtk->fEasyFfs = 1;
}
else if ( Wlc_PrsStrCmp( pStart, "CPL_MEM_" ) ) else if ( Wlc_PrsStrCmp( pStart, "CPL_MEM_" ) )
{ {
int * pNameId = NULL, NameOutput, NameMi = -1, NameMo = -1, NameAddr = -1, NameDi = -1, NameDo = -1, fFound, fRead = 1; int * pNameId = NULL, NameOutput, NameMi = -1, NameMo = -1, NameAddr = -1, NameDi = -1, NameDo = -1, fFound, fRead = 1;
...@@ -1324,6 +1441,87 @@ startword: ...@@ -1324,6 +1441,87 @@ startword:
//printf( "Memory %s ", fRead ? "Read" : "Write" ); printf( "Fanins: " ); Vec_IntPrint( p->vFanins ); //printf( "Memory %s ", fRead ? "Read" : "Write" ); printf( "Fanins: " ); Vec_IntPrint( p->vFanins );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins ); Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
} }
else if ( Wlc_PrsStrCmp( pStart, "ABC_READ" ) )
{
int * pNameId = NULL, NameMemIn = -1, NameData = -1, NameAddr = -1, fFound;
pStart += strlen("ABC_READ");
while ( 1 )
{
pStart = Wlc_PrsFindSymbol( pStart, '.' );
if ( pStart == NULL )
break;
pStart = Wlc_PrsSkipSpaces( pStart+1 );
if ( !strncmp(pStart, "mem_in", 6) )
pNameId = &NameMemIn;
else if ( !strncmp(pStart, "addr", 4) )
pNameId = &NameAddr;
else if ( !strncmp(pStart, "data", 4) )
pNameId = &NameData;
else
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name of the input/output port." );
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." );
*pNameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
}
if ( NameMemIn == -1 || NameAddr == -1 || NameData == -1 )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name of one of signals of read port is missing." );
// create output
pObj = Wlc_NtkObj( p->pNtk, NameData );
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_READ );
Vec_IntClear( p->vFanins );
Vec_IntPush( p->vFanins, NameMemIn );
Vec_IntPush( p->vFanins, NameAddr );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
p->pNtk->fMemPorts = 1;
}
else if ( Wlc_PrsStrCmp( pStart, "ABC_WRITE" ) )
{
int * pNameId = NULL, NameMemIn = -1, NameMemOut = -1, NameData = -1, NameAddr = -1, fFound;
pStart += strlen("ABC_WRITE");
while ( 1 )
{
pStart = Wlc_PrsFindSymbol( pStart, '.' );
if ( pStart == NULL )
break;
pStart = Wlc_PrsSkipSpaces( pStart+1 );
if ( !strncmp(pStart, "mem_in", 6) )
pNameId = &NameMemIn;
else if ( !strncmp(pStart, "mem_out", 7) )
pNameId = &NameMemOut;
else if ( !strncmp(pStart, "data", 4) )
pNameId = &NameData;
else if ( !strncmp(pStart, "addr", 4) )
pNameId = &NameAddr;
else
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name of the input/output port." );
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." );
*pNameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
}
if ( NameMemIn == -1 || NameAddr == -1 || NameData == -1 || NameMemOut == -1 )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name of one of signals of write port is missing." );
// create output
pObj = Wlc_NtkObj( p->pNtk, NameMemOut );
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_WRITE );
Vec_IntClear( p->vFanins );
Vec_IntPush( p->vFanins, NameMemIn );
Vec_IntPush( p->vFanins, NameAddr );
Vec_IntPush( p->vFanins, NameData );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
p->pNtk->fMemPorts = 1;
}
else if ( pStart[0] == '(' && pStart[1] == '*' ) // skip comments else if ( pStart[0] == '(' && pStart[1] == '*' ) // skip comments
{ {
while ( *pStart++ != ')' ); while ( *pStart++ != ')' );
......
...@@ -186,13 +186,13 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) ...@@ -186,13 +186,13 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
continue; continue;
Range[0] = 0; Range[0] = 0;
} }
if ( pObj->fIsPo || (fNoFlops && pObj->fIsFi) ) if ( (pObj->fIsPo || (fNoFlops && pObj->fIsFi)) && pObj->Type != WLC_OBJ_FF )
{ {
if ( Wlc_ObjFaninNum(pObj) == 0 ) if ( Wlc_ObjFaninNum(pObj) == 0 )
continue; continue;
fprintf( pFile, " assign " ); fprintf( pFile, " assign " );
} }
else if ( pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3 ) else if ( (pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3) || pObj->Type == WLC_OBJ_FF )
fprintf( pFile, "reg %s ", Range ); fprintf( pFile, "reg %s ", Range );
else else
fprintf( pFile, "wire %s ", Range ); fprintf( pFile, "wire %s ", Range );
...@@ -255,6 +255,18 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) ...@@ -255,6 +255,18 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
} }
else if ( pObj->Type == WLC_OBJ_READ || pObj->Type == WLC_OBJ_WRITE ) else if ( pObj->Type == WLC_OBJ_READ || pObj->Type == WLC_OBJ_WRITE )
{ {
if ( p->fMemPorts )
{
fprintf( pFile, "%s ;\n", Wlc_ObjName(p, i) );
fprintf( pFile, " " );
fprintf( pFile, "%s (", pObj->Type == WLC_OBJ_READ ? "ABC_READ" : "ABC_WRITE" );
Wlc_ObjForEachFanin( pObj, iFanin, k )
fprintf( pFile, " .%s(%s)", k==0 ? "mem_in" : (k==1 ? "addr": "data"), Wlc_ObjName(p, iFanin) );
fprintf( pFile, " .%s(%s) ) ;\n", pObj->Type == WLC_OBJ_READ ? "data" : "mem_out", Wlc_ObjName(p, i) );
continue;
}
else
{
int nBitsMem = Wlc_ObjRange( Wlc_ObjFanin(p, pObj, 0) ); int nBitsMem = Wlc_ObjRange( Wlc_ObjFanin(p, pObj, 0) );
//int nBitsAddr = Wlc_ObjRange( Wlc_ObjFanin(p, pObj, 1) ); //int nBitsAddr = Wlc_ObjRange( Wlc_ObjFanin(p, pObj, 1) );
int nBitsDat = pObj->Type == WLC_OBJ_READ ? Wlc_ObjRange(pObj) : Wlc_ObjRange(Wlc_ObjFanin(p, pObj, 2)); int nBitsDat = pObj->Type == WLC_OBJ_READ ? Wlc_ObjRange(pObj) : Wlc_ObjRange(Wlc_ObjFanin(p, pObj, 2));
...@@ -265,7 +277,19 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) ...@@ -265,7 +277,19 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
fprintf( pFile, "%s_%d (", pObj->Type == WLC_OBJ_READ ? "CPL_MEM_READ" : "CPL_MEM_WRITE", Depth ); fprintf( pFile, "%s_%d (", pObj->Type == WLC_OBJ_READ ? "CPL_MEM_READ" : "CPL_MEM_WRITE", Depth );
Wlc_ObjForEachFanin( pObj, iFanin, k ) Wlc_ObjForEachFanin( pObj, iFanin, k )
fprintf( pFile, " .%s(%s)", k==0 ? "mem_data_in" : (k==1 ? "addr_in": "data_in"), Wlc_ObjName(p, iFanin) ); fprintf( pFile, " .%s(%s)", k==0 ? "mem_data_in" : (k==1 ? "addr_in": "data_in"), Wlc_ObjName(p, iFanin) );
fprintf( pFile, " .%s(%s) );\n", "data_out", Wlc_ObjName(p, i) ); fprintf( pFile, " .%s(%s) ) ;\n", "data_out", Wlc_ObjName(p, i) );
continue;
}
}
else if ( pObj->Type == WLC_OBJ_FF )
{
char * pInNames[7] = {"d", "clk", "reset", "set", "enable", "async", "init"};
fprintf( pFile, "%s ;\n", Wlc_ObjName(p, i) );
fprintf( pFile, " " );
fprintf( pFile, "%s (", "ABC_DFFRSE" );
Wlc_ObjForEachFanin( pObj, iFanin, k )
fprintf( pFile, " .%s(%s)", pInNames[k], Wlc_ObjName(p, iFanin) );
fprintf( pFile, " .%s(%s) ) ;\n", "q", Wlc_ObjName(p, i) );
continue; continue;
} }
else else
...@@ -426,23 +450,36 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) ...@@ -426,23 +450,36 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
if ( pObj->Type == WLC_OBJ_PI ) if ( pObj->Type == WLC_OBJ_PI )
continue; continue;
fprintf( pFile, " " ); fprintf( pFile, " " );
if ( p->fEasyFfs )
{
fprintf( pFile, "ABC_DFF" );
fprintf( pFile, " reg%d (", i );
fprintf( pFile, " .q(%s),", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) );
fprintf( pFile, " .d(%s),", Wlc_ObjName(p, Wlc_ObjId(p, Wlc_ObjFo2Fi(p, pObj))) );
if ( p->vInits )
fprintf( pFile, " .init(%s_init)", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) );
fprintf( pFile, " ) ;\n" );
}
else
{
fprintf( pFile, "CPL_FF" ); fprintf( pFile, "CPL_FF" );
if ( Wlc_ObjRange(pObj) > 1 ) if ( Wlc_ObjRange(pObj) > 1 )
fprintf( pFile, "#%d%*s", Wlc_ObjRange(pObj), 4 - Abc_Base10Log(Wlc_ObjRange(pObj)+1), "" ); fprintf( pFile, "#%d%*s", Wlc_ObjRange(pObj), 4 - Abc_Base10Log(Wlc_ObjRange(pObj)+1), "" );
else else
fprintf( pFile, " " ); fprintf( pFile, " " );
fprintf( pFile, " reg%d (", i ); fprintf( pFile, " reg%d (", i );
fprintf( pFile, " .q( %s ),", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) ); fprintf( pFile, " .q(%s),", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) );
fprintf( pFile, " .qbar()," ); fprintf( pFile, " .qbar()," );
fprintf( pFile, " .d( %s ),", Wlc_ObjName(p, Wlc_ObjId(p, Wlc_ObjFo2Fi(p, pObj))) ); fprintf( pFile, " .d(%s),", Wlc_ObjName(p, Wlc_ObjId(p, Wlc_ObjFo2Fi(p, pObj))) );
fprintf( pFile, " .clk( %s ),", "1\'b0" ); fprintf( pFile, " .clk(%s),", "1\'b0" );
fprintf( pFile, " .arst( %s ),", "1\'b0" ); fprintf( pFile, " .arst(%s),", "1\'b0" );
if ( p->vInits ) if ( p->vInits )
fprintf( pFile, " .arstval( %s_init )", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) ); fprintf( pFile, " .arstval(%s_init)", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) );
else else
fprintf( pFile, " .arstval( %s )", "1\'b0" ); fprintf( pFile, " .arstval(%s)", "1\'b0" );
fprintf( pFile, " ) ;\n" ); fprintf( pFile, " ) ;\n" );
} }
}
assert( !p->vInits || iFanin == (int)strlen(p->pInits) ); assert( !p->vInits || iFanin == (int)strlen(p->pInits) );
} }
fprintf( pFile, "endmodule\n\n" ); fprintf( pFile, "endmodule\n\n" );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment