Commit f23ea8e3 by Alan Mishchenko

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

parent 89c981c6
......@@ -138,8 +138,8 @@ typedef enum {
ABC_OPER_LATCH, // 86
ABC_OPER_LATCHRS, // 87
ABC_OPER_DFF, // 88
ABC_OPER_DFFCPL, // 89
ABC_OPER_DFFRS, // 90
ABC_OPER_DFFRSE, // 89
ABC_OPER_DFFLAST, // 90
ABC_OPER_SLICE, // 91
ABC_OPER_CONCAT, // 92
......
......@@ -42,61 +42,51 @@ ABC_NAMESPACE_HEADER_START
/*
For the lack of a better name, this format is called New Data Representation (NDR).
NDR is based on the following principles:
- complex data is composed of individual records
- 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
- 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
- the format should be simple, easy to use, low-memory, and extensible
- new record types can be added by the user as needed
The implementation is based on the following ideas:
- a record is composed of two parts (the header followed by the body)
- the header contains two items (the record type and the body size, measured in terms of 4-byte integers)
- the body contains as many entries as stated in the record size
- if a record is composed of other records, its body contains these records
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),
The body of the record is composed of one unsigned integer representing the name (say, 357).
So the complete record looks as follows: { <header>, <body> } = { {NDR_NAME, 1}, {357} }.
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
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},
{{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
(name ID, gate type, first fanin, second fanin).
Headers and bodies of all objects are stored differently. Headers are stored in an array of unsigned chars,
while bodies are stored in the array of 4-byte unsigned integers. This is important for memory efficiency.
However, the user does not see these details.
To estimate memory usage, we can assume that each header takes 1 byte and each body entry contains 4 bytes.
A name takes 5 bytes, and an AND-gate takes 1 * NumHeaders + 4 * NumBodyEntries = 1 * 4 + 4 * 4 = 20 bytes.
Not bad. The same as memory usage in a well-designed AIG package with structural hashing.
Comments:
- 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
- primary input and primary output objects have to be explicitly created (as shown in the example below)
- object inputs are name IDs of the driving nets; object outputs are name IDs of the driven nets
- 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,
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
- 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().
NDR is designed as an interchange format to pass hierarchical word-level designs between the tools.
It is relatively simple, uses little memory, and can be easily converted into other ABC data-structures.
This tutorial discusses how to construct the NDR representation of a hierarchical word-level design.
First, all names used in the design (including the design name, module names, port names, net names,
instance names, etc) are hashed into 1-based integers called "name IDs". Nets are not explicitly represented.
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 design is initialized using procedure Ndr_Create(), which takes the design name as an argument.
A module in the design is initialized using procedure Ndr_AddModule(), which take the design and
the module name as arguments. Objects are added to a module in any order using procedure Ndr_AddObject().
Primary input and primary output objects should be explicitly created, as shown in the examples below.
Instances of known operators listed in file "abcOper.h" are assumed to have one output. The only known
issue due to this restriction concerns an adder, which produces a sum and a carry-out. To make sure the
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.
Instances of hierarchical modules defined by the user can have multiple outputs.
Bit-slice and concatenation operators should be represented as separate objects.
If the ordering of inputs/outputs/flops of a module is not provided as a separate record in NDR format,
their ordering is determined by the order of their appearance of their records in the body of the module.
If left limit and right limit of a range are equal, it is assumed that the range contains one bit
If range limits and signedness are all 0, it is assumed that it is the bit-width is equal to 1.
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" and is given as an argument
(char * pFunction) to the procedure Ndr_AddObject().
Currently two types of flops are supported: a simple flop with implicit clock with two fanins (data and init)
and a complex flop with 7 fanins (clock, data, reset, set, enable, async, init), as shown in the examples below.
The initial value of a flop is represented by input "init", which can be driven by a constant or by a primary
input of the module. If it is a primary input, is it assumed that the flop is not initialized. If the input
"init" is not driven, it is assumed that the flop is initialized to 0.
Memory read and write ports are supported, as shown in the example below.
(to be continued)
*/
////////////////////////////////////////////////////////////////////////
......@@ -377,7 +367,7 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod
if ( Type >= 256 )
{
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, "( " );
nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
......@@ -386,6 +376,64 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod
fprintf( pFile, ");\n" );
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) );
nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
if ( nArray == 0 )
......@@ -551,7 +599,7 @@ static inline void Ndr_Write( char * pFileName, void * pDesign )
////////////////////////////////////////////////////////////////////////
// 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 );
// wire [3:0] const10 = 4'b1010;
......@@ -589,7 +637,7 @@ static inline void Ndr_ModuleTest()
// 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 );
// wire [3:0] a0 = a[3:0];
......@@ -676,7 +724,7 @@ static inline void Ndr_ModuleTestAdder()
}
// 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 );
// assign out = sel ? d1 : d0;
......@@ -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
#endif
......
......@@ -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 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_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
typedef enum {
WLC_OBJ_NONE = 0, // 00: unknown
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_FI, // 04: flop input (unused)
WLC_OBJ_FF, // 05: flop (unused)
WLC_OBJ_FF, // 05: flop
WLC_OBJ_CONST, // 06: constant
WLC_OBJ_BUF, // 07: buffer
WLC_OBJ_MUX, // 08: multiplexer
......@@ -98,7 +98,8 @@ typedef enum {
WLC_OBJ_TABLE, // 53: bit table
WLC_OBJ_READ, // 54: read 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;
// when adding new types, remember to update table Wlc_Names in "wlcNtk.c"
......@@ -142,6 +143,8 @@ struct Wlc_Ntk_t_
int nObjs[WLC_OBJ_NUMBER]; // counter of objects of each type
int nAnds[WLC_OBJ_NUMBER]; // counter of AND gates after blasting
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
// memory for objects
Wlc_Obj_t * pObjs;
......
......@@ -1642,7 +1642,7 @@ usage:
int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
{
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;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
......@@ -1658,11 +1658,12 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
}
}
if ( pNtk == NULL )
{
Abc_Print( 1, "Abc_CommandTest(): There is no current design.\n" );
return 0;
}
// if ( pNtk == NULL )
// {
// Abc_Print( 1, "Abc_CommandTest(): There is no current design.\n" );
// return 0;
// }
// transform
//pNtk = Wlc_NtkUifNodePairs( pNtk, NULL );
//pNtk = Wlc_NtkAbstractNodes( pNtk, NULL );
......@@ -1671,9 +1672,9 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
//Wlc_NtkSimulateTest( (Wlc_Ntk_t *)pAbc->pAbcWlc );
//pNtk = Wlc_NtkDupSingleNodes( pNtk );
//Wlc_AbcUpdateNtk( pAbc, pNtk );
//Wlc_ReadNdrTest( pNtk );
pNtk = Wlc_NtkMemAbstractTest( pNtk );
Wlc_AbcUpdateNtk( pAbc, pNtk );
Ndr_ModuleTestMemory();
//pNtk = Wlc_NtkMemAbstractTest( pNtk );
//Wlc_AbcUpdateNtk( pAbc, pNtk );
return 0;
usage:
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_
Wlc_NtkCleanCopy( p );
pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc + 1000 );
pNew->fSmtLib = p->fSmtLib;
pNew->fMemPorts = p->fMemPorts;
pNew->fEasyFfs = p->fEasyFfs;
pNew->vInits = Vec_IntAlloc( 100 );
// duplicate PIs
......
......@@ -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_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_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;
}
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_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_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;
}
......@@ -337,6 +349,7 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData )
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_NtkCheckIntegrity( pData );
Vec_IntClear( &pNtk->vFfs );
//pNtk->pSpec = Abc_UtilStrsav( pFileName );
// construct network and save name IDs
Wlc_NtkCleanNameId( pNtk );
......@@ -357,6 +370,25 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData )
int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT );
Vec_IntClear( vFanins );
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 )
Vec_IntPushTwo( vFanins, End, Beg );
else if ( Type == ABC_OPER_CONST )
......@@ -365,6 +397,13 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData )
ABC_SWAP( int, Vec_IntEntryP(vFanins, 1)[0], Vec_IntEntryP(vFanins, 2)[0] );
Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), vFanins );
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
Ndr_ModForEachPo( p, Mod, Obj )
......@@ -388,6 +427,27 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData )
for ( k = 0; k < Wlc_ObjFaninNum(pObj); 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);
// create fake object names
NameIdMax = Vec_IntFindMax(&pNtk->vNameIds);
......@@ -395,14 +455,17 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData )
pNtk->pManName = Abc_NamStart( NameIdMax+1, 10 );
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 );
assert( !fFound && i == NameId );
}
//Ndr_NtkPrintNodes( pNtk );
// derive topological order
pNtk = Wlc_NtkDupDfs( pTemp = pNtk, 0, 1 );
Wlc_NtkFree( pTemp );
//Ndr_NtkPrintNodes( pNtk );
pNtk->fMemPorts = 1; // the network contains memory ports
pNtk->fEasyFfs = 1; // the network contains simple flops
return pNtk;
}
......
......@@ -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;
if ( Wlc_ObjCopy(p, iObj) )
return;
//printf( "Visiting node %d\n", iObj );
pObj = Wlc_NtkObj( p, iObj );
Wlc_ObjForEachFanin( pObj, iFanin, i )
Wlc_NtkDupDfs_rec( pNew, p, iFanin, vFanins );
......@@ -876,6 +877,8 @@ Wlc_Ntk_t * Wlc_NtkDupDfsSimple( Wlc_Ntk_t * p )
vFanins = Vec_IntAlloc( 100 );
pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc );
pNew->fSmtLib = p->fSmtLib;
pNew->fMemPorts = p->fMemPorts;
pNew->fEasyFfs = p->fEasyFfs;
Wlc_NtkForEachCi( p, pObj, i )
Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins );
Wlc_NtkForEachCo( p, pObj, i )
......@@ -902,6 +905,8 @@ Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p, int fMarked, int fSeq )
Wlc_NtkCleanCopy( p );
pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc );
pNew->fSmtLib = p->fSmtLib;
pNew->fMemPorts = p->fMemPorts;
pNew->fEasyFfs = p->fEasyFfs;
Wlc_NtkForEachCi( p, pObj, i )
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
Wlc_NtkCleanCopy( p );
pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc );
pNew->fSmtLib = p->fSmtLib;
pNew->fMemPorts = p->fMemPorts;
pNew->fEasyFfs = p->fEasyFfs;
// duplicate marked PIs
vFanins = Vec_IntAlloc( 100 );
......@@ -1132,6 +1139,8 @@ Wlc_Ntk_t * Wlc_NtkDupSingleNodes( Wlc_Ntk_t * p )
vFanins = Vec_IntAlloc( 100 );
pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc );
pNew->fSmtLib = p->fSmtLib;
pNew->fMemPorts = p->fMemPorts;
pNew->fEasyFfs = p->fEasyFfs;
Wlc_NtkForEachObj( p, pObj, i )
{
if ( Wlc_ObjIsCi(pObj) )
......
......@@ -1275,6 +1275,123 @@ startword:
// 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 );
}
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_" ) )
{
int * pNameId = NULL, NameOutput, NameMi = -1, NameMo = -1, NameAddr = -1, NameDi = -1, NameDo = -1, fFound, fRead = 1;
......@@ -1324,6 +1441,87 @@ startword:
//printf( "Memory %s ", fRead ? "Read" : "Write" ); printf( "Fanins: " ); Vec_IntPrint( 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
{
while ( *pStart++ != ')' );
......
......@@ -186,13 +186,13 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
continue;
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 )
continue;
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 );
else
fprintf( pFile, "wire %s ", Range );
......@@ -255,17 +255,41 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
}
else if ( pObj->Type == WLC_OBJ_READ || pObj->Type == WLC_OBJ_WRITE )
{
int nBitsMem = Wlc_ObjRange( Wlc_ObjFanin(p, pObj, 0) );
//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 Depth = nBitsMem / nBitsDat;
assert( nBitsMem % nBitsDat == 0 );
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 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 Depth = nBitsMem / nBitsDat;
assert( nBitsMem % nBitsDat == 0 );
fprintf( pFile, "%s ;\n", Wlc_ObjName(p, i) );
fprintf( pFile, " " );
fprintf( pFile, "%s_%d (", pObj->Type == WLC_OBJ_READ ? "CPL_MEM_READ" : "CPL_MEM_WRITE", Depth );
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) ) ;\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_%d (", pObj->Type == WLC_OBJ_READ ? "CPL_MEM_READ" : "CPL_MEM_WRITE", Depth );
fprintf( pFile, "%s (", "ABC_DFFRSE" );
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) );\n", "data_out", Wlc_ObjName(p, i) );
fprintf( pFile, " .%s(%s)", pInNames[k], Wlc_ObjName(p, iFanin) );
fprintf( pFile, " .%s(%s) ) ;\n", "q", Wlc_ObjName(p, i) );
continue;
}
else
......@@ -426,22 +450,35 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
if ( pObj->Type == WLC_OBJ_PI )
continue;
fprintf( pFile, " " );
fprintf( pFile, "CPL_FF" );
if ( Wlc_ObjRange(pObj) > 1 )
fprintf( pFile, "#%d%*s", Wlc_ObjRange(pObj), 4 - Abc_Base10Log(Wlc_ObjRange(pObj)+1), "" );
else
fprintf( pFile, " " );
fprintf( pFile, " reg%d (", i );
fprintf( pFile, " .q( %s ),", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) );
fprintf( pFile, " .qbar()," );
fprintf( pFile, " .d( %s ),", Wlc_ObjName(p, Wlc_ObjId(p, Wlc_ObjFo2Fi(p, pObj))) );
fprintf( pFile, " .clk( %s ),", "1\'b0" );
fprintf( pFile, " .arst( %s ),", "1\'b0" );
if ( p->vInits )
fprintf( pFile, " .arstval( %s_init )", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) );
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, " .arstval( %s )", "1\'b0" );
fprintf( pFile, " ) ;\n" );
{
fprintf( pFile, "CPL_FF" );
if ( Wlc_ObjRange(pObj) > 1 )
fprintf( pFile, "#%d%*s", Wlc_ObjRange(pObj), 4 - Abc_Base10Log(Wlc_ObjRange(pObj)+1), "" );
else
fprintf( pFile, " " );
fprintf( pFile, " reg%d (", i );
fprintf( pFile, " .q(%s),", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) );
fprintf( pFile, " .qbar()," );
fprintf( pFile, " .d(%s),", Wlc_ObjName(p, Wlc_ObjId(p, Wlc_ObjFo2Fi(p, pObj))) );
fprintf( pFile, " .clk(%s),", "1\'b0" );
fprintf( pFile, " .arst(%s),", "1\'b0" );
if ( p->vInits )
fprintf( pFile, " .arstval(%s_init)", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) );
else
fprintf( pFile, " .arstval(%s)", "1\'b0" );
fprintf( pFile, " ) ;\n" );
}
}
assert( !p->vInits || iFanin == (int)strlen(p->pInits) );
}
......
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