/* $Id: cmdexec1.c,v 1.1.1.1 2003/11/04 23:34:56 mjames Exp $
*
* $Log: cmdexec1.c,v $
* Revision 1.1.1.1 2003/11/04 23:34:56 mjames
* Imported into local repositrory
*
* Revision 1.31 2002/09/09 10:17:41 mjames
* Altered search path description for HPUX
*
* Revision 1.30 2002/08/23 14:20:44 mjames
* Updated comments on regular expressions.
*
* Revision 1.29 2002/08/19 14:30:04 mjames
* Added the 'write UCF' command for
* listing pin assignments in Xilinx UCF file format
*
* Revision 1.28 2002/08/06 12:52:07 mjames
* Merge in from latest version
*
* Revision 1.31 2002/04/04 14:53:05 mjames
* Added mentor board station reader to the portfolio
*
* Revision 1.30 2002/03/21 17:14:22 mjames
* Added search path to vertical file opening for read
*
* Revision 1.29 2002/03/08 14:56:14 mjames
* Edited all of the commands in the cmdexec1.c and cmdexec2.c files
* so that they can be read by doc2.pl
*
* Revision 1.28 2002/03/08 11:54:38 mjames
* Tagging for perl script to list commands out
*
* Revision 1.27 2002/01/15 12:37:47 mjames
* now uses a function to set the debug level rather than global variable
*
* Revision 1.26 2001/12/24 21:14:00 mjames
* Added header includes to get correct declarations for all functions
* called from command handlers
*
* Revision 1.25 2001/12/24 20:08:38 mjames
* Added more information about ensure template command to help message
*
* Revision 1.24 2001/12/20 13:54:19 mjames
* Update version number to 15.1
*
* Revision 1.23 2001/12/13 22:13:22 mjames
* Vertical now supports nested include database files
* This allows wrappers around 'pure' VHDL or Verilog files
*
* Read command now initialises include stack correctly
*
* Revision 1.22 2001/11/19 10:41:05 mjames
* Merge conflict resolution
*
* Revision 1.21 2001/11/09 22:14:45 mjames
* Added in delete chip node connection command
* In order to remove small number of chip pins in a large board
* which have been damaged.
*
* Revision 1.20.2.1 2001/11/16 15:13:23 mjames
* Included some more needed header files
* Added extra documentation in auto generate -> HTML
*
* Revision 1.20 2001/10/31 22:20:00 mjames
* Tidying up problematical comments caused by CVS
* 'intelligent' comment guessing
*
* Revision 1.19 2001/10/23 21:28:51 mjames
* Produce a list of diagnostic printouts enabled via the debug <n> command
*
* Revision 1.18 2001/10/11 16:10:18 mjames
* Corrections to the SWAP command, and printout so that
* WRITE net now outputs all chips in the design so that their generics
* can be passed forward to the next phase.
*
* Revision 1.17 2001/10/02 20:55:18 mjames
* Edited help files to try and get them more up to date.
*
* Revision 1.16 2001/09/21 14:13:52 mjames
* Implemented Write Pin command
*
* Revision 1.15 2001/08/23 20:44:14 mjames
* Corrected mistake in file name on write fit command.
*
* Revision 1.14 2001/07/09 15:09:36 mjames
* Lists external sockets as components before using them
*
* Revision 1.13 2001/06/20 13:09:45 mjames
* Took out 'from from' message.
*
* Revision 1.12 2001/06/19 05:24:34 mjames
* Created a trap_fopen to overcome trying to write to read only files.
* If this attempted in NT the file can be opened but not written to.
*
* Revision 1.11 2001/06/06 12:10:25 mjames
* Move from HPUX
*
* Revision 1.10 2001/04/09 14:58:28 mjames
* Added capability to delete generics from specific sockets.
*
* Revision 1.9 2001/04/04 22:12:31 mjames
* Added some online documentation to the C program command handler
* THis is scanned by a utility called 'doc' that currently creates
* simple HTML from part formatted C comments
*
* Also working well on printing VERILOG
*
* still have problems with C comments and VERTICAL pragmas.
*
* Revision 1.8 2001/03/19 19:13:21 mjames
* Tidied up a few commands
*
* Revision 1.7 2001/02/06 22:41:14 mjames
* Added correct argument passing for 'read file comp_suffix arg0 arg1 arg2 ...
*
* Revision 1.6 2001/02/01 21:41:43 mjames
* Made the code begin to compile without TCL/TK
*
* Revision 1.5 2001/01/26 21:50:09 mjames
* Managed to get vertical non TCL to compile again
*
* Conversion to argv, argc[] mode of operation continues
*
* Revision 1.4 2001/01/04 21:26:54 mjames
* Modifications to add in the TCL style
* argument list to all of the functions
* .
*
* Revision 1.3 2001/01/02 07:53:51 mjames
* Made changes to allow for interface with TCL/Tk
*
* Revision 1.2 2000/10/21 20:41:29 mjames
* Added the 'write flatten' command that only lists the wires
* created by making jumpered connections rather than listing
* the jumpers themselves
*
* Revision 1.1.1.1 2000/10/19 21:58:35 mjames
* Mike put it here
*
*
Removed RCS log information to reduce clutter
*****************************************************************************/
#include "bundle.h"
#include "chck_names.h"
#include "cmdexec.h"
#include "cmdlog.h"
#include "cmdparse.h"
#include "cmdutil.h"
#include "database.h"
#include "expression.h"
#include "ext_nets.h"
#include "generic.h"
#include "jumpering.h"
#include "partition.h"
#include "print_ports.h"
#include "print_quartus.h"
#include "print_ucf.h"
#include "print_vhdl.h"
#include "print_vlog.h"
#include "printout.h"
#include "rename.h"
#include "routing.h"
#include "statistics.h"
#include "template.h"
#include "unrouted.h"
#include "vertcl_main.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
tcl_mode_t Tcl_Mode;
/* make this a global */
Tcl_Interp *Tcl_interp;
#ident \
"@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/cmdexec1.c,v 1.1.1.1 2003/11/04 23:34:56 mjames Exp $"
/* Additional information for the user is provided in this section for inclusion in the
HTML file
@title
Vertical application areas
@text
The following indices represent the commands that are likely to be useful for each
of the 'modes' of Vertical and its PCB translator family
@list_index
@end
*/
/*
@title
Vertical External PCB netlist translators
@index external
@end
*/
/*
@title
Vertical Pin assignment mode commands
@index vertical_pin
@end
*/
/*
@title
Vertical PCB merging commands
@index vertical_pcb
@end
*/
/*
@title
Vertical HDL handling commands
@index vertical_hdl
@end
*/
/*
@title
Vertical Regular expressions and commands that use them
@index regular_exp
@end
*/
/*
@title
Vertical search paths
@application vertical_pin
@application vertical_pcb
@application vertical_hdl
@text
As of version 15.5a, Vertical can now use search paths when opening scripts or database
files for reading. All file writes are in the current directory.
@break
For the PC the search path is :
@listing
.;c:/cygwin/usr/local/vert_files
@text
Or in english : look in the current directory '.' and then look in
'c:/cygwin/usr/local/vert_files'.
@break
For PC; filenames containing ':' or starting with either '/' or '.' are not searched down the
path,
@break
The path is in the environment variable called 'VERTICAL_PATH', which can either be
set in the shell (MSDOS or cygwin) which invokes vertical, or as a command from within
a Vertical script. e.g.
@listing
setenv VERTICAL_PATH "$(VERTICAL_PATH);/home/project/reference_data"
@text
This will make Vertical search in the usual places and then in the additional directory.
@break
For the HPUX port of Vertical the search path is
.;.caddata/vert_files
@text
For HPUX; filenames starting in '/' and '.' are not searched for down the path. These two
characters are normally used to specify a definite path, either relative to the current working
directory or absolute relative to the file system root.
@end
=======
HTML file
@title
Vertical application areas
@text
The following indices represent the commands that are likely to be useful for each
of the 'modes' of Vertical and its PCB translator family
@listing
vertical_pin
vertical_pcb
vertical_hdl
@end
*/
/*
@title
Vertical Pin assignment mode commands
@index vertical_pin
@end
*/
/*
@title
Vertical PCB merging commands
@index vertical_pcb
@end
*/
/*
@title
Vertical HDL partitioning commands
@index vertical_hdl
@end
*/
/*
@title
Vertical script command notation: Command line and script files
@application vertical_pin
@application vertical_pcb
@application vertical_hdl
@text
Vertical uses its own 'shell' like command language. In this language, quoting a string
simply means that spaces appearing inside strings can be passed into Vertical as a single
argument. Normally spaces are used to delimit parameters in a command.
@break
When the command is listed out the following notation is used.
@text
If an item is given without angle ( '<' '>' ) brackets then the word is typed as is. e.g.
@listing
command
@break
If '<' '>' angle brackets are given then this an item such as a filename which is user defined.
e.g. Command followed
@listing
command <filename>
@break
If followed by an asterisk '*' it means in this context that more than one of these items
may be entered. It is not the same as a regular expression used within one of these items. e.g.
command followed by several items
@listing
command <item> *
@break
If '[' ']' square brackets are given then the item is optional. e.g. command with an optional
parameter
@listing
command [ <optional> ]
@text
More than one of these may appear at a time on the same item. e.g. Optional list of letters.
@end
@title
Vertical database file notation: Database files
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Vertical handles several different database file formats. These are :
@listing
Altera .acf : tagged as AHDL
Verilog : tagged as VERILOG
VHDL : tagged as VHDL
Vertical Native : initial state and outside other tagged blocks
@text
They are all read in by a single database handler which can switch between different
languages on the fly.
@break
In all cases the Vertical parser begins expecting Vertical Native file format, and then
it is switched into other modes by the presence of tag keywords
@break
These bracket the code. e.g.
@listing
VHDL -- this indicates following syntax.
entity nine is
(
);
end entity nine;
architecture seven of nine is
-- vertical read_off
this code will not be seen by vertical, as it has
tags in the comments.
DONT start comments with the word 'VERTICAL' as it is seen an
an escape into vertical database language.
-- vertical read_on
begin
end;
END; -- this belongs to Vertical
@text
Because Vertical recognises the comments that are found in
all of the HDL's that it understands, it is possible to feed
a native HDL file in with Vertical tags in comments.
e.g.
@end
@title
regular expression: Information on wildcards in Vertical
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
The wildcards now used in several commands conform to standard regular expressions.
If no 'special' characters are given then patterns must match exactly, except that
the case of alphabetic characters is ignored.
@break
For instance: to select :
@listing
pattern meaning
------- -------
X2[1-7] 'X' or 'x', '2' and then digit '1' to '7'
.* any char zero or more times (anything)
X[0-9]+ 'X' or 'x', followed by one or more digits
(expr) A pattern to be matched that can be used in a string replace.
Each bracketed expression can be used in a replacement string
&1 is the first pattern. &0 is the whole of the matched string.
@text
On cygwin and Unix 'man regex' will work to tell you more.
@break
The edit_pin ident command and edit_pin type
command documentation has more on regular expressions.
@break
Use '\' characters to escape special characters.
@end
*/
/************************************************************************/
/* Command handling code */
/************************************************************************/
/*********************** Simple command calls ***************************/
/* BYE : Exit program
@title
bye, quit, exit
@application vertical_pcb
@application vertical_pin
@application vertical_hdl
@text
Leave program, closing files tidily.
@end
*/
int BYEHandler (ET_TCLARGS)
{
CloseLog (); /* append summary and close the log file */
Log (LOG_GENERAL, "#Goodbye for now\n");
return (QUITCMD); /* try to leave cleanly */
}
/****************************************************************************/
/* external parser variables */
extern int yydebug;
extern FILE *yyin;
extern int lineno;
extern int yy_nArgs;
extern char **yy_Args;
extern int inside_block;
/* debug level */
long level;
/******************** Setup YYDEBUG flag ***********************/
/*
@title
debug <debug_flags>
@application vertical_pcb
@application vertical_pin
@application vertical_hdl
@text
Internal debugging flags. Bit fields can be combined. In general issue debug
flag setting commands before issuing commands:
@break
Followed by the 'read' command:
@listing
For read command:
Bit 0 : The yydebug flag (see man yacc/lex for more info)
For template command
Bit 0 : Prints basic actions
Bit 1 : More detailed info
Bit 2 : Extremely detailed info.
For partition command
Bit 0 : Prints basic actions.
For route command
Bit 2 : Prints basic actions
Bit 3 : More detailed info
For jumper command
Bit 0 : Basic information
For set/del ext and set/del fpga commands
Bit 2 : Trace operations in detail
For equivalent pin operations (normally via netlist)
Bit 0 : Trace operations
For print vlog
Bit 0 : In Verilog file : indicate status for wires, list unused sigs as comments
For all file opening
Bit 4 : List files that Vertical attempts to open using its search path.
@end
*/
int DEBUGHandler (ET_TCLARGS)
{
if (argc == 1)
{
set_debug_level (level); /* send info into DLL */
yydebug = level & 1;
Log (LOG_GENERAL, "# setting debug level to %d\n", level);
return (TCL_OK);
}
else
return (TCL_ERROR);
}
/******************** Read a data file ***********************/
/*
@title
read <filename> [<identifier_suffix> | "" ] [ <arg>* ]
@application vertical_pcb
@application vertical_pin
@application vertical_hdl
@text
Read a data file in to the internal database. If <suffix> is
given, the newly read socket and net identifiers are suffixed
with the suffix given. This is the means by which a single PCB
netlist file is given a unique identity. In this way the same
netlist may be repeated many times, but every object is given
an unique identifier.
In other words if the netlist is read in twice, once with the
suffix 'a' and once with the suffix 'b' then a socket 'U1' in
the netlist will become two sockets : 'U1a' and U1b' in the
combined netlist.
@break
String concatenation WARNING:
@break
If you have a set of sockets in the PCB netlist file with
identifiers U1 to U 20 and you decide to suffix a new ACF file
being read with "0" then U1 in the new file will match U10 in
the old file and will 'vanish' or be confused with U10 in the
old file. The best way to avoid this problem is to
It is normal to use an underscore character as in "_" to
prefix the suffix to avoid this.
@break
In addition any arguments after the suffix field (which can be omitted if a "" null string is
given) can be used as macro variables $0, $1 and so on inside the database file.
e.g.
@listing
read conn.txt "" x1_a x1_b
@text
Will, if the file conn.txt contains the following
@listing
JOINED_NETS
BEGIN
JUMPER J_$0$1_3A = ($0(3A );$1(16A); );
JUMPER J_$0$1_4A = ($0(4A );$1(15A); );
JUMPER J_$0$1_5A = ($0(5A );$1(14A); );
JUMPER J_$0$1_6A = ($0(6A );$1(13A); );
END;
@text
Be translated into
@listing
JOINED_NETS
BEGIN
JUMPER J_x1_ax1_b_3A = (x1_a(3A );x2_a(16A); );
JUMPER J_x1_ax1_b_4A = (x1_a(4A );x2_a(15A); );
JUMPER J_x1_ax1_b_5A = (x1_a(5A );x2_a(14A); );
JUMPER J_x1_ax1_b_6A = (x1_a(6A );x2_a(13A); );
END;
@text
If no arguments are given, then the argument list of the currently
executing script are used as $0, $1 and so on.
@end
*/
extern void tidy_lex (void);
extern int yyparse (void);
int READHandler (ET_TCLARGS)
{
int rc = 0;
int old_yy_nArgs;
char **old_yy_Args;
#if defined DIAGNOSE
{
int i;
for (i = 0; i < argc; i++)
"[%d]=%s\n",
i,
argv[i] ? (argv[i][0] ? argv[i] : "\"\"") : "<null>");
for (i = 0; i < yy_nArgs; i++)
"[%d]=%s\n",
i,
yy_Args[i] ? (yy_Args[i][0] ? yy_Args[i] : "\"\"") : "<null>");
}
#endif
if (argc < 1)
return (TCL_ERROR);
Log (LOG_GENERAL, "# reading information from <%s>\n", argv[0]);
mark_board_objects (); /* record some pointers - last object before rename */
inside_block = 0;
tidy_lex ();
yyin = trap_fopen (argv[0], "r"); /* open text file for reading */
if (!yyin)
{
Log (LOG_ERROR, "# Error opening file: <%s>\n", argv[0]);
return (TCL_ERROR);
}
else
{
/* setup the argument lists for expansion :
either inherit from calling script (no args) or
copy from rest of command line. No need to make duplicates of
values as they cannot be changed within a 'read' operation
unlike 'do' which may call other command files with different arg.
lists.
*/
old_yy_nArgs = yy_nArgs;
old_yy_Args = yy_Args;
if (argc >= 3)
{
yy_Args = argv + 2;
yy_nArgs = argc - 2;
}
#if defined DIAGNOSE
{
int i;
for (i = 0; i < yy_nArgs; i++)
"[%d]=%s\n",
i,
yy_Args[i] ? (yy_Args[i][0] ? yy_Args[i] : "\"\"")
: "<null>");
}
#endif
lineno = 1;
while (!feof (yyin
) && !rc
)
{
if (yydebug)
Log (LOG_GENERAL, "Processing line %d\n", lineno);
rc = yyparse ();
}
#if defined DIAGNOSE
{
int i;
printf ("new2 global args\n");
for (i = 0; i < yy_nArgs; i++)
"[%d]=%s\n",
i,
yy_Args[i] ? (yy_Args[i][0] ? yy_Args[i] : "\"\"")
: "<null>");
}
#endif
yy_nArgs = old_yy_nArgs;
yy_Args = old_yy_Args;
/* added the concatenation of suffixes
* to the Names and Identifiers of objects *
* if there was a suffix and it is not null apply it */
if (argc >= 2 && !ISNULLSTR (argv[1]))
{
set_board_suffix (argv[1]);
Log (LOG_GENERAL, "# Object name/identifier suffix = '%s'\n", argv[1]);
}
need_validate_names = 1; /* tell validate_names there is some work to do */
if (rc == 0)
return (TCL_OK);
else
return (TCL_ERROR);
}
}
/******************** Output an ACF file all pins connected to nets ***********************/
/*
@title
write connected <filename>
@application vertical_pcb
@application vertical_pin
@text
Write out an 'Extended ACF' file for the entire netlist and
device and net assignments. If there are any sockets with
names assigned to the socket identifier (implying the socket
contains something important) then their entire pinout (without pin reservations) will be
written as part of the netlist. All connections made to external sockets will be listed.
@end
*/
int WriteConnectedHandler (ET_TCLARGS)
{
FILE *ACFfile;
if (argc < 1)
return (TCL_ERROR);
Log (LOG_GENERAL, "# producing an ACF file <%s>\n", argv[0]);
ACFfile = trap_fopen (argv[0], "w"); /* open text file for reading */
if (!ACFfile)
{
Log (LOG_ERROR, "# Error opening ACF output file: <%s>\n", argv[0]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
print_header (ACFfile, TOOL_NAME ": WRITE CONNECTED");
list_database (ACFfile, PRESERVE_JUMPERS);
list_jumper (ACFfile);
list_generic_values (ACFfile, &global_generics, 0);
list_devices (
ACFfile,
PRINT_TYPE | PRINT_EXPAND_BUS | PRINT_NET_NAMES | PRINT_GENERIC |
PRINT_GROUP | PRINT_ROUTE_FLAGS | PRINT_EQUIVALENT_PINS);
list_alias (ACFfile);
print_pin_renames (ACFfile);
return (TCL_OK);
}
}
/******************** Output an ACF file ***********************/
/*
@title
write acf <filename>
@application vertical_pcb
@application vertical_pin
@text
Write out an 'Extended ACF' file for the entire netlist and
device and net assignments. If there are any sockets with
names assigned to the socket identifier (implying the socket
contains something important) then their pinout will be
written as part of the netlist. Connections to sockets without
names assigned are still written out.
@end
*/
int WriteAcfHandler (ET_TCLARGS)
{
FILE *ACFfile;
if (argc < 1)
return (TCL_ERROR);
Log (LOG_GENERAL, "# producing an ACF file <%s>\n", argv[0]);
ACFfile = trap_fopen (argv[0], "w"); /* open text file for reading */
if (!ACFfile)
{
Log (LOG_ERROR, "# Error opening ACF output file: <%s>\n", argv[0]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
print_header (ACFfile, TOOL_NAME ": WRITE ACF");
list_database (ACFfile, PRESERVE_JUMPERS);
list_jumper (ACFfile);
list_generic_values (ACFfile, &global_generics, 0);
list_devices (
ACFfile,
PRINT_TYPE | PRINT_EXPAND_BUS | PRINT_GENERIC | PRINT_GROUP |
PRINT_ROUTE_FLAGS | PRINT_EQUIVALENT_PINS);
list_alias (ACFfile);
print_pin_renames (ACFfile);
return (TCL_OK);
}
}
/******************** Output an ACF, just net part file ***********************/
/*
@title
write net <filename>
@application vertical_pcb
@application vertical_pin
@text
Write out an 'Extended ACF' file for the entire netlist. In this case no socket
information is printed.
@end
*/
int WriteNetHandler (ET_TCLARGS)
{
FILE *ACFfile;
if (argc < 1)
return (TCL_ERROR);
Log (LOG_GENERAL, "# producing an ACF (net only) file <%s>\n", argv[0]);
ACFfile = trap_fopen (argv[0], "w"); /* open text file for reading */
if (!ACFfile)
{
Log (LOG_ERROR, "# Error opening ACF output file: <%s>\n", argv[0]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
print_header (ACFfile, TOOL_NAME ": WRITE NET");
list_database (ACFfile, PRESERVE_JUMPERS);
list_jumper (ACFfile);
list_devices (
ACFfile,
PRINT_TYPE | PRINT_GENERIC | PRINT_GROUP | PRINT_ROUTE_FLAGS |
PRINT_EQUIVALENT_PINS | NO_PRINT_PINS);
return (TCL_OK);
}
}
/******************** Write Flatten command ***********************/
/*
@title
write flatten <filename>
@application vertical_pcb
@application vertical_hdl
@text
Write out an 'Extended ACF' file for the entire netlist and
device and net assignments. If there are any sockets with
names assigned to the socket identifier (implying the socket
contains something important) then their pinout will be
written as part of the netlist. Connections to sockets without
names assigned are still written out.
@break
In addition, all jumpers are flattened, and the joined together
nets created by jumpers are written out as a single wire. This is used with the
equivalent pin connections on socket templates.
@end
*/
int WriteFlattenHandler (ET_TCLARGS)
{
FILE *ACFfile;
if (argc < 1)
return (TCL_ERROR);
Log (LOG_GENERAL, "# producing a flattened ACF file <%s>\n", argv[0]);
ACFfile = trap_fopen (argv[0], "w"); /* open text file for reading */
if (!ACFfile)
{
Log (LOG_ERROR, "# Error opening ACF output file: <%s>\n", argv[0]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
print_header (ACFfile, TOOL_NAME ": WRITE FLATTEN");
list_database (ACFfile, FLATTEN_JUMPERS);
return (TCL_OK);
}
}
/******************** Output an FRB file ***********************/
/*
@title
write pcb <filename>
@application vertical_pcb
@text
Write out a "neutral architecture file" PCB netlist file for
CadStar. This is hard to use properly, as Southampton Cadstar
users always seem to be coming up with different netlist
formats, and there are problems with library portability and
the unique and 'useful' way this has been setup at
Southampton.
@end
*/
int WriteFrbHandler (ET_TCLARGS)
{
FILE *FRBfile;
if (argc < 1)
return (TCL_ERROR);
Log (LOG_GENERAL, "# producing an FRB file <%s>\n", argv[0]);
FRBfile = trap_fopen (argv[0], "w"); /* open text file for reading */
if (!FRBfile)
{
Log (LOG_ERROR, "# Error opening FRB output file: <%s>\n", argv[0]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
produce_frb (FRBfile);
return (TCL_OK);
}
}
/******************** Output a list of templates to a file ***********************/
/*
@title
write template <filename>
@application vertical_pin
@application vertical_hdl
@text
List out all of the socket templates (alternatively these are VHDL component declarations)
loaded into the VERTICAL database into a file,
which can be used to create a library of templates.
@end
*/
int WriteTemplateHandler (ET_TCLARGS)
{
FILE *Templatefile;
if (argc < 1)
return (TCL_ERROR);
Log (LOG_GENERAL, "# producing an Template file <%s>\n", argv[0]);
Templatefile = trap_fopen (argv[0], "w"); /* open text file for reading */
if (!Templatefile)
{
Log (LOG_ERROR, "# Error opening Template output file: <%s>\n", argv[0]);
return (TCL_ERROR);
}
else
{
template_list_pins (Templatefile);
}
return (TCL_OK);
}
/************ Output a device by Name to file - expanding VHDL busses ********/
/*
@title
write fit <device> <filename>
@application vertical_pcb
@application vertical_pin
@application vertical_hdl
@text
Write out a device socket, and expand out busses, using the VHDL declarations
of the signals connected to produce the required number of pins. These databases
created can be used in the creation of an initial pin fit without the use of
an FPGA fitter.
@break
Partitioning use : If the 'chip' appears to have VHDL busses
rather than individual wires on some of its 'pins' then these
busses will be expanded into unique signal names. This process
is performed at the time of printout. A bus declared as
@listing
fred : in STD_LOGIC (3 DOWNTO 0)
in the input acfp file will be printed out as
fred_0 : INPUT_PIN := 1_1 "STD_LOGIC"
fred_1 : INPUT_PIN := 1_2 "STD_LOGIC"
fred_2 : INPUT_PIN := 1_3 "STD_LOGIC"
fred_3 : INPUT_PIN := 1_4 "STD_LOGIC"
@end
*/
int WriteFitHandler (ET_TCLARGS)
{
FILE *ACFfile;
socket_t *skt;
if (argc < 2)
return (TCL_ERROR);
skt = find_socket (Name, argv[0], Search, &socket_head);
if (!skt)
{
Log (LOG_GENERAL, "# Cannot find socket name '%s'\n", argv[0]);
return (TCL_ERROR);
};
Log (LOG_GENERAL, "# producing ACF for socket name '%s' in <%s>\n", argv[0], argv[1]);
ACFfile = trap_fopen (argv[1], "w"); /* open text file for writing */
if (!ACFfile)
{
Log (LOG_ERROR, "# Error opening ACF output file: <%s>\n", argv[1]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
print_header (ACFfile, TOOL_NAME ": WRITE FIT");
print_device (ACFfile, skt, PRINT_EXPAND_BUS); /* include pins not connected to
nets */
return (TCL_OK);
}
}
/******************** Output a device by ID to file ***********************/
/*
@title
write identifier <chip_ident> <filename>
@application vertical_pcb
@application vertical_pin
@application vertical_hdl
@text
Write out device info by ident e.g. U1 or U2 . All pins that
are known either on routed nets or unrouted nets will be
listed. The names of the routed nets attached to the chip pins
are given so that the user can detertmine which socket pins
are usable for making connections to the socket. That is all
of those that are not VCC or Ground for example.
@break
This format is exactly compatible with maxplus2 so it is used
to produce the new pin assignment files for maxplus2
It is also used to help with the creation of pin definition
files for external connectors.
@end
*/
int WriteIdHandler (ET_TCLARGS)
{
FILE *ACFfile;
socket_t *skt;
if (argc < 2)
return (TCL_ERROR);
skt = find_socket (Ident, argv[0], Search, &socket_head);
if (!skt)
{
Log (LOG_GENERAL, "# Cannot find socket id '%s'\n", argv[0]);
return (TCL_ERROR);
};
Log (LOG_GENERAL, "# producing ACF for socket id '%s' in <%s>\n", argv[0], argv[1]);
ACFfile = trap_fopen (argv[1], "w"); /* open text file for writing */
if (!ACFfile)
{
Log (LOG_ERROR, "# Error opening ACF output file: <%s>\n", argv[1]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
print_header (ACFfile, TOOL_NAME ": WRITE ID");
print_device (ACFfile, skt, PRINT_ALL | PRINT_USABLE); /* include pins not
connected to nets */
}
return (TCL_OK);
}
/******************** Output a device by name to file ***********************/
/*
@title
write name <chip_name> <filename>
@application vertical_pcb
@application vertical_pin
@application vertical_hdl
@text
Write out device info for the named device/socket (with only
pins that are used by routed nets). Tis is used for user
documentation purposes and diagnostics, in separating out
induvidual sockets from the netlist into separate files.
@text
@end
*/
int WriteNameHandler (ET_TCLARGS)
{
FILE *ACFfile;
socket_t *skt;
if (argc < 2)
return (TCL_ERROR);
skt = find_socket (Name, argv[0], Search, &socket_head);
if (!skt)
{
Log (LOG_GENERAL, "# Cannot find socket name '%s'\n", argv[0]);
return (TCL_ERROR);
};
Log (LOG_GENERAL, "# producing ACF for socket name '%s' in <%s>\n", argv[0], argv[1]);
ACFfile = trap_fopen (argv[1], "w"); /* open text file for writing */
if (!ACFfile)
{
Log (LOG_ERROR, "# Error opening ACF output file: <%s>\n", argv[1]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
print_header (ACFfile, TOOL_NAME " : WRITE NAME");
print_device (ACFfile, skt, 0); /* used pins only */
return (TCL_OK);
};
}
/******************** Output a partition name to file ***********************/
/*
@title
write VHDl <new_entityname> <filename> [ <template_file> ]
@text
Write out partition as VHDL, with the top level entity named
as the new_entityname. If a template file name is given then
the template file will be copied to filename, but where the
string '$ENT$' appears in the template file, the entity will
be inserted, and where the string '$ARCH$' appears in the
template file, the architecture will be inserted. This allows
for project specific libraries to be used and for specific
header and footer information to be provided. e.g.
@listing
Example of a VHDL template file
-------------------------------
-- Super dooper junk project --
-- Default template file with--
-- VERTICAL --------------------
-------------------------------
library ieee,proj_std;
use ieee.std_logic_1164.all;
use proj_std.dodgy_conversions.all;
-- Now an entity --
$ENT$
library ieee,proj_std;
use ieee.std_logic_1164.all;
use proj_std.dodgy_conversions.all;
-- now an architecture --
$ARCH$
@text
You will be warned if the template contains other than exactly
one $ENT$ and $ARCH$ string.
@end
*/
int WriteVHDLHandler (ET_TCLARGS)
{
char *TemplateName;
FILE *VHDLfile;
if (argc < 2)
return (TCL_ERROR);
/* template name is optional */
TemplateName = NULL;
if (argc > 2)
TemplateName = argv[2];
/* slip-up with a null pointer 17 Feb 2000 */
if (TemplateName
&& strcmp (TemplateName
, argv
[0]) == 0)
{
Log (
LOG_ERROR,
"# ERROR : VHDL template file name '%s' is the same as the template file "
"name\n",
argv[1]);
return (TCL_ERROR);
}
Log (
LOG_GENERAL,
"# producing VHDL of partition for new entity name '%s' in <%s>\n",
argv[0],
argv[1]);
VHDLfile = trap_fopen (argv[1], "w"); /* open text file for writing */
if (!VHDLfile)
{
Log (LOG_ERROR, "# Error opening VHDL output file: <%s>\n", argv[1]);
return (TCL_ERROR);
}
else
{ /* include a template if it exists */
create_unrouted_list ();
produce_VHDL (VHDLfile, argv[0], TemplateName);
return (TCL_OK);
};
}
/******************** Output a partition name to file ***********************/
/*
@title
write VLOG <new_entityname> <filename>
@text
This is an experimental function used primarily with Certify.
It writes out a board level netlist Verilog (.vb) file with
only sockets that are set as external actually instanced. This
removes unnecessary clutter from the design, and allows for
the creation of large breadboards using VERTICAL to combine
PCBs.
@end
*/
int WriteVLOGHandler (ET_TCLARGS)
{
char *TemplateName;
FILE *VLOGfile;
if (argc < 2)
return (TCL_OK);
/* template name is optional */
TemplateName = NULL;
if (argc > 2)
TemplateName = argv[2];
/* slip-up with a null pointer 17 Feb 2000 */
if (TemplateName
&& strcmp (TemplateName
, argv
[1]) == 0)
{
Log (
LOG_ERROR,
"# ERROR : VLOG file name '%s' is the same as the template file name\n",
argv[1]);
return (TCL_ERROR);
}
Log (
LOG_GENERAL,
"# producing VLOG of partition for new entity name '%s' in <%s>\n",
argv[0],
argv[1]);
VLOGfile = trap_fopen (argv[1], "w"); /* open text file for writing */
if (!VLOGfile)
{
Log (LOG_ERROR, "# Error opening VLOG output file: <%s>\n", argv[1]);
return (TCL_ERROR);
}
else
{ /* include a template if it exists */
create_unrouted_list ();
produce_VLOG (VLOGfile, argv[0], TemplateName);
return (TCL_OK);
};
}
/******************** Write Extern command ***********************/
/*
@title
write EXTernal <filename>
@text
Write out all sockets set as external to a file as a .acfp
file.
@break
In addition a COMPONENTS block will be written
@break
This is intended to provide Vertical write extern
with an explicit tie-up between the socket ID
e.g. U1 and a device name in the socket e.g. BusChip or whatever. For example:
@listing
COMPONENTS
BEGIN
U1 : BusChip EPM7234 "" ;
END;
@text
@break
In fact in many cases where write ext is used, the contents of socket U1 will be known as
device name U1.
@break
@listing
COMPONENTS
BEGIN
U1 : U1 EPM7234 "" ;
END;
@text
Without this info, the tool cannot locate sockets by name using the chip identifier
as ACF files do not contain the chip identifier, only the chip name.
@break
(see set external command)
@end
*/
int WriteExternHandler (ET_TCLARGS)
{
FILE *ACFfile;
if (argc < 1)
return (TCL_ERROR);
Log (LOG_GENERAL, "# producing an ACF file <%s>\n", argv[0]);
ACFfile = trap_fopen (argv[0], "w"); /* open text file for reading */
if (!ACFfile)
{
Log (LOG_ERROR, "# Error opening ACF output file: <%s>\n", argv[0]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
print_header (ACFfile, TOOL_NAME ": WRITE EXTERN");
list_extern_sockets (ACFfile);
list_extern_devices (ACFfile);
return (TCL_OK);
}
}
/******************** Output a device pin assignments as Xilinx Virtex UCF format
* ***********************/
/*
@title
write UCF <chip_ident> <filename>
@application vertical_pcb
@application vertical_pin
@application vertical_hdl
@text
Write out device info as a Xilinx Alliance (Virtex etc) UCF, naming socket
by ident e.g. U1 or U2 . All pins that
are known either on routed nets or unrouted nets will be
listed. The names of the routed nets attached to the chip pins
are given so that the user can detertmine which socket pins
are usable for making connections to the socket. That is all
of those that are not VCC or Ground for example.
@break
This format is exactly compatible with Xilinx Alliance so it is used
to produce the new pin assignment files for Xilinx Alliance
@end
*/
int WriteUCFHandler (ET_TCLARGS)
{
FILE *UCFfile;
socket_t *skt;
if (argc < 2)
return (TCL_ERROR);
skt = find_socket (Ident, argv[0], Search, &socket_head);
if (!skt)
{
Log (LOG_GENERAL, "# Cannot find socket id '%s'\n", argv[0]);
return (TCL_ERROR);
};
Log (LOG_GENERAL, "# producing UCF for socket id '%s' in <%s>\n", argv[0], argv[1]);
UCFfile = trap_fopen (argv[1], "w"); /* open text file for writing */
if (!UCFfile)
{
Log (LOG_ERROR, "# Error opening UCF output file: <%s>\n", argv[1]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
print_UCF_instance (UCFfile, skt, PRINT_ALL | PRINT_USABLE); /* include pins
not connected
to nets */
return (TCL_OK);
}
}
/******************** Write Sockets command ***********************/
/*
@title
write SOCkets <filename>
@text
Write out all sockets to a file as a .acfp
file.
@end
*/
int WriteSocketHandler (ET_TCLARGS)
{
FILE *ACFfile;
if (argc < 2)
return (TCL_ERROR);
Log (LOG_GENERAL, "# producing an ACF file <%s>\n", argv[0]);
ACFfile = trap_fopen (argv[0], "w"); /* open text file for write*/
if (!ACFfile)
{
Log (LOG_ERROR, "# Error opening ACF output file: <%s>\n", argv[0]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
print_header (ACFfile, TOOL_NAME ": WRITE SOCKETS");
list_components (ACFfile);
return (TCL_OK);
}
}
/******************** Output a device by name to file ***********************/
/*
@title
write PAR_acf <new_entityname> <filename>
@text
Write out partition entity as Extended ACF so that it may be
read in as a description of the ports of the top level of a
partitiion, in conjunction with the extended ACF files for
the other partitions in the system.
This then allows the connection together of all of the
partitioned pieces of the design back into a new toplevel
entitiy that may be simulated.
@end
*/
int WriteParACFHandler (ET_TCLARGS)
{
FILE *Parfile;
if (argc < 2)
return (TCL_ERROR);
Log (
LOG_GENERAL,
"# producing Extended ACF of partition for new entity name '%s' in <%s>\n",
argv[0],
argv[1]);
Parfile = trap_fopen (argv[1], "w"); /* open text file for writing */
if (!Parfile)
{
Log (LOG_ERROR, "# Error opening ACF+ output file: <%s>\n", argv[1]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
print_header (Parfile, TOOL_NAME " : WRITE PAR_ACF");
print_ACF_entity (Parfile, argv[0]);
return (TCL_OK);
};
}
/******************** Output a device by name to Quartus pinfit file ***********************/
/*
@title
write quartus <chip_name> <filename>
@text
Writes out a Quartus .pin pin assignment file with reserved pins and recommended tiedown pins.
@end
*/
int WriteQuartusPinfitHandler (ET_TCLARGS)
{
FILE *ACFfile;
socket_t *skt;
if (argc < 2)
return (TCL_ERROR);
skt = find_socket (Name, argv[0], Search, &socket_head);
if (!skt)
{
Log (LOG_GENERAL, "# Cannot find socket name '%s'\n", argv[0]);
return (TCL_ERROR);
};
Log (
LOG_GENERAL,
"# producing Quartus pinfit for socket name '%s' in <%s>\n",
argv[0],
argv[1]);
ACFfile = trap_fopen (argv[1], "w"); /* open text file for writing */
if (!ACFfile)
{
Log (LOG_ERROR, "# Error opening Quartus pinfit file: <%s>\n", argv[1]);
return (TCL_ERROR);
}
else
{
create_unrouted_list ();
print_header (ACFfile, TOOL_NAME " : WRITE QUARTUS");
print_quartus_pinfit (ACFfile, skt, 0); /* used pins only */
return (TCL_OK);
};
}
/******************** Write PinList *************************/
/*
@title
write pinlist <socket_id*> <chip_id> [ <filename> ]
@text
Writes out a pinlist for the connections of socket(s) to an fpga. This is written to a file as
HTML. It also writes the pin index created by the 'bundle' command if this has been used on a
socket.
@break
This command is extremely useful for checking pin assignments
@listing
write fit x.*_a u1_a u1_a.html
@text
This lists all of the pinouts of connectors 'x' on board '_a' which are
connected to 'u1_a'.
@end
*/
int WritePinlistHandler (ET_TCLARGS)
{
FILE *ACFfile;
if (argc < 2)
return (TCL_ERROR);
if (argc > 2)
ACFfile = trap_fopen (argv[2], "w"); /* open text file for writing */
else
ACFfile = stdout;
if (!ACFfile)
{
Log (LOG_ERROR, "# Error opening Pinlist file: <%s>\n", argv[2]);
return (TCL_ERROR);
}
else
{
list_intersection (ACFfile, argv[0], argv[1]);
if (ACFfile != stdout)
{
}
}
if (ACFfile != stdout)
{
}
return TCL_OK;
};
/******************** Write xxx Menu ***********************/
CommandMenu const WriteMenu = {
{"acf",
3,
WriteAcfHandler, NULL, "Write out an 'Extended ACF' file", "<filename>", NULL},
{"connected",
3,
WriteConnectedHandler,
NULL,
"Write out an 'Extended ACF' file, with all connected pins",
"<filename>",
NULL},
{"net",
3,
WriteNetHandler,
NULL,
"Write out an 'Extended ACF' file, just the netlist part",
"<filename>",
NULL},
{"pcb",
3,
WriteFrbHandler,
NULL,
"Write out an 'FRB' PCB netlist file",
"<filename>",
NULL},
{"pinlist",
2,
WritePinlistHandler,
NULL,
"Write out Pin list for socket crossreferenced to FPGA",
"<socket ident> <fpga ident> <filename>",
NULL},
{"identifier",
2,
WriteIdHandler,
NULL,
"Write out device info by ident. (with all pins)",
"<ident> <filename>",
NULL},
{"name",
3,
WriteNameHandler,
NULL,
"Write out device info by Name (with used pins)",
"<name> <filename>",
NULL},
{"fit",
3,
WriteFitHandler,
NULL,
"Write out device info by Name (with Expanded VHDL busses)",
"<name> <filename>",
NULL},
{"flatten",
3,
WriteFlattenHandler,
NULL,
"Write out Flattened (no jumpers) netlist",
"<filename>",
NULL},
{"extern",
3,
WriteExternHandler,
NULL,
"Write sockets with external connection flags set ",
"<filename>",
NULL},
{"quartus",
3,
WriteQuartusPinfitHandler,
NULL,
"Write Quartus pinfit file",
"<name> <filename>",
NULL},
{"sockets", 3, WriteSocketHandler, NULL, "Write socket list to file ", "<filename>", NULL},
{"template", 3, WriteTemplateHandler, NULL, "Write socket templates", "<filename>", NULL},
{"ucf",
3,
WriteUCFHandler,
NULL,
"Write Xilinx User configuration pin assignments",
"<ident> <filename>",
NULL},
{"vhdl",
3,
WriteVHDLHandler,
NULL,
"Write out partition as VHDL",
"<new_entityname> <filename> [<template VHDL>]",
NULL},
{"vlog",
3,
WriteVLOGHandler,
NULL,
"Write out partition as Verilog",
"<new_entityname> <filename> [<template Verilog>]",
NULL},
{"par_acf",
3,
WriteParACFHandler,
NULL,
"Write out partition entity as Extended ACF",
"<new_entityname> <filename>",
NULL},
{NULL, 0, NULL, NULL, NULL, NULL, NULL},
};
/*********************** List components Command ***************************/
/* this lists all of the sockets to standard output */
/*
@title
list SOCkets
@text
List all of the known components in acfp form to standard output
@end
*/
int ListSktHandler (ET_TCLARGS)
{
list_components (stdout);
return (TCL_OK);
}
/*********************** List components Command ***************************/
/* this lists all of the sockets to standard output */
/*
@title
list RENames
@text
List all of the pin renames in ACFP form to standard output
@end
*/
int ListRenamesHandler (ET_TCLARGS)
{
print_pin_renames (stdout);
return (TCL_OK);
}
/*********************** List joins Command ***************************/
/* this lists all of the joins to standard output */
/*
@title
list JOIn
@text
List all of the netlist joins (jumpers and aliases) in ACFP form to standard output
@end
*/
int ListJoinHandler (ET_TCLARGS)
{
list_joined (stdout);
return (TCL_OK);
}
/*********************** List partition Command ***************************/
/* this lists all of the joins to standard output */
/*
@title
list PARtition
@text
List out to standard output all of the entities currently selected to to combine
in the top level entitiy when the partition is created
@end
*/
int ListPartHandler (ET_TCLARGS)
{
list_partition (stdout);
return (TCL_OK);
}
/*********************** List xref Command ***************************/
/* this lists all of the links from one socket to another
to standard output */
/*
@title
list XREF [<chip_id>]
@text
List cross references between this socket and all other named
sockets. The number of nets will be given, for each of the net
lists used by VERTICAL.
@listing
EPLD tool : list xref b*
-- Listing xref for socket names 'b*' --
-- Cross reference for socket 'Bcu'
Name : Named&Used, Named, Routed,Unrouted
Bcu : 106, 16, 2419, 4
unused1 : 0, 78, 0, 0
test_par : 92, 0, 2312, 0
unused2 : 0, 78, 0, 0
bcu_x101_a : 2, 5, 526, 1
test_par_x111_a : 1, 60, 476, 0
test_par_x112_a : 0, 12, 473, 0
mips_connector : 0, 0, 471, 0
simm_connector : 16, 2, 478, 0
pi_bus_clock : 1, 0, 39, 0
mips_clock : 0, 0, 39, 0
@text
The example above shows the '*' wildcard used to indcate all
named sockets with names beginning wiith 'b'. Name matching is
case insensitive.
@break
If the template name given is blank then all sockets will be
listed regardless of whether they are named, cross referenced
to named sockets. A large amount of meaningless data will be
obtained in this way.
@break
If the template name given is '*' then all named sockets are
cross-referenced.
@break
The command may be used both in partitioning and in general
PCB routing.
@break
Before partition, the cross reference connection count is
calculated via interpretation of the array range given in the
component entity declaration e.g. std_ulogic_vector ( 6
downto 0 ) will be seen as 7 wires when doing a partition, and
when the list xref command is given.
@break
After partition and synthesis all signals become one physical
wire or an array of discrete wires given as separate signals
in any case.
@end
*/
int ListXrefHandler (ET_TCLARGS)
{
char *SocketName;
SocketName = NULL; /* no names given, pass null pointer down */
if (argc > 0)
SocketName = argv[0];
count_paths (SocketName);
return (TCL_OK);
}
/*********************** List Templates Command ***************************/
/* this lists all of the available socket templates */
/*
@title
list TEMplates
@text
List out all of the CHIP pin templates (or VHDL components) that are available (the
device types)
@end
*/
int ListTemplHandler (ET_TCLARGS)
{
template_list ();
return (TCL_OK);
}
/*********************** List Generic Command ***************************/
/* this lists all of the global generic values */
/*
@title
list GENerics
@text
List out all of the generics (variables)
@end
*/
int ListGenericHandler (ET_TCLARGS)
{
Log (LOG_GENERAL, "-- partition generics\n");
list_generic_values (stdout, &partition_generics, 0);
Log (LOG_GENERAL, "-- global generics\n");
list_generic_values (stdout, &global_generics, 0);
return (TCL_OK);
}
/*********************** List Unrouted Command ***************************/
/* this lists all of the unrouted nets */
/*
@title
list UNRouted
@text
List out all of the currently unrouted nets. Use after ROUTE command to highlight those nets
still not routed.
@end
*/
int ListUnroutedHandler (ET_TCLARGS)
{
if (unrouted_list)
{
fprintf (stdout
, "-- Unrouted nets follow --\n");
list_nets (stdout, unrouted_list, 0);
}
else
fprintf (stdout
, "-- Currently no unrouted nets --\n");
return (TCL_OK);
}
/*********************** List Net Command ***************************/
/* this lists all of the nodes on the named net */
/*
@title
list NET <netname>
@text
Locates the named net, informs of which netlist it is found on, and then gives the node list of
the net (devices visited).
@end
*/
int ListNetHandler (ET_TCLARGS)
{
net_t *Net;
if (argc > 0)
{
Net = find_net (&named_list, Name, argv[0], Search);
if (Net)
Log (LOG_GENERAL, "-- Net on named list\n");
else
{
Net = find_net (&routed_list, Name, argv[0], Search);
if (Net)
Log (LOG_GENERAL, "-- Net on routed list\n");
else
{
Net = find_net (&unrouted_list, Name, argv[0], Search);
if (Net)
Log (LOG_GENERAL, "-- Net on unrouted list\n");
}
}
if (Net)
list_net_structure (stdout, Net, Net, 0, 0);
};
return (TCL_OK);
}
/*********************** List Command ***************************/
CommandMenu const ListMenu = {
{"sockets", 3, ListSktHandler, NULL, "List all known sockets", "", NULL},
{"joined", 3, ListJoinHandler, NULL, "List all joined nets", "", NULL},
{"xref", 3, ListXrefHandler, NULL, "List cross reference", "<socket_name>", NULL},
{"partition", 3, ListPartHandler, NULL, "List current partition", "", NULL},
{"templates", 3, ListTemplHandler, NULL, "List IC templates", "", NULL},
{"generics", 3, ListGenericHandler, NULL, "List Global Generics", "", NULL},
{"renames", 3, ListRenamesHandler, NULL, "List Pin Renames", "", NULL},
{"unrouted", 3, ListUnroutedHandler, NULL, "List Unrouted nets ", "", NULL},
{"net", 3, ListNetHandler, NULL, "List nodes on net", "<netname>", NULL},
{NULL, 0, NULL, NULL, NULL, NULL, NULL},
};
/*********************** Connection handler ***************************/
/* connects the two sockets pin for pin */
/*
@title
CONNect <socket_id1> <socket_id2>
@text
This command provides a means for automatically jumpering
together all pins on a pair of sockets. This connection is
different to the jumper command.
@break
The connection command simply takes two sockets and connects
up their pins in the routed metal netlist with the pins
completely in order. This is what happens when two sockets are
mated rather than a set of wirewrap jumpers being used to
connect the sockets.
@break
In order for this to work, the sockets must have pin
connections that can be found on the routed list : in other
words, they are connected via metal connections to other
sockets. Use of 'route' commands may be needed on some
occasions in order to create the metal connection netlist from
e.g. a list of sockets with assigned pins.
@break
Once the command is issued, the software takes each pin in
turn on <socket_id1> and searches for the pin with the same
identifier on <socket_id2>.
@break
If this pin is found then a jumper is created, even if the
nets that the sockets are on are already jumpered to something
else. This jumper created will have the identifier created by
the concatenation of the socket identifiers and the pin
identifiers : something like :
cn_<socket_id1>_<socket_id2>_<pin_id>
@break
This command facilitates the connection together of different
PCBs. If it is known that a connection cable (or X-PCB) is to
be used which has a different connection pattern and/or
connector type at each end of the cable, then it would be
possible to manually create a netlist for the cable as though
it were a PCB , with two sockets on it with appropriately
connected via routed nets.
@break
Reading this PCB in (using the socket/net name suffixing
feature of VERTICAL) and then issuing connection commands for
each socket pair (one for each end of the new cable) will
result in the desired set of jumpers being created.
e.g.
@break
A script to be executed by VERTICAL
@listing
# Crossover script
read conn_net _a
read conn_net _b
write acf cross_net0
# read in the connectors (have X1 and X2)
read xc_pcb _a
read xc_pcb _b
# the main file has sockets ID1 and ID2 on it. Because they
are read in
# with name suffixes _a and _b they are distinct.
# use the connector betweeen id1 on PCB _a and id1 on PCB _b
con id1_a x1_a
con id1_b x2_a
# use the connector betweeen id2 on PCB _a and id2 on PCB _b
con id2_a x1_b
con id2_b x2_b
write acf cross_net
Example of an acfp file describing a 4 way crossover (xc_pcb)
COMPONENTS
BEGIN
X1 : "test1" "PLUG4" "";
X2 : "test2" "PLUG4" "";
END;
WIRED_NETS
BEGIN
CONNECTION "c1" "" CREATED_NET;
X1(4); X2(1);
END_CONN;
CONNECTION "c2" "" CREATED_NET;
X1(3); X2(2);
END_CONN;
CONNECTION "c3" "" CREATED_NET;
X1(2); X2(3);
END_CONN;
CONNECTION "c4" "" CREATED_NET;
X1(1); X2(4);
END_CONN;
END;
@end
*/
int ConnectionHandler (ET_TCLARGS)
{
if (argc < 2)
return (TCL_ERROR);
create_all_jumpers (argv[0], argv[1]);
return (TCL_OK);
}