Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
abc
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
abc
Commits
f23ea8e3
Commit
f23ea8e3
authored
Apr 29, 2018
by
Alan Mishchenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updates to NDR format (flops, memories, signed mult, etc).
parent
89c981c6
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
596 additions
and
100 deletions
+596
-100
src/aig/miniaig/abcOper.h
+2
-2
src/aig/miniaig/ndr.h
+242
-59
src/base/acb/acb.h
+1
-1
src/base/wlc/wlc.h
+6
-3
src/base/wlc/wlcCom.c
+10
-9
src/base/wlc/wlcMem.c
+2
-0
src/base/wlc/wlcNdr.c
+64
-1
src/base/wlc/wlcNtk.c
+9
-0
src/base/wlc/wlcReadVer.c
+198
-0
src/base/wlc/wlcWriteVer.c
+62
-25
No files found.
src/aig/miniaig/abcOper.h
View file @
f23ea8e3
...
...
@@ -138,8 +138,8 @@ typedef enum {
ABC_OPER_LATCH
,
// 86
ABC_OPER_LATCHRS
,
// 87
ABC_OPER_DFF
,
// 88
ABC_OPER_DFF
CPL
,
// 89
ABC_OPER_DFF
RS
,
// 90
ABC_OPER_DFF
RSE
,
// 89
ABC_OPER_DFF
LAST
,
// 90
ABC_OPER_SLICE
,
// 91
ABC_OPER_CONCAT
,
// 92
...
...
src/aig/miniaig/ndr.h
View file @
f23ea8e3
...
...
@@ -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
...
...
src/base/acb/acb.h
View file @
f23ea8e3
...
...
@@ -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_DFF
RS
;
}
static
inline
int
Acb_TypeIsSeq
(
Acb_ObjType_t
Type
)
{
return
Type
>=
ABC_OPER_RAM
&&
Type
<=
ABC_OPER_DFF
LAST
;
}
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
;
}
...
...
src/base/wlc/wlc.h
View file @
f23ea8e3
...
...
@@ -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
;
...
...
src/base/wlc/wlcCom.c
View file @
f23ea8e3
...
...
@@ -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
"
);
...
...
src/base/wlc/wlcMem.c
View file @
f23ea8e3
...
...
@@ -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
...
...
src/base/wlc/wlcNdr.c
View file @
f23ea8e3
...
...
@@ -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
;
}
...
...
src/base/wlc/wlcNtk.c
View file @
f23ea8e3
...
...
@@ -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
)
)
...
...
src/base/wlc/wlcReadVer.c
View file @
f23ea8e3
...
...
@@ -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
++
!=
')'
);
...
...
src/base/wlc/wlcWriteVer.c
View file @
f23ea8e3
...
...
@@ -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
)
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment