/**CFile*********************************************************************** FileName [ioCmd.c] PackageName [io] Synopsis [Top-level routines for reading and writing files.] Description [This file contains top-level routines for I/O functions of VIS.] Author [Yuji Kukimoto, Rajeev K. Ranjan, Sunil P. Khatri, Huey-Yih Wang] Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California. All rights reserved. Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.] ******************************************************************************/ #include "ioInt.h" static char rcsid[] UNUSED = "$Id: ioCmd.c,v 1.16 2005/05/19 02:34:33 awedh Exp $"; /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #ifndef NAWK #define NAWK "gawk" #endif /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ extern FILE *yyin; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int CommandReadBlifMv(Hrc_Manager_t **hmgr, int argc, char **argv); static int CommandWriteBlifMv(Hrc_Manager_t **hmgr, int argc, char **argv); static int CommandReadVerilog(Hrc_Manager_t **hmgr, int argc, char **argv); static int CommandReadBlif(Hrc_Manager_t **hmgr, int argc, char **argv); static int CommandWriteBlif(Hrc_Manager_t **hmgr, int argc, char **argv); static int CommandWriteSmv(Hrc_Manager_t **hmgr, int argc, char **argv); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Initializes the I/O package.] SideEffects [] SeeAlso [Io_End] ******************************************************************************/ void Io_Init(void) { Cmd_CommandAdd("read_blif_mv", CommandReadBlifMv, 0); Cmd_CommandAdd("write_blif_mv", CommandWriteBlifMv, 0); Cmd_CommandAdd("write_smv", CommandWriteSmv, 0); Cmd_CommandAdd("read_verilog", CommandReadVerilog, 0); Cmd_CommandAdd("read_blif", CommandReadBlif, 0); Cmd_CommandAdd("write_blif", CommandWriteBlif, 0); } /**Function******************************************************************** Synopsis [Ends the I/O package.] SideEffects [] SeeAlso [Io_Init] ******************************************************************************/ void Io_End(void) { } /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [The top-level routine for read_blif_mv.] Description [] SideEffects [] CommandName [read_blif_mv] CommandSynopsis [read a blif-mv file] CommandArguments [\[-c\] \[-h\] \[-r\] \[-v\] <file_name>] CommandDescription [Reads a blif-mv file into VIS. The existing hierarchy for the blif-mv file previously read in is overwritten upon a successful read. If an error is detected while reading a file, the previous hierarchy is preserved.
Command options:
Command options:
Command options:
Command options:
Encoding the Multi-Valued Variables:
First, all multi-valued variables in the hnode are binary
encoded. Each multi-valued variable requires 'm' binary variables in
its encoding, where m = log2(n). Here 'n' is the number of values in
the domain of the multi-valued variable. If variable X has n binary
variables in its encoding, these are called X0, X1, ... X
Determinizing Non-Deterministic Tables:
Non-deterministic tables are determinized by adding more binary variables
to a particular variable's encoding. The variable that is chosen is the
one that has the smallest number of binary variables in its encoding.
Determinization is explained by means of an example:
Consider the BLIF-MV table, where each of a, b, and c can have 4 values.
Each multi-valued variable has two binary variables in its encoding. These
are called a0, a1, b0, b1, c0 and c1.
.model foo
.inputs a b
.outputs c
.mv a, b, c 4
.table a b ->c
2 1 (1,2)
(1,2) 1 3
.end
The first row of this table represents non-determinism, since for a
given assignment of input values (i.e. a=2, b=1), the output can take
on two values (1 or 2). To determinize this row, it is split into two
rows, each with a unique singleton output value. A new binary variable
is added to the encoding of a (or b, since in this case each of them has
the same number of binary variables in its encoding). The new variable
a2 is given separate values in each of the new rows. The resulting blif
table looks like:
.model foo
.inputs a0 a1 a2 b0 b1
.outputs c0 c1
.names a0 a1 a2 b0 b1 ->c0 c1
0 1 0 1 0 1 0 (these two rows represent
0 1 1 1 0 0 1 row 1 of the MV table)
1 0 - 1 0 1 1 (these two rows represent
0 1 - 1 0 1 1 row 2 of the MV table)
.end
Note that this table is still not deterministic, since rows 1 and
4 have input minterm(s) in common, but the corresponding outputs
are different. To resolve this, a new binary variable is added to
the encoding for b (since b currently has the smallest encoding).
For the conflicting rows, this variable b2 is assigned different
values, and for all other rows, it is assigned a '-' value. After
this change, rows 1 and 4 no longer have common input minterm(s).
The intermediate table now looks like:
.model foo
.inputs a0 a1 a2 b0 b1 b2
.outputs c0 c1
.names a0 a1 a2 b0 b1 b2->c0 c1
0 1 0 1 0 1 1 0
0 1 1 1 0 - 0 1
1 0 - 1 0 - 1 1
0 1 - 1 0 0 1 1
.end
This process is continued until the table is determinized. In this
example, the final blif file looks like:
.model foo
.inputs a0 a1 a2 a3 b0 b1 b2
.outputs c0 c1
.table a0 a1 a2 a3 b0 b1 b2 ->c0 c1
0 1 0 - 1 0 1 1 0
0 1 1 1 1 0 - 0 1
1 0 - - 1 0 - 1 1
0 1 - 0 1 0 0 1 1
.end
Blif allows only single output tables, so in reality the above table
is split into two single output tables before being written out to
the blif file. The new binary variables that are thus introduced are
treated as primary inputs in the blif file.
We make no claim on the optimality of this process, just that it is
simple. It may turn out that the number of new variables is much larger than
the optimum one.
Interfacing Between Binary and Multi-Valued Variables:
In order for the SIS-optimized version of this file to be read back into
VIS, we need to re-create the corresponding multi-valued variables. For
this purpose, interface information (model name, input and output
declarations for the hnode) is written out to a special encoding file
(e.g. foo.enc).
Additionally, binary->multi-valued encoding tables are written to the
encoding file for each PO. In the above example, the binary->multi-valued
table for variable c looks like
.table c0 c1 -> c
0 0 0
1 0 1
0 1 2
1 1 3
and this can be seen as a decoder of the binary variables.
Similarly, multi-valued->binary encoding tables are written to the encoding
file for each PI. The multi-valued->binary table for variable b in the above
example is:
.table b -> b0 b1
0 0 0
1 1 0
2 0 1
3 1 1
and this can be seen as an encoder of the multi-valued variables.
Similar tables are written to the encoding file for sub-circuit inputs and
outputs. Likewise, such tables are written out for latch inputs and outputs.
This is needed so that the original multi-valued latches can be reinstated
while the blif file is being read back into VIS. These multi-valued latch
declarations are written to the encoding file during the write_blif process.
The combination of this encoding file and the blif file results in a legal
BLIF-MV hnode description.
If no file is specified, the blif file is written out to the standard output.
If the encoding file is not specified, encoding information is written out
to
Options:
The '-R' option writes the entire hierarchy rooted at the current hnode to
the blif file, first checking that all tables are deterministic and all variables are
boolean. Other options ('-c', '-l', or write_blif with no options) only write
out the current hnode. Also, when the '-R' option is specified, no encoding
file is written since none is needed.
Command options:
]
SeeAlso []
SeeAlso []
******************************************************************************/
static int
CommandWriteBlif(
Hrc_Manager_t **hmgr,
int argc,
char **argv)
{
FILE *enc_fp, *fp;
char *modelName, *dupname;
int status, verbosity, combinationalOnly, makeLatchIOsPOs;
Io_Encoding_Type_t encoding_type;
Hrc_Node_t *hnode;
int c;
boolean recursive;
fp = stdout;
enc_fp = NIL(FILE);
verbosity = 0;
combinationalOnly = 0;
makeLatchIOsPOs = 0;
recursive = 0;
util_getopt_reset();
while ((c = util_getopt(argc, argv, "clRe:hv:")) != EOF) {
switch(c) {
case 'c':
combinationalOnly = 1;
break;
case 'l':
makeLatchIOsPOs = 1;
break;
case 'R':
recursive = 1;
break;
case 'e':
enc_fp = Cmd_FileOpen(util_optarg, "w", NIL(char *), 1);
if (enc_fp == NIL(FILE)){
(void)fprintf(vis_stderr,"Cannot write to %s\n", util_optarg);
return 1;
}
break;
case 'h':
goto usage;
case 'v':
verbosity = atoi(util_optarg);
break;
default:
goto usage;
}
}
if(makeLatchIOsPOs && combinationalOnly){
(void)fprintf(vis_stderr,"Cannot use -c and -l options simultaneously.\n");
goto usage;
}
if(recursive){
if(makeLatchIOsPOs || combinationalOnly){
(void)fprintf(vis_stderr,"Cannot use -c or -l options with -R option.\n");
goto usage;
}
if(enc_fp != NIL(FILE)){
(void)fprintf(vis_stderr,"Cannot use -e option with -R option.\n");
goto usage;
}
}
hnode = Hrc_ManagerReadCurrentNode(*hmgr);
if (hnode == NIL(Hrc_Node_t)){
(void)fprintf(vis_stderr,"No file has been read in.\n");
return 1;
}
/* check to see if there is only one argument left for a file name */
if (argc == util_optind){
fp = stdout;
}
else if (argc-1 == util_optind){
fp = Cmd_FileOpen(argv[util_optind], "w", NIL(char *), 1);
if (fp == NIL(FILE)){
(void)fprintf(vis_stderr,"Cannot write to %s\n", argv[util_optind]);
if (enc_fp != NIL(FILE)){
fclose(enc_fp);
}
return 1;
}
}
else {
if (enc_fp != NIL(FILE)){
fclose(enc_fp);
}
goto usage;
}
if((enc_fp == NIL(FILE)) && !recursive){
modelName = Hrc_NodeReadModelName(hnode);
dupname = ALLOC(char, strlen(modelName) + strlen(".enc") + 1);
sprintf(dupname, "%s%s", modelName, ".enc");
enc_fp = Cmd_FileOpen(dupname, "w", NIL(char *), 1);
if (enc_fp == NIL(FILE)){
(void)fprintf(vis_stderr,"Cannot write to %s\n", dupname);
return 1;
}
(void)fprintf(stdout, "Writing encoding information to %s\n",dupname);
FREE(dupname);
}
if(!recursive){
if(!(makeLatchIOsPOs || combinationalOnly)){
(void)fprintf(vis_stderr,"Warning - The blif and encoding files generated cannot be read back into \n");
(void)fprintf(vis_stderr, "VIS. If you would like to read the optimized blif file back into VIS, then \n");
(void)fprintf(vis_stderr, "please use 'write_blif -l' or 'write_blif -c' instead.\n");
}
}
error_init();
encoding_type = SIMPLE;
if(recursive){
status = Io_HnodeWriteBlifTotal(encoding_type, hnode, fp, verbosity);
}
else{
status = Io_HnodeWriteBlif(encoding_type, hnode, fp, enc_fp, verbosity, combinationalOnly, makeLatchIOsPOs);
}
(void)fprintf(vis_stderr,"%s",error_string());
fflush(fp);
if (fp != stdout) {
(void) fclose(fp);
}
if(status == 0){
return 0;
}
else{
return 1;
}
usage:
(void)fprintf(vis_stderr, "usage: write_blif [-c] [-l] [-e encoding_file] [-R] [-h] [-v verbosity] [blif_file]\n");
(void)fprintf(vis_stderr, " -c write only combinational part to blif file\n");
(void)fprintf(vis_stderr, " -l make latch IOs primary outputs in the blif file\n");
(void)fprintf(vis_stderr, " -e encoding_file, default is