/*
* $id: c:\\cygwin\\cvsroot/vertical/cmdexec2.c,v 1.26 2001/10/31 16:23:22 mjames Exp $
*
* $Log: cmdexec2.c,v $
* Revision 1.1.1.1 2003/11/04 23:34:57 mjames
* Imported into local repositrory
*
* Revision 1.40 2003/01/02 21:37:14 mjames
* Experiment on creating NOT_ROUTABLE_H and NOT_ROUTABLE_L
* properties on the nets so that pin jumpers can be made without a problem.
*
* Still need to sort out pin assignments made to these not_routable nets
* which will become legal in some cases so that pullups and pulldown
* pins can be used on the FPGA.
*
* Revision 1.39 2002/09/30 13:23:53 MJAMES
* Tidied up the set par , set all_par and del par commands to make them
* all consistent with each other.
*
* Revision 1.38 2002/09/09 10:20:31 mjames
* Removed set generic range and replaced it with a set generic value command
* that takes both integers and ranges.
*
* Revision 1.37 2002/08/23 14:20:09 mjames
* Added Require command,
* modified edit ident and edit type commands comments to be more
* helpful.
*
* Revision 1.36 2002/08/06 12:53:03 mjames
* Merge in from latest version
*
* Revision 1.36 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.35 2001/12/24 21:13:59 mjames
* Added header includes to get correct declarations for all functions
* called from command handlers
*
* Revision 1.34 2001/12/24 20:08:11 mjames
* Added more information about ensure template command to help message
*
* Revision 1.33 2001/12/11 20:32:45 mjames
* Implemented regular expression pin name editing
*
* Revision 1.32 2001/11/19 10:41:53 mjames
* Merged back DTC release
*
* Revision 1.31 2001/11/19 10:39:47 mjames
* Merge conflict resolution
*
* Revision 1.30 2001/11/09 22:14:44 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.29.2.1 2001/11/16 15:12:23 mjames
* Altered modify_names command in response to TH request.
*
* Revision 1.29 2001/11/01 11:08:05 mjames
* Changed help message on extract_templates call
*
* Revision 1.28 2001/10/31 22:28:27 mjames
* Problems with regular expression argument lists.
*
* Revision 1.27 2001/10/31 22:20:00 mjames
* Tidying up problematical comments caused by CVS
* 'intelligent' comment guessing
*
* Revision 1.26 2001/10/31 16:23:22 mjames
* Added a datastructure to hide regular expression information from programs.
* Changed call to regexec to indicate 0 subexpressions to be matched
* rather than a number dependent on strlen(string) which was wrong.
*
* Revision 1.25 2001/10/23 21:14:28 mjames
* Added match_template command : purpose to remove connections
* to device pins which do not exist in the template of that device.
*
* Modified set type_id to use wildcards (the only case where this applies)
*
* Revision 1.24 2001/10/18 21:36:01 mjames
* Added modify pins command : nets inherit identifier from selected socket and pin on that socket to ease cross referencing.
*
* Revision 1.23 2001/10/11 16:10:17 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.22 2001/10/10 20:19:19 mjames
* added echoq command to give quoted arguments for checking
*
* Revision 1.21 2001/10/07 20:50:54 mjames
* Added wildcard checking (warn user about
* using wildcard '*' on the end of a string in stead of wildcard '.*')
*
* Revision 1.20 2001/10/02 20:55:18 mjames
* Edited help files to try and get them more up to date.
*
* Revision 1.19 2001/09/25 23:15:24 mjames
* Converted wildcards to use proper regexp pattern match library
*
* Revision 1.18 2001/09/13 21:08:54 mjames
* Added initial bundle/unbundle commands.
*
* Revision 1.17 2001/08/23 21:34:27 mjames
* Added version command to list out all of the tags
*
* Revision 1.16 2001/08/23 20:34:12 mjames
* Made sure that attempts to create duplicate socket identifiers or names fails with the set id and set name commands.
*
* Revision 1.15 2001/08/23 20:06:30 mjames
* Added 'reserve' command for use with preroute commands.
* This command provides the 'correct' documented pin reservation
* behaviour.
*
* Revision 1.14 2001/07/20 10:47:43 mjames
* Allowed setting of pin routing group properties on pins on nets
* by the "set pin" command
*
* Revision 1.13 2001/07/02 21:21:31 mjames
* Added logging to standard output as well as standard error
* in the 'echoe' command
*
* Revision 1.12 2001/06/21 10:52:43 mjames
* Added "echoe" command which echos an error string to the output file.
* Also added command documentation for some more of the command line commands.
*
* Revision 1.11 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.10 2001/06/06 12:10:25 mjames
* Move from HPUX
*
* Revision 1.9 2001/04/09 14:58:29 mjames
* Added capability to delete generics from specific sockets.
*
* Revision 1.8 2001/04/06 22:47:01 mjames
* Added doc2, the creator of documentation to Vertical scripts uses PERL
*
*
* Also correcting generic behaviour and the printing of Verilog.
*
* Revision 1.7 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.6 2001/03/29 22:08:55 mjames
* Modified to define the scope of set generic commands : now can be global
* or defined for a socket or a simple wildcarded list of sockets.
*
* In addition the is_FPGA property has been activated so that FPGA components
* are not listed out when used in a Verilog (.vb) file.
*
* Version raised to 11.02
*
* Revision 1.5 2001/01/26 21:50:10 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/11/29 23:25:39 mjames
* Corrected a failure to cope with integer type ports on entities
* in acf_yacc.y
*
* Altered the elaborate command to call up the template command aw well
*
* Altered equivalent pins handler to cope with the absence of any templates
*
* Altered printout routines to use correct datatype for expansion of
* VHDL constants
*
* Revision 1.1.1.1 2000/10/19 21:58:35 mjames
* Mike put it here
*
*
*
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <regex.h>
#include "vertcl_main.h"
#include "expression.h"
#include "generic.h"
#include "database.h"
#include "printout.h"
#include "routing.h"
#include "jumpering.h"
#include "ext_nets.h"
#include "statistics.h"
#include "partition.h"
#include "cmdparse.h"
#include "cmdexec.h"
#include "cmdutil.h"
#include "cmdlog.h"
#include "rename.h"
#include "template.h"
#include "chck_names.h"
#include "acf_yacc.h"
#include "sorting.h"
#include "bundle.h"
#include "equivalent.h"
#include "unrouted.h"
#include "acf_lex_ext.h"
#ident "@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/cmdexec2.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $"
/************************************************************************/
/* Command handling code */
/************************************************************************/
/*********************** Set id (of) <name> (to) <id>Command ***************************/
/*
@title
set ID_of_name <device_name> <new_id>
@application vertical_pin
@application vertical_pcb
@text
Set Identifier for Name. Change the identifier for a named
socket. This is used when VERTICAL invents identifiers e.g.
'ID1', and you would rather call it e.g. 'U101'.
Assuming chip 'multiplier' is in socket 'ID1'
@listing
set id multiplier U101
@text
Command will fail if there is already a device with the new
identifier.
@end
*/
int SetIdOfNameHandler(ET_TCLARGS)
{
socket_t * chip;
if (argc < 2)
return(TCL_ERROR);
/* safety catch code added : is the ident already in use ? */
chip = find_socket(Ident,argv[1],Search,&socket_head);
if(chip) {
Log(LOG_ERROR,"Changing socket id for name='%s' fails : id '%s' in use already\n",argv[0],argv[1]);
return (TCL_ERROR);
};
chip = find_socket(Name,argv[0],Search,&socket_head);
if(!chip) {
Log(LOG_ERROR,"Changing ID: Cannot find socket with name='%s'\n",argv[0]);
return (TCL_ERROR);
};
set_socket(chip,Ident,argv[1]);
Log(LOG_GENERAL,"# Set ident of socket name='%s' to be '%s'\n",argv[0],argv[1]);
return(TCL_OK);
}
/*********************** Set type (of) <name> (to) <type> Command ***************************/
/*
@title
set TYpe_name <device_name> <new_type>
@text
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
Provides a means of assigning a device type to a socket where
the socket contains a design e.g. an FPGA. This can then be
used to tag sockets for the application of pin templates.
@end
*/
int SetTypeOfNameHandler(ET_TCLARGS)
{
socket_t * chip;
if (argc < 2)
return(TCL_ERROR);
chip = find_socket(Name,argv[0],Search,&socket_head);
if(!chip) {
Log(LOG_GENERAL,"Cannot find socket with name='%s'\n",argv[0]);
return (TCL_ERROR);
};
set_socket(chip,Type,argv[1]);
Log(LOG_GENERAL,"# Set type of socket name='%s' to be '%s'\n",argv[0],argv[1]);
return(TCL_OK);
}
/*********************** Set type (of) <ident> (to) <type> Command ***************************/
/*
@title
set TYPE_Id <device_id> <new_type>
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Provides a means of assigning a device type to a socket where
the socket does not necessarily contain a design e.g. a
resistor pack. This can then be used to tag sockets for the
application of pin templates. This has been converted to wildcard usage, as this means
all Rxxx can be made type 'resistor'.
@end
*/
int SetTypeOfIDHandler(ET_TCLARGS)
{
socket_t * skt;
int rc;
/* compile regular expression */
vert_regex_t * preg;
char * pattern;
if(argc < 2 )
{
Log(LOG_ERROR,"-- Need a device ID and a type\n");
return(TCL_ERROR);
}
pattern = argv[0];
Log(LOG_GENERAL,"-- Beginning setting pin template: prefix '%s' --\n",pattern);
rc = vert_regcomp(&preg,pattern);
if (rc != 0 )
{
char errbuff[100];
regerror(rc,preg->preg,errbuff,100);
Log(LOG_ERROR,"-- Problem (rc=%d) %s with '%s' as regular expression\n",rc,errbuff,pattern);
return TCL_ERROR;
}
else
{
Log(LOG_GENERAL,"-- Using '%s' as match pattern\n",pattern);
}
skt = socket_head;
while(skt)
{
int found;
found = regexec(preg->preg,skt->identifier,0,preg->regpatt,0);
if(!found)
{
set_socket(skt,Type,argv[1]);
if(level & 1)
{
Log(LOG_GENERAL,"# Set type of socket Ident='%s' to be '%s'\n",skt->identifier,argv[1]);
}
}
skt = skt->next;
}
vert_regfree(&preg);
return(TCL_OK);
}
/*********************** Set Partition Command ***************************/
/*
@title
set PARtition <socket_name> <socket_name> ......
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Sets partition list to be the following named chip sockets,
the names being those used in the CHIP declarations in the
acfp file. Wildcarding can be used to select related groups of
sockets. All this does is select a socket/entity as being a member of the
set of socket/entities that will be selected in this partition.
@break
@If no arguments are given this is the same as the set all_par command, in that
It routes the design before selecting the partition
@end
*/
int SetPartHandler(ET_TCLARGS) {
int i = 0;
int Status = TCL_OK;
if(argc == 0)
{
name_routed_nets();
Status = set_clear_partition(".*",1);
}
else
{
for(i=0;i<argc && Status == TCL_OK;i++)
{
Status = set_clear_partition(argv[i],1);
}
}
if(Status != TCL_OK)
{
Log(LOG_ERROR,"-- ERROR with pattern '%s'\n",argv[i]);
}
return(TCL_OK);
}
/*********************** Set Partition Command ***************************/
/*
@title
set all_par
@application vertical_hdl
@text
All sockets are selected for the partition. This can be used
as part of the process of creating a top level wrapper for the
entire design in VHDL.
@break
This is now no different from
@listing
set partition
@end
*/
int SetPartAllHandler(ET_TCLARGS)
{
name_routed_nets();
return set_clear_partition(".*",1);
}
/*********************** Set name (of) <id> (to) <name> Command ***************************/
/*
@title
set NAme_of_id <device_id> <new_name>
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Sets name for socket identified by identifier e.g. 'U1' etc.
This is used as a means of assigning chip names given in CHIP
declarations in an ACF file to actual PCB socket positions. It
is usable as an alternative to the COMPONENTS block in the
ACFplus file.
@break
One an ACFplus file is written (write acf) then the COMPONENTS
block will be updated with the CHIP to socket assignment given
by this command.
@break
Fails if the name is already in use in the design.
@end
*/
int SetNameOfIdHandler(ET_TCLARGS)
{
socket_t * chip;
if (argc < 2)
return(TCL_ERROR);
/* safety catch code added : is the name already in use ? */
chip = find_socket(Name,argv[1],Search,&socket_head);
if(chip) {
Log(LOG_ERROR,"Renaming socket id='%s' fails : name '%s' in use already\n",argv[0],argv[1]);
return (TCL_ERROR);
};
chip = find_socket(Ident,argv[0],Search,&socket_head);
if(!chip) {
Log(LOG_ERROR,"Cannot find socket with ident='%s' to rename\n",argv[0]);
return (TCL_ERROR);
};
set_socket(chip,Name,argv[1]);
Log(LOG_GENERAL,"# Set name of socket ident='%s' to be '%s'\n",argv[0],argv[1]);
return(TCL_OK);
}
/*********************** Set Port Command ***************************/
/* Forces the port to leave the partition */
/*
@title
set PORt <net_name>
@application vertical_hdl
@text
Forces port on the exterior of a partition if the net is used
inside. This is used in VHDL partitioning.
@break
This is used when a net completes its connection from source
to all destinations entirely within the partition. Set port
ensures the net is observable via an output port on the
exterior of the partition.
@break
For example: to observe an internal clock signal at the top
level of the partition. Note this only works for nets which
are visible at the top level of a created entity representing
a partition of the design.
@listing
partition
set port divided_clock
@end
*/
int SetPortHandler(ET_TCLARGS)
{
int i;
for(i=0;i<argc;i++){
force_port(argv[i]);
}
return(TCL_OK);
}
/*********************** Set Routable Command ***************************/
/* Sets nets to be routable */
/*
@title
set routable <net> <net> <net>
@application vertical_pin
@application vertical_pcb
@text
Sets the routable flags on wildcarded nets.
VERTICAL will see these nets as routable and therefore
use them for logic signal assignments.
@end
*/
int SetRouteHandler(ET_TCLARGS)
{
int i;
for(i=0;i<argc;i++){
force_route(argv[i],Free);
}
return(TCL_OK);
}
/*********************** Set High Command ***************************/
/* Sets nets to be not routable */
/*
@title
set high <net> <net> <net>
@application vertical_pin
@application vertical_pcb
@text
Sets the routing flags on wildcarded nets as Not_Routable_H
VERTICAL will see these nets as generally not routable for signals
but pulled up to a logic '1'.
@end
*/
int SetHighHandler(ET_TCLARGS)
{
int i;
for(i=0;i<argc;i++){
force_route(argv[i],Not_Routable_H);
}
return(TCL_OK);
}
/*********************** Set Low Command ***************************/
/* Sets nets to be routable */
/*
@title
set low <net> <net> <net>
@application vertical_pin
@application vertical_pcb
@text
Sets the routing flags on wildcarded nets as Not_Routable_L
VERTICAL will see these nets as generally not routable for signals
but pulled up to a logic '0'.
@end
*/
int SetLowHandler(ET_TCLARGS)
{
int i;
for(i=0;i<argc;i++){
force_route(argv[i],Not_Routable_L);
}
return(TCL_OK);
}
/*********************** Set Group ***************************/
/* Sets FastTrack routing flags */
/*
@title
set group <control> <socket> [ <socket> * ]
@application vertical_hdl
@text
Control is an integer value. Socket is a wildcard
@break
Pin group control flags are setup for each socket:
for each pin on that socket , while routing , if
@listing
<pin group pin A> & <control> == <pin group pin B> & <control>
@text
Then the pins are seen to be interchangeable within their groups. This allows for the scrambling of
a databus for e.g. a RAM chip where data in and out are shared. Some address pins could also be shared
in this case.
@break
Quite often a pin would be given a pin group which is a power of 2:
interchangeable address pins might be placed in group 1, interchangeable data pins in group 2.
@end
*/
int SetGroupHandler(ET_TCLARGS) {
int i;
long num;
if (argc == 0)
return TCL_ERROR;
num
= atoi(argv
[0]); /* 16 bit number */
for (i=1;i<argc;i++ ){
set_group_route_flags(argv[i],(int)num);
}
return TCL_OK;
}
/*********************** Set Group ***************************/
/* Sets FastTrack pin group membership on device pins */
/*
@title
set pin_group <control> <socket_id>[(<pin_id>)]
@application vertical_pin
@text
Control is an integer value.
@break
Pin group memberships are setup for each pin on each socket. Socket identifier and pin identifiers can be wildcarded.
The pin identifier is wrapped by "()" brackets.
@listing
set pin_group 11 X.*(.*a)
@text
All pins on sockets with identifiers beginning with 'X' and whose pin identifier ends
in 'a' are to be made a member of group 11.
@listing
set pin_group 12 X12
@text
All pins on X12 are members of group 12; If the pin identifier is omitted this is the same as 'all pins on the socket'. Otherwise pins with Id matching will be processed.
@end
*/
int SetPinGroupHandler(ET_TCLARGS) {
int i;
long num;
if (argc == 0)
return TCL_ERROR;
num
= atoi(argv
[0]); /* 16 bit number */
for (i=1;i<argc;i++ ){
set_pin_group_flags(argv[i],(int)num);
}
return TCL_OK;
}
/*********************** Set External Command ***************************/
/* Sets sockets as external connections. Prevents 'rsvXXXXz' nets name
from appearing on connected nets */
/*
@title
set EXTernal [<prefix> | <identifier> ]
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
The concept of internal and external sockets is used in
several situations. Imagine that an external socket is placed
in a position where it is visible and the other non-external
sockets are not visible.
@break
Once a socket has been declared as external, different parts
of VERTICAL use this information in different ways. If the
user wishes to set different sockets as 'external' at
different times then this can be achieved by the use of set
and del external commands.
@break
Wildcards using regexp pattern matching are allowed
@break
When routing, an internal socket will have pins that are
connected to nets but not required on the socket named as
'rsvXXXXz'. An external socket will have these pins named
according to the name of the net. (see route and preroute command)
@break
When creating jumpers, only those sockets marked as external
will be considered for jumpering. (see jumper command)
@break
In addition, using the write external command will list only
those sockets which have the external attribute.
@listing
set external X.*
@text
Will flag all sockets with identifier prefixed by 'X' as
external.
So in this case e.g. X1, X2, X100, X101_a will all be labelled
as external.
Usage of set external is cumulative.
@break
Only external sockets are listed out in write vlog command
to filter out unwanted sockets by deleting the external
property.
@end
*/
int SetExternHandler(ET_TCLARGS)
{
int i;
for(i=0;i<argc;i++) {
set_external_flags(argv[i]);
}
return(TCL_OK);
}
/**************************************************************/
/* wildcard setting of generics */
/**************************************************************/
static void set_wildcard_generic( char * template,
generic_info_t * info)
{
int rc;
socket_t * skt = socket_head;
int found = 0;
/* compile regular expression */
vert_regex_t * preg;
/* pick out a wildcard if all sockets then scope is the global generics */
if(ISNULLSTR(template))
{
set_generic_value(&global_generics,info);
return;
}
rc = vert_regcomp(&preg,template);
if (rc != 0 )
{
char errbuff[100];
regerror(rc,preg->preg,errbuff,100);
Log(LOG_ERROR,"-- Problem (rc=%d) %s with '%s' as regular expression\n",rc,errbuff,template);
return /*TCL_ERROR*/;
}
else
{
Log(LOG_GENERAL,"-- Using '%s' as match pattern\n",template);
}
while(skt) {
found = regexec(preg->preg,skt->identifier,0,preg->regpatt,0);
if(!found) {
set_generic_value(&skt->generics,info);
}
skt = skt->next;
}
vert_regfree(&preg);
}
/*********************** Set FPGA Command ***************************/
/* Sets a socket as containing an FPGA : if set then a module declaration will not be made in
when writing VERILOG out */
/*
@title
set fpga <socket> <line_replacing_declaration>
@application vertical_hdl
@text
Sets sockets as containing an FPGA : if set then a module declaration will not be made in
when writing VERILOG out
@end
*/
int SetFPGAHandler(ET_TCLARGS)
{
generic_info_t info;
if(argc<2) {
Log(LOG_ERROR,"-- need 2 arguments to Set FPGA\n");
return TCL_ERROR;
}
info.name = "fpga_file";
info.typename = "string";
info.g_type = IS_ATTRIBUTE;
info.expr = compile_expression_from_string(argv[1]);
info.g_class = DEFINED;
set_wildcard_generic(argv[0],&info);
set_FPGA_flags(argv[0]); /* set flags */
return(TCL_OK);
}
/*********************** Set Generic String ***************************/
/* Sets a named generic to a value or string */
/*
@title
set generic string <ident> <scope> <string>
@application vertical_hdl
@text
This command sets up a generic identified by name as <ident>
(variable) to be a string value.
@break
If <scope> is "" then the scope of the generic is global, applied to all sockets and signals within the design
@listing
set generic string vhdl_basetype "" "std_logic_vector"
@text
Will set up a global generic called vhdl_basetype with value "std_logic_vector"
@break
If <scope> is "*" then the generic is applied to all sockets. This is used to set a default value for all instances of that
generic to the string value given. Its scope is local to each socket. It can be overridden by
specific socket generic assignments.
@break
If <scope> is a wildcard (ends in "*") then all of the sockets matching will have their generic values set.
@end
*/
int SetGenericStringHandler(ET_TCLARGS) {
generic_info_t info;
if (argc < 3)
return TCL_ERROR;
info.name = argv[1];
info.typename = "string";
info.g_type = IS_STRING;
info.expr = compile_string(argv[2]);
set_wildcard_generic(argv[0],&info);
return(TCL_OK);
}
/*********************** Set Generic Declaration ***************************/
/* Sets a named generic to a value or string */
/*
@title
set generic declaration <ident> <scope> <string>
@application vertical_hdl
@text
This sets up generics which are string generics but which are used in Verilog declarations
for use with Certify. These are enclosed in verilog comments as pragmas when written out.
@break
See set generic string for more information.
@end
*/
int SetGenericDeclarationHandler(ET_TCLARGS) {
generic_info_t info;
info.name = argv[1];
info.typename = "string";
info.g_class = DEFINED;
info.g_type = IS_DECLARATION_DIRECTIVE;
info.expr = compile_string(argv[2]);
set_wildcard_generic(argv[0],&info);
return(TCL_OK);
}
/*********************** Set Generic instance ***************************/
/* Sets a named generic to a value or string */
/*
@title
set generic instance <ident> <scope> <string>
@application vertical_hdl
@text
This sets up generics which are string generics but which are used in Verilog instances
for use with Certify. These are enclosed in verilog comments as pragmas when written out.
@break
See set generic string for more information.
@end
*/
int SetGenericInstanceHandler(ET_TCLARGS) {
generic_info_t info;
if (argc < 3)
return TCL_ERROR;
info.name = argv[1];
info.typename = "string";
info.g_class = DEFINED;
info.g_type = IS_INSTANCE_DIRECTIVE;
info.expr = compile_string(argv[2]);
set_wildcard_generic(argv[0],&info);
return(TCL_OK);
}
/*********************** Set Generic Integer ***************************/
/* Sets a named generic to an integer value*/
/*
@title
set generic integer <ident> <scope> <expression>
@application vertical_hdl
@text
This sets up generics which are integer expressions, usable in place of VHDL constant declarations in .acfp files.
@break
See set generic string for more information.
@end
*/
int SetGenericIntegerHandler(ET_TCLARGS) {
generic_info_t info;
if (argc < 3)
return TCL_ERROR;
info.name = argv[1];
info.typename = "integer";
info.g_type = IS_INTEGER;
info.g_class = DEFINED;
info.expr = compile_expression_from_string(argv[2]); /* this needs to be altered */
set_wildcard_generic(argv[0],&info);
return(TCL_OK);
}
/*********************** Set Generic Value ***************************/
/* Sets a named generic to an integer range : workout from range whether this is TO or DOWNTO */
/*
@title
set generic value <ident> <scope> <expression>
@application vertical_hdl
@text
Sets a named generic to an integer range : workout from range whether this is TO or DOWNTO, (TO has first expression less than second), usable in place of VHDL constant declarations in .acfp files.
@break
See set generic string for more information.
@end
*/
int SetGenericValueHandler(ET_TCLARGS) {
expression_t * p;
generic_info_t info ;
if (argc<3)
return (TCL_ERROR);
info.name = argv[1];
p = compile_expression_from_string(argv[2]);
if(p)
{
switch(p->opcode)
{
case TO:
case DOWNTO:
{
info.g_type = p->opcode;
info.typename = "integer range";
break;
}
case TXT_STRING:
{
info.g_type = IS_STRING;
info.typename = "string";
break;
}
default:
{
info.g_type = IS_INTEGER;
info.typename = "integer";
break;
}
}
}
info.g_class = DEFINED;
info.expr = p;
set_wildcard_generic(argv[0],&info);
return(TCL_OK);
}
/*********************** Set Generic Attribute ***************************/
/* Sets a named generic attribute to an integer value*/
/*
@title
set generic attribute <ident> <scope> <expression>
@application vertical_hdl
@text
This sets up generics which are integer expressions, usable in place of VHDL constant declarations in .acfp files.
@break
See set generic string for more information.
@end
*/
int SetGenericAttributeHandler(ET_TCLARGS) {
generic_info_t info;
if (argc < 3)
return TCL_ERROR;
info.name = argv[1];
info.typename = "attribute";
info.g_type = IS_ATTRIBUTE;
info.expr = compile_expression_from_string(argv[2]);
info.g_class = DEFINED;
set_wildcard_generic(argv[0],&info);
return(TCL_OK);
}
/*********************** Set Generic Boolean ***************************/
/* Sets a named generic to an integer value*/
/*
@title
set generic boolean <ident> <scope> <integer>
@application vertical_hdl
@text
This sets up booleans containing the value of boolean expressions, usable in place of VHDL constant declarations in .acfp files.
@break
Any non-zero integer is TRUE, and zero is FALSE.
@break
See set generic string for more information.
@end
*/
int SetGenericBooleanHandler(ET_TCLARGS) {
generic_info_t info;
if (argc < 3)
return TCL_ERROR;
info.name = argv[1];
info.typename = "integer";
info.g_type = IS_BOOLEAN;
/* think about using : convert_num(char * string,int * value) */
info.expr = compile_expression_from_string(argv[2]); /* Can use true/false as well now ... */
set_wildcard_generic(argv[0],&info);
return(TCL_OK);
}
/*********************** Set Generic Menu ***************************/
/* Sets a named generic to a value or string */
CommandMenu SetGenericMenu= {
{"attribute", 3, SetGenericAttributeHandler,NULL,
"Integer instance attribute",
"<socket*>|\"\" <name> <value>",NULL},
{"string", 3, SetGenericStringHandler,NULL,
"String constant",
"<socket*>|\"\" <name> <string text>",NULL},
{"integer", 3, SetGenericIntegerHandler,NULL,
"Integer constant expression",
"<socket*>|\"\" <name> <value>",NULL},
{"boolean", 3, SetGenericBooleanHandler,NULL,
"Boolean constant",
"<socket*>|\"\" <name> <value>",NULL},
{"value", 3, SetGenericValueHandler,NULL,
"Generic expression",
"<socket*>|\"\" <name> <expression>",NULL},
{"declaration", 3, SetGenericDeclarationHandler,NULL,
"Certify .vb declaration directive",
"<socket*>|\"\" <name> <value>",NULL},
{"instance", 3, SetGenericInstanceHandler,NULL,
"Certify .vb instance directive",
"<socket*>|\"\" <name> <value>",NULL},
{ NULL,0,NULL,NULL,NULL}
};
/*********************** Set Command ***************************/
CommandMenu SetMenu = {
{"id_of_name", 2, SetIdOfNameHandler,NULL,
"Set Identifier for Name",
"<device_name> <new_id>",NULL},
{"name_id", 2, SetNameOfIdHandler,NULL,
"Sets name for socket identifier",
"<device_id> <new_name>",NULL},
{"type_id", 6, SetTypeOfIDHandler,NULL,
"Sets type for socket identifier",
"<device_id> <new_type>",NULL},
{"type_name", 2, SetTypeOfNameHandler,NULL,
"Sets type for device named",
"<device_name> <new_type>",NULL},
{"partition", 3, SetPartHandler,NULL,
"Sets partition list",
"<socket_name>*",NULL},
{"all_partition",5, SetPartAllHandler,NULL,
"Sets partition list to all sockets",
"",NULL},
{"port", 3, SetPortHandler,NULL,
"Forces port on partition if used inside",
"<net_name_prefix>*",NULL},
{"routable", 3, SetRouteHandler,NULL,
"Flags routed nets as routable",
"<net_id>*",NULL},
{"high", 3, SetHighHandler,NULL,
"Flags routed nets as not routable logic 1",
"<net_id>*",NULL},
{"low", 3, SetLowHandler,NULL,
"Flags routed nets as not routable logic 0",
"<net_id>*",NULL},
{"external", 3, SetExternHandler,NULL,
"Sets socket IDs prefixed by prefix as external",
"<prefix>*",NULL},
{"fpga", 3, SetFPGAHandler,NULL,
"Sets socket IDs prefixed by prefix as being FPGA: no Verilog declaration",
"<prefix>*",NULL},
{"group", 3, SetGroupHandler,NULL,
"Enables 'FastTrack group' routing: 1=row 2=col 3=both",
"<mask_value> [<id_prefix>*]",NULL},
{"pin_group", 3, SetPinGroupHandler,NULL,
"Sets pin group membership on pins of devices",
"<group> <id_prefix>[(<pin_prefix>)]",NULL},
{"generic", 3, NULL,SetGenericMenu,
"Sets generic value ",
"more",NULL},
{ NULL,0,NULL,NULL,NULL,NULL},
};
/*********************** Delete Port Command ***************************/
/* Deletes the ports from the partition */
/*
@title
delete port <port> [ <port> ]*
@application vertical_hdl
@text
Remove port from partition. If a signal (port) of that name
exists on the top level of a partition, it is made to be
hidden inside.
@break
This is used e.g. when a local copy of a bus is used in all
partitions on a multiple EPLD board.
If the bus appears as a port on all of the EPLDs as it would
by default, as there is a driver inside each EPLD and inputs
in each EPLD, then there will be multiple driver conflicts on
the breadboard.
@end
*/
int DelPortHandler(ET_TCLARGS)
{
int i;
for(i=0;i<argc;i++) {
delete_port(argv[i]);
}
return(TCL_OK);
}
/*********************** Set Not Routable Command ***************************/
/* Sets nets to be not routable */
/*
@title
delete route <net> [ <net> ] *
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Remove the routable property from the named nets. These nets will not be used in routing by vertical.
@listing
del route VCC.* GND.* NCONFIG CONF_DONE
@text
Will ensure that these nets are set as not routable.
This is often seen in netlist import scripts.
@end
*/
int DelRouteHandler(ET_TCLARGS)
{
int i;
for(i=0;i<argc;i++) {
force_route(argv[i],Not_Routable);
}
return(TCL_OK);
}
/*********************** Delete NetName Command ***************************/
/* Deletes the name fileds form nets by ID from the partition */
/*
@title
delete netname <net> [ <net> ] *
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
The signal names assigned to the nets are removed, so that clean netlists are
written out without any routing history. Use this if when importing netlists,
where the net names used may match those in the as yet unrouted design that
will use those nets. Routing that tries to reuse nets which were previously
used will be confused by names appearing on the nets.
@end
*/
int DelNetNameHandler(ET_TCLARGS)
{
int i;
for(i=0;i<argc;i++) {
del_net_names(argv[i]);
}
return(TCL_OK);
}
/*********************** Delete Port Command ***************************/
/* Clears the is_external bits on all sockets */
/*
@title
delete EXTernal <socket> [ <socket ] *
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
This clears the external attribute flags from all sockets. The
name matching rules are the same as for set external command
@end
*/
int DelExternHandler(ET_TCLARGS)
{
int i;
for(i=0;i<argc;i++) {
clear_external_flags(argv[i]);
}
return(TCL_OK);
}
/*********************** Delete Port Command ***************************/
/* Clears the is_FPGA bits on all sockets */
/*
@title
delete FPGA <socket> [ <socket ] *
@application vertical_hdl
@text
This clears the FPGA attribute flags from all sockets. The
name matching rules are the same as for set FPGA command
@end
*/
int DelFPGAHandler(ET_TCLARGS)
{
int i;
for(i=0;i<argc;i++) {
clear_FPGA_flags(argv[i]);
}
return(TCL_OK);
}
/*********************** Delete Partition Command ***************************/
/* Clears the partition selection on all sockets */
/*
@title
delete partition <socket> [ <socket>* ]
@application vertical_hdl
@text
This clears the partition flags from wildcarded named sockets. The
name matching rules are the same as for set partition command
@break
If no arguments are given this results in routing created for the partition being
ripped up. Use
@listing
delete partition
@text
to clean up
@end
*/
int DelPartitionHandler(ET_TCLARGS)
{
int i,Status = TCL_OK;
if (argc==0)
{
clear_partition_nets();
Status = set_clear_partition(".*",0);
}
for(i=0;i<argc && Status == TCL_OK;i++){
Status = set_clear_partition(argv[i],0);
}
if(Status != TCL_OK)
{
Log(LOG_ERROR,"-- ERROR with pattern '%s'\n",argv[i]);
}
return(Status);
}
/*********************** Delete Generic Command ***************************/
/*
@title
delete generic <generic_name> <scope>
@application vertical_hdl
@text
This function will delete any generic given in either global generics or all sockets matching pattern.
See set generic for naming rules.
@end
*/
int DelGenericHandler(ET_TCLARGS)
{
generic_info_t info ;
int rc;
socket_t * skt = socket_head;
int found = 0;
/* compile regular expression */
vert_regex_t * preg;
if (argc<2)
return (TCL_ERROR);
info.name = argv[1];
/* pick out a wildcard if all sockets then scope is the global generics */
if(ISNULLSTR(argv[0]))
{
del_generic_value(&global_generics,&info);
return 0;
}
rc = vert_regcomp(&preg,argv[0]);
if (rc != 0 )
{
char errbuff[100];
regerror(rc,preg->preg,errbuff,100);
Log(LOG_ERROR,"-- Problem (rc=%d) %s with '%s' as regular expression\n",rc,errbuff,argv[0]);
return TCL_ERROR;
}
else
{
Log(LOG_GENERAL,"-- Using '%s' as match pattern\n",argv[0]);
}
while(skt) {
found = regexec(preg->preg,skt->identifier,0,preg->regpatt,0);
if(!found) {
del_generic_value(&skt->generics,&info);
}
skt = skt->next;
}
vert_regfree(&preg);
return 0;
}
/*********************** Delete Command ***************************/
CommandMenu DeleteMenu= {
{"port", 2, DelPortHandler,NULL,
"Remove port from partition",
"<net_name_prefix>* ",NULL},
{"routable", 3, DelRouteHandler,NULL,
"Flags routed nets as NOT_ROUTABLE",
"<net_id>*",NULL},
{"netname", 3, DelNetNameHandler,NULL,
"Remove name from nets by ID",
"<net_ID>*",NULL},
{"external", 3, DelExternHandler,NULL,
"Set sockets as being internal",
"<name_prefix>*",NULL},
{"fpga", 3, DelFPGAHandler,NULL,
"Set sockets as not being FPGA: Verilog declaration given",
"<name_prefix>*",NULL},
{"generic", 3, DelGenericHandler,NULL,
"Removes generic values from sockets",
"<socket>* <generic_name>",NULL},
{"partition", 3, DelPartitionHandler,NULL,
"Clear the partition list",
"",NULL},
{ NULL,0,NULL,NULL,NULL}
};
/*********************** Partial routing calls ***************************/
/*********************** Route By Path ***************************/
/*
@title
preroute path
@application vertical_pin
@application vertical_pcb
@text
Route by path only: If there exists a routed path between the
chips which has the correct pin directions on each chip
visited, then this path will be used to carry the unrouted
net.
@end
*/
int RoutePathHandler (ET_TCLARGS)
{
Log (LOG_GENERAL, "#begin routing\n");
perform_routing(By_Net);
Log (LOG_GENERAL, "#done routing\n");
return (TCL_OK);
}
/*********************** Route By Exact Path ***************************/
/*
@title
preroute EXact
@application vertical_pin
@application vertical_pcb
@text
Route by exact same path only: As for preroute path, but the
unrouted net and the routed net must both visit the same pins
on the chips that are visited by the nets. This is important
where there are very specific pin functions associated with a
pin.
@break
It also helps with maintenace of similar routing if a design
is recompiled via maxplus2, the newly unrouted nets will tend
to be routed on the same routed nets as for the first compile
if this is used.
@end
*/
int RouteExactPathHandler (ET_TCLARGS)
{
Log (LOG_GENERAL, "#begin routing\n");
perform_routing(By_Exact_Net);
Log (LOG_GENERAL, "#done routing\n");
return (TCL_OK);
}
/*********************** Route By Fixed Net ***************************/
/*
@title
preroute FIxed
@application vertical_pin
@application vertical_pcb
@text
Route by fixed nets only. Any nets which have a fixed pin on
them will be routed first. Fixed pins are those where the pin
identifier used on a socket in the unrouted list should carry
the same signal after routing. This is used to keep e.g.
external connections.
@end
*/
int RouteFixedNetHandler (ET_TCLARGS)
{
Log (LOG_GENERAL, "#begin routing\n");
perform_routing(By_Fixed_Net);
Log (LOG_GENERAL, "#done routing\n");
return (TCL_OK);
}
/*********************** Route By Name ***************************/
/*
@title
preroute NAMe
@application vertical_pin
@application vertical_pcb
@text
Route by name only: If the net identifier of an unrouted net
matches either the net name or identifier of a routed net then
the router will try and use this net. All pins must be in the
right direction and of the right type for a route to succeed.
@break
Once an unrouted net has been routed, the name of a routed net
will be changed to the identifier of the unrouted net. This
again encourages successive re-routings of a design to use the
same nets wherever possible.
@end
*/
int RouteNameHandler (ET_TCLARGS)
{
Log (LOG_GENERAL, "#begin routing\n");
perform_routing(By_Name);
Log (LOG_GENERAL, "#done routing\n");
return (TCL_OK);
}
/*********************** Route By creating Nets ***************************/
/*
@title
preroute CREate
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Route by creating nets only: The user will be asked to join
the pins of the devices in question with wires. This is
intended for use with uncomitted wirewrap boards. Once a board
has been part-wired, or if it is a PCB, then the use of the
jumpering commands permits the generation of new wiring lists.
@break
If nets are created during routing of a PCB there is a
problem. This is why this subcommand is not performed by default
with the route command.
@end
*/
int RouteCreateHandler (ET_TCLARGS)
{
Log (LOG_GENERAL, "#begin routing\n");
perform_routing(By_Creating);
Log (LOG_GENERAL, "#done routing\n");
return (TCL_OK);
}
CommandMenu PrerouteMenu = {
{"path", 2, RoutePathHandler,NULL,
"Route by path only",
"",NULL},
{"fixed", 2, RouteFixedNetHandler,NULL,
"Route by fixed nets only",
"",NULL},
{"exact", 2, RouteExactPathHandler,NULL,
"Route by exact same path only",
"",NULL},
{"name", 3, RouteNameHandler,NULL,
"Route by name only",
"",NULL},
{"create", 3, RouteCreateHandler,NULL,
"Route by creating nets only",
"",NULL},
{ NULL,0,NULL,NULL,NULL},
};
/*********************** Simple command calls ***************************/
/*
@title
route
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Route the wiring.
Any nets with their routing status set as NOT_ROUTABLE will
not be considered for routing. Use to protect VDD, GND from
being used for general signal routing.
@break
An experiment in version 16.5 onwards allows for NOT_ROUTABLE_H
and NOT_ROUTABLE_L tracks that can be used as pullup and
pulldown, as they represent logic '1' and logic '0' values.
@break
The list of metal tracks on the PCB, the wired nets is
reconciled with the list of desired connections, the unrouted
nets and the assignment of the unrouted nets to the wired nets
produces the routed nets list.
@break
As there are several phases to the routing, and the order in
which they are applied is fixed, it has been found necessary
to occasionally use the preroute command to order the use of
the routing algorithms.
@break
The order of use of routing algorithms implied by using route
is as follows:
@listing
preroute name, preroute fixed , preroute exact, preroute path
@text
This is then automatically followed by the
@listing
reserve
@text
command, which ensures pin reservation for Maxplus2. If you need to use 'preroute' then
you will need to use the 'reserve' command, to ensure pin reservation.
@break
The 'preroute create' option is now only available via preroute. Nobody
needs a PCB to silently grow extra tracks. If the goal is to
create a new PCB or wirewrap list then this option will be
necessary.
@break
To achieve the same effect as the older 'route' command, use
'route' then 'preroute create'.
@break
Just prior to issuing any route commands, any new pins added
to the design will be checked for pin renaming and the
unrouted netlist is updated.
@end
*/
int ROUTEHandler (ET_TCLARGS)
{
Log (LOG_GENERAL, "#begin routing\n");
perform_routing(Free);
Log (LOG_GENERAL, "#done routing\n");
return (TCL_OK);
}
/**************************************************************************/
/*
@title
reserve
@application vertical_pin
@text
Perform pin reservation according to Maxplus2 requirements.
@break
This function ensures net reservation is made for all internal
nodes that are on internal sockets .
@break
If any external socket is on the net then all internal pins are reserved.
Otherwise a single internal pin is left as a non-reserved driver
@end
*/
int ReservePinsHandler (ET_TCLARGS)
{
Log (LOG_GENERAL, "#begin pin reservation\n");
ensure_reservation();
Log (LOG_GENERAL, "#done pin reservation\n");
return (TCL_OK);
}
/*********************** Simple command calls ***************************/
/* partitioning */
/*
@title
partition
@application vertical_hdl
@text
Do the partition calculation. This takes the entities given in
the partition and works out the port list for the top level.
@break
To do this the partitioner must be made aware of the entire set
of top level entity port lists in the system.
@break
To do this an acfp, vhdl or verilog file must be read in
containing a description of the top level entity for each
block used in the partition.
@break
See the section on Vertical script files.
@end
*/
int PARTHandler( ET_TCLARGS)
{
Log (LOG_GENERAL, "#begin partition\n");
create_unrouted_list();
clear_partition_generics(&partition_generics);
perform_partition();
Log (LOG_GENERAL, "#done partition\n");
return (TCL_OK);
}
/*********************** Simple command calls ***************************/
/* trial */
/*
@title
fix_pins
@application vertical_pin
@application vertical_pcb
@text
This command is used in conjunction with set external on a socket. If a socket is set external and it has unrouted nets connected to it, the fix_pins command
will attempt to freeze the connections given in the unrouted netlist. This means that a socket with a defined pinout should be routed with that pinout rather than
having the pinout exchanged by VERTICAL.
@break
NB If an attempt is made to connect a signal to a net which cannot reach its destination because
there is no wire present, then the signal will be moved to another pin which reaches the destination.
@end
*/
int FIXHandler (ET_TCLARGS)
{
Log (LOG_GENERAL, "#begin attempting to fix port pins\n");
perform_trial_naming();
Log (LOG_GENERAL, "#done fixing pins\n");
return (TCL_OK);
}
/*********************** Simple command calls ***************************/
/* Auto-jumpering
@title
jumper <suffix>
@application vertical_pin
@application vertical_pcb
@text
This is the original routing algorithm for VERTICAL.
This can be used to create wirewrap jumper lists.
If there are unrouted connections made between sockets that are flagged as external, and which therefore
need wirewrapped connections.
@break
In use different pairs or groups of sockets would be set as external and then the jumper command is issued for that pair or group.
The suffix would be used to identify the jumpers created from each induvidual jumper command: These can then be extracted for wirewrap lists.
@end
*/
int JUMPERHandler (ET_TCLARGS)
{
char * Suffix;
if (argc<1 )
Suffix = NULL;
else
Suffix = argv[0];
Log (LOG_GENERAL, "#begin jumpering\n");
create_unrouted_list();
perform_jumpering(Suffix);
Log (LOG_GENERAL, "#done jumpering\n");
return (TCL_OK);
}
/******************** Parser for the 'DO' batch files ***********************/
/*
@title
do <commandfile> [ <arg1> <arg2> ... ]
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Interpret the command file as though typed in on the command line.
@break
The argument list are accessible as $1, $2 etc while interpreting the command file, and can be used to pass down
arguments to the file.
@break
Up to 10 levels of nesting of command files is allowed. This limit is imposed to trap recursion.
@end
*/
int DOHandler (ET_TCLARGS)
{
FILE *DoFile;
if (argc<1)
return(TCL_ERROR);
DoFile = trap_fopen(argv[0], "r"); /* open text file for reading */
if (!DoFile) {
Log (LOG_ERROR, "# Error opening file: <%s>\n", argv[0]);
return(TCL_ERROR);
}
else {
ParseFile (DoFile,argc-1,argv+1);
InitialiseData(); /* March 8 2000 :
* added to make sure any environment
* variables which are directly used as
* C structures are set. */
return (TCL_OK);
}
}
/******************** Calling the count nets with few nodes ***********************/
/*
@title
count_nets [ <threshold> ]
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Report on nets with a node count less than or equal to threshold. Used to find
hanging unrouted nets where there is an error in the netname.
@break
If no threshold is given , the threshold defaults to 1
@end
*/
int COUNTNETSHandler (ET_TCLARGS) {
long limit;
if (argc<1)
limit = 1;
else
count_nets_with_few_nodes((int) limit);
return (TCL_OK);
}
/*********************** Ensure Templates Command ***************************/
/* this ensures all templated sockets have all correct pin properties */
/*
@title
Socket Templating Background Information
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
When the maxplus2 software runs and it fits a design to an
EPLD, it only lists out the pins that it has in fact used.
All unused pins on a chip will remain unknown to VERTICAL. The
use of templates is meant to overcome this. If a template is
read in for a particular device type , the VERTICAL tool can
ensure that every instance of that device in the design will
have all of its pins available. An aliasing mechanism exists
for allowing a group of device types (e.g. speed variants) to
all share the same template.
@break
In addition in Vertical-HDL, the socket templates are used as being logically equivalent to a VHDL component declaration.
The elaborate command ensures that the socket templates( declarations of ports and generics) are applied to the component instances.
@break
There are two template commands. When these are issued, all
sockets are checked to see if there is a template for them.
For any socket with a template, if the socket lacks a pin
identifier defined in the template, it is given an unassigned
pin with that identifier and appropriate pin type.
All definition of socket templating is achieved by the use of
ACFP files. A socket type template has the same general syntax
as the CHIP template. Pins are listed out with no name but
with an identifier (pin number) and a direction. There is also
the possiblility of aliasing chip types - e.g. all speed
variants of the FLEX10k50GC403 have the same pinout. Only one
template need be defined, the others can all be derived simply
from it by using template aliasing in the acfp file.
So you would find e.g.
@listing
TEMPLATE FLEX10K50GC403;
BEGIN
"" : INPUT_PIN = AL1 ;
. "" : CONFIG_PIN = AL2;
... more stuff ....
END;
@text
Then, assuming you have
@listing
TEMPLATE EPM10K50GC403-3;
BEGIN
ALIAS FLEX10K50GC403;
END;
@text
Then if a chip of type EPM10K50GC403-3 is seen then the pinout
template that will be used will be the FLEX10K50GC403 version.
@end
@title
Templating Equivalent Pins: Series resistor handling
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
In order to deal with problems associated with series
termination resistors in signal lines on high performance
FPGAs, where the resistors are seen as disconnections of nets,
the concept of equivalent pins has been developed.
@break
If a device has equivalent pins then any signal seen on one
equivalent pin can be regarded as also appearing on any other
of the equivalent pins. As of Sep 2000 the pin directions of
the device are ignored. If a device has equivalent pins then
these can be automatically connected via 'virtual jumpers'
allowing VERTICAL to then use the completed nets as signal
paths between FPGAs
@break
An example of a template file for a dual in line
series terminator resistor pack
@listing
template rp8dil
begin
"" : bidir_pin = 1;
"" : bidir_pin = 2;
"" : bidir_pin = 3;
"" : bidir_pin = 4;
"" : bidir_pin = 5;
"" : bidir_pin = 6;
"" : bidir_pin = 7;
"" : bidir_pin = 8;
equivalent (1;8);
equivalent (2;7);
equivalent (3;6);
equivalent (4;5);
end;
@text
The information in this file consists firstly of a list of pin
identifiers, followed by a list of which pins can be regarded
as equivalent.
@break
More than 2 pins may be included in the set of pins in an
equivalent group.
@break
If this template file has been read in then for all devices of
type 'rp8dil' the sequence of
'template' followed by 'equivalent' will produce jumpers
across pins 1 and 8 , 2 and 7 , 3 and 6 , also 4 and 5. Then
when routing is performed, Vertical will be able to see wired
connections across the resistor packs and complete the
routing.
@break
Note that this mechanism can be applied to single resistors, or 8 pin devices with different
resistor arrangements (e.g. SIL rather than DIL).
@break
For example a two pin resistor:
@listing
template res0805
begin
"" : bidir_pin = 1;
"" : bidir_pin = 2;
equivalent (1;2);
end;
@end
@title
template <socket_id_template>
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Apply the templating process to all sockets whose identifiers match the given template e.g. 'U1*' which have a valid template
defining pin directions and unrouable pins for example.
@text
DO NOT define any pins that the device ought to posess according to the template but which are not used in the
netlist.
@end
*/
int EnsureTemplateHandler(ET_TCLARGS)
{
char * Word = NULL;
if(argc>0)
Word = argv[0];
template_ensure(Word,TEMPLATE_NO_OP);
return(TCL_OK);
}
/*********************** Create Template Command ***************************/
/* this ensures all sockets have all pins available even if not connected to nets*/
/*
@title
create_template <socket_id_template>
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Apply the templating process to all sockets whose identifiers match the given template e.g. 'U1*' which have a valid template
defining pin directions and unrouable pins for example.
@text
DEFINE any pins that the device ought to posess according to the template but which are not used in the
netlist.
@end
*/
int EnsureCreateTemplateHandler(ET_TCLARGS)
{
char * Word = NULL;
if (argc > 0 )
Word = argv[0];
template_ensure(Word,TEMPLATE_CREATE_MISSING_PINS);
return(TCL_OK);
}
/*********************** Match Template Command ***************************/
/* this ensures all sockets have all pins available even if not connected to nets*/
/*
@title
match_template <socket_id_template>
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Apply the templating process to all sockets whose identifiers match the given template e.g. 'U1*' which have a valid template
defining pin directions and unrouable pins for example.
@text
DEFINE any pins that the device ought to posess according to the template but which are not used in the
netlist.
@break
DISCONNECT any pins that the device socket has , but which are not in the template. This is for use with FPGAs which
have fewer pins connected than there are pins in the socket (eg APEX 20k600 in a 20k1000 position)
@break
Any nets that are disconnected are also set as not routable so that they are not listed
in Verilog output.
@end
*/
int EnsureMatchTemplateHandler(ET_TCLARGS)
{
char * Word = NULL;
if (argc > 0 )
Word = argv[0];
template_ensure(Word,TEMPLATE_CREATE_MISSING_PINS | TEMPLATE_DISCONNECT_PINS);
return(TCL_OK);
}
/* ********************* extract template command **********************************/
/*
@title
extract_template
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
This command scans the netlist for all chips or components of the same type and produces
a single description of the component in a template which is then used in write vhdl or
write verilog commands. It is also usable in other cases where chip templates are needed,
they can be extracted from the PCB netlist instead of needing additional work to create them.
@break
Pins will only be created on the template if
They are connected to a net.
@end
*/
int ExtractTemplateHandler(ET_TCLARGS) {
/* templates are used to make VHDL component instances
match up to the declared components */
extract_templates();
return(TCL_OK);
}
/*********************** modify_names Command ***************************/
/*
@title
modify_names <socket_id> [ <alternate_prefix> ]
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
This affects the name of nets, not the pins of the device to which they are connected.
@break
Routable nets attached to pins on sockets are renamed to be by default socketID_pinID
in order to make them more traceable.
If an alternate prefix is given then it is used instead (not advisable if the socket name
regular expression will match more than one socket).
@end
*/
int Modify_NamesHandler(ET_TCLARGS)
{
if (argc)
{
alter_net_to_socket_name(argv[0],argc>1?argv[1]:NULL);
}
else
{
Log(LOG_ERROR,"-- Need at least one socket identifier for this command\n");
return (TCL_ERROR);
}
return(TCL_OK);
}
/*********************** edit_pins type Command ***************************/
/*
@title
edit_pins type <socket_type> <pin_match_pattern> <replacement>
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@application regular_exp
@text
This command is a more sophisticated form of the swap command.
@break
Searching finds all sockets of a given TYPE.
@break
All sockets are searched for in both component template and netlist space.
If a socket type is matched then the pin identifiers are edited using regular expressions.
e.g.
@listing
edit_pins type SK ([a-z]+)([0-9]+) &2&1
@text
Will reverse (on sockets of type 'SK) all pin identifiers identified by letters followed by digits, swapping the
letter and digit parts of the string.
@break
See edit_pins ident for more information on the regular expressions and pattern replacement of these commands.
@break
This supercedes the swap command which is kept for compatibility.
@end
*/
int Edit_PinNames_By_ChipType_Handler(ET_TCLARGS)
{
if (argc>=3)
{
edit_socket_pin_name(argv[0],argv[1],argv[2],Type);
}
else
{
Log(LOG_ERROR,"-- Need socket type, a search and replace pattern for this command\n");
return (TCL_ERROR);
}
return(TCL_OK);
}
/*********************** edit_pins ident Command ***************************/
/*
@title
edit_pins ident <socket_ident> <pin_match_pattern> <replacement>
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@application regular_exp
@text
@text
This command is a more sophisticated form of the swap command.
@break
Searching finds all sockets with matching IDENTIFIERS.
@break
If a socket identifier is matched then the pin identifiers are edited using regular expressions.
e.g.
@listing
edit_pins ident U[0-9] ([a-z]+)([0-9]+) &2&1
@text
Will reverse all pins identifiers on chip U0 .. U9 where the pins are identified by letters followed by digits,
swapping the
letter and digit parts of the string.
@break
The pattern &0 is a special pattern which means the whole of the string.
@listing
edit type ep20k1000efc672 .* pin_&0
@text
Will prefix all pin identifiers with "pin_" on all sockets of type ep20k1000efc672
@break
This command will also work with HDL port names...
@listing
The special patterns that can be used in the replace string are:
&0 : the whole of the matched pattern
&1..&9 : The n'th bracketed regular expression
&a : The alphabetic = column identifier part of an alphanumeric pin ident
&n : The numeric = row identifier part of an alphanumeric pin ident
&c : The identifier of the connected net
&d : The chip identifier
&i : The numerical pin index = row + column * total_rows
@text
The &a,&n and &i patterns are extracted from the _current_ pin identifiers of the chip.
If you have already edited the pin identifiers then the pin identification is extracted from the
new pin identifier pattern. There may be some problems created if the command is
repeated on the the same chip.
@break
All of the alphabetic part of the pin identifiers are converted to numbers representing device
pin columns. Dont use this command with pin identifiers with a lot of letters like BOOT12, as the conversion of letters
to numbers can cause arithmetic overflows and strange results.
@break
Currently the illegal characters in pin identifiers are PIN_MAP_ILLEGAL_CHARS. If these appear they are mapped onto the
next character in the alphabet.
@break
It is possible to define the rows and columns of a chip where the pin identifiers are numeric
@listing
set generic attribute SK2 min_pin_row 1
set generic attribute SK2 max_pin_row 50
set generic attribute SK2 min_pin_col 0
set generic attribute SK2 max_pin_col 3
@text
This is describing a 200 pin package with 4 columns of 50 rows. Rows number from 1 to N, columns from 0 to M-1.
@end
*/
int Edit_PinNames_By_ChipIdent_Handler(ET_TCLARGS)
{
if (argc>=3)
{
edit_socket_pin_name(argv[0],argv[1],argv[2],Ident);
}
else
{
Log(LOG_ERROR,"-- Need socket ident, a search and replace pattern for this command\n");
return (TCL_ERROR);
}
return(TCL_OK);
}
CommandMenu EditPinNamesMenu =
{
{"ident", 3, Edit_PinNames_By_ChipIdent_Handler,NULL, "Edit pin names selecting chips by ID","<chip_name_template> <search_expr> <replace_expr>",NULL},
{"type", 3, Edit_PinNames_By_ChipType_Handler,NULL, "Edit pin names selecting chips by Type","<chip_name_template> <search_expr> <replace_expr>",NULL},
{NULL, 0, NULL,NULL,NULL,NULL},
};
/*********************** edit_nets ident Command ***************************/
/*
@title
edit_nets name <net_match_pattern> <replacement>
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@application regular_exp
@text
This commmand matches all nets by name and then renames them according to the replacement pattern.
@listing
The special patterns that can be used in the replace string are:
&0 : the whole of the matched pattern
&1..&9 : The n'th bracketed regular expression
&n : The net name in its entirety
&i : The net identifier
@break
I am sure that this command is extremely dangerous but anyway it is provided.
@end
*/
int Edit_NetNames_Handler(ET_TCLARGS)
{
if (argc>=2)
{
edit_net_names(argv[0],argv[1],Name);
}
else
{
Log(LOG_ERROR,"-- Need a search and replace pattern for this command\n");
return (TCL_ERROR);
}
return(TCL_OK);
}
/*********************** edit_nets ident Command ***************************/
/*
@title
edit_nets ident <net_match_pattern> <replacement>
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@application regular_exp
@text
This commmand matches all nets by identifier and then replaces identifier according to the replacement pattern.
@listing
The special patterns that can be used in the replace string are:
&0 : the whole of the matched pattern
&1..&9 : The n'th bracketed regular expression
&n : The net name in its entirety
&i : The net identifier
@break
I am sure that this command is extremely dangerous but anyway it is provided.
@end
*/
int Edit_NetIdents_Handler(ET_TCLARGS)
{
if (argc>=2)
{
edit_net_names(argv[0],argv[1],Ident);
}
else
{
Log(LOG_ERROR,"-- Need a search and replace pattern for this command\n");
return (TCL_ERROR);
}
return(TCL_OK);
}
/*********************** Top level menu driver ******************************/
CommandMenu EditNetNamesMenu =
{
{"name", 3, Edit_NetNames_Handler,NULL, "Edit net names ","<search_expr> <replace_expr>",NULL},
{"ident", 3, Edit_NetIdents_Handler,NULL, "Edit net idents ","<search_expr> <replace_expr>",NULL},
{NULL, 0, NULL,NULL,NULL,NULL},
};
/*********************** Bundle Command ***************************/
/*
@title
bundle <socket_id> [ <socket_id> * ]
@application vertical_hdl
@text
The bundle command is used with Certify in order to reduce the port count of a
PCB. It converts all of the signals connected to a single multipin socket into
a single bus where each pin of the bus is defined according to the connector pin identifier.
@break
The initial assumption is that each socket will have pins labelled either 'a1' or '1a' or simply numbers or letters.
@break
In each case the letter codes are regarded as the columns of the connector and
the numbers as the rows of the connector.
@break
The highest and lowest numbered rows are identified and once the number of rows is
known the array index of the bundle is defined by :
@listing
BundleIndex = RowNum-LowestRow + (ColNum-LowestCol)*TotalRows;
@text
This should always be consistent for any multipole connector.
@break
A port on the top level of the design will appear, the net identifier is the same as the
connector identifier. If Verilog printout is used then the ports will be assigned automatically to the correct signals.
@break
This command is fully implemented for working with
"write vlog", Verilog output. It is not
yet implemented for "write VHDL", VHDL output.
@end
*/
int BundleHandler(ET_TCLARGS)
{
int i = 0;
char * Word = NULL;
while(i<argc)
{
Word = argv[i++];
wildcard_bundle(Word,1);
}
return(TCL_OK);
}
/*********************** UnBundle Command ***************************/
/*
@title
unbundle <socket_id> [ <socket_id> * ]
@application vertical_hdl
@text
The unbundle command is used to undo the effect of the bundle command.
@end
*/
int UnBundleHandler(ET_TCLARGS)
{
int i = 0;
char * Word = NULL;
while(i<argc)
{
Word = argv[i++];
wildcard_bundle(Word,0);
}
return(TCL_OK);
}
/*********************** Jumper Equivalent Pins Command ***************************/
/* Connect together pin groups that are equivalent */
/*
@title
equivalent
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
@text
The netlist is searched for all sockets which have had a template applied to them, which includes defined
equivalent pins, or the socket has an equivalent pins section defined in the ACF source file.
@break
For these sockets,
a netlist jumper is created to create a logical short circuit between the sets of defined equivalent pins
@break
This is used in order to create logical shorts across series termination resistors. For example from a well known FPGA672 card:
@listing
-- an ACFP template file
template resistor
begin
"" : bidir_pin = 1;
"" : bidir_pin = 2;
equivalent (1;2);
end;
template "RES INNER 16R"
begin
alias resistor;
end;
template "RES INNER 51R"
begin
alias resistor;
end;
@text
Which is read in and then the template command is applied for all resistors in the design.
Only those of type 'resistor', "RES INNER 16R" and "RES INNER 51R" would have their pins
connected together in this case.
@break
It can also be used to make e.g. bus buffers invisible for the purpose of routing signals from interface pins via a bus buffer:
something like
@listing
template bus245buf
begin
"" : bidir pin = 2;
"" : bidir pin = 3;
....
"" : bidir_pin = 18;
"" : bidir_pin = 17;
equivalent (2;18);
equivalent (3;17);
...
end;
template "74HCT245"
begin
alias bus245buf;
end;
-- Schematic netlist component library naming error
-- mapped by alias template
template "bizarre245"
begin
alias bus245buf;
end;
@text
Which will short out any type of 245 buffer for the purpose of signal routing. It is expected to introduce the concept
of directional jumpers to more correctly map the behaviour of a bus buffer. At the moment Vertical will not take any notice of
unidirectional buffers !
@end
*/
int JumperEquivPairsHandler(ET_TCLARGS) {
jumper_equivalent_pins();
return(TCL_OK);
}
/*********************** Elaborate Command ***************************/
/* Connect together pin groups that are equivalent */
/*
@title
elaborate
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@break
This performs exactly the same task as for VHDL. All component instances which use a declared
component are elaborated into unique instances of that component.
@break
Generic values are then evaluated for such things as bus widths on ports which have
variable widths defined by constants and expressions of those constants.
@break
Finally, all of the unrouted nets created by the implied connections of VHDL component
instances (port name matching and renaming via port=>fred types of mapping)
are converted into wires by creating wiring automatically.
@end
*/
int ElaborateHandler(ET_TCLARGS) {
/* templates are used to make VHDL component instances
match up to the declared components */
template_ensure(NULL,Search);
elaborate_all();
create_vhdl_connections();
perform_routing(By_Creating);
return(TCL_OK);
}
/******************** Swapping pin ids on sockets. ***************************/
/* first arg. chip ID template, second is max number of chars before letter ***********/
/*
@title
swap <identifier> [ <style> ]
@application vertical_pin
@application vertical_pcb
@text
This is replaced by the edit_pin commands, which can do much more than this.
@break
All pin identifiers on the device identified (or identified by the "name*") type of syntax will be
converted to the defined style.
@break
Valid styles are "1a" or "a1" indicating either leading or trailing numeric parts to the
pin identifier.
@break
SO the following would happen:
@listing
Style | A1 | A1 | 1A | 1A
-------------------------------------
Original ident | X32 | 4b | X32 | 4b
Swapped ident | X32 | b4 | 32X | 4B
@text
The default style is "A1".
@end
*/
int SwapIdHandler (ET_TCLARGS) {
char *Template=NULL;
int limit;
AlphaSwap_t swapping;
Log(LOG_GENERAL,"# Freezing pin renames\n");
create_unrouted_list();
limit = 2;
swapping = Want_A1;
if (argc > 0)
Template = argv[0];
if (argc > 1)
{
{
swapping = Want_A1;
}
else {
swapping = Want_1A;
}
}
if (argc > 2)
{
}
pin_id_swap(Template,limit,swapping);
return (TCL_OK);
}
/*********************** SetEnv ***************************/
/* Set acfread environment */
/*
@title
setenv <name> <string>
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
The environment variable is a special class of generic which
is not used in e.g. VHDL listings.
@break
It is rougly equivalent to the shell environment variables
which may also be looked up by Vertical if no variable/generic
of the wanted name exists inside Vertical.
@break
Set the environment variable (looked up by $(name) within netlists)
named to be the string given. e.g.
@listing
setenv fred "A string"
echo $(fred)
@text
Will result in the string
@listing
A string
@text
appearing on standard output and in the log file.
@end
*/
int SetEnvHandler(ET_TCLARGS) {
generic_info_t info;
if (argc < 2)
return TCL_ERROR;
info.name = argv[0];
info.typename = "env_string";
info.g_type = IS_STRING;
info.expr = compile_string(argv[1]);
set_generic_value(&global_generics,&info);
return(TCL_OK);
}
/*********************** ECHO ***************************/
/*
@title
echo [ <string>* ]
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Prints out the strings given to standard output and to the
Vertical log file.
@end
*/
int ECHOHandler(ET_TCLARGS) {
int i;
for(i=0;i<argc;i++) {
Log(LOG_GENERAL,"%s ",argv[i]);
};
Log(LOG_GENERAL,"\n");
return(TCL_OK);
}
/*********************** ECHO quoted ***************************/
/*
@title
echoq [ <string>* ]
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
Prints out the strings given , with "" quotes around them to standard output and to the Vertical log file. used to check
command parser behaviour. It also can show up any variable with space characters in its value (which may be a problem)
@listing
Vertical : setenv earwig "one two "
Vertical : echoe $(earwig)
"one two "
Vertical : echo $(earwig)
one two
@text
In the second echo example it is not clear there is a space inside
the variable.
@end
*/
int ECHOQHandler(ET_TCLARGS) {
int i;
for(i=0;i<argc;i++) {
Log(LOG_GENERAL,"\"%s\" ",argv[i]);
};
Log(LOG_GENERAL,"\n");
return(TCL_OK);
}
/*********************** ECHO to error log ***************************/
/*
@title
echoe [ <string>* ]
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
This is echoe where the e stands for ERROR. Allows tagging of the error report file
with the progress of scripts. It also prints to the standard Vertical log file.
@break
Prints out the strings given to standard output and to the Vertical ERROR log file
@end
*/
int ECHOEHandler(ET_TCLARGS) {
int i;
for(i=0;i<argc;i++) {
Log(LOG_ERROR,"%s ",argv[i]);
};
Log(LOG_ERROR,"\n");
for(i=0;i<argc;i++) {
Log(LOG_GENERAL,"%s ",argv[i]);
};
Log(LOG_GENERAL,"\n");
return(TCL_OK);
}
/**************************************************/
/* Disconnect node handler
@title
disconnect <chip>'('<pin_ident>')' ( <chip>'('<pin_ident>')' ) *
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
The pin will be disconnected from the routed net list. This is is used to delete pins
on chips which are broken. For more than a few pins on the chip it is better to use
the template command to disconnect unused pins en masse.
@break
This command has been promised for about 5 years but was implemented only in 2001.
@end
*/
int DisconnectNodeHandler(ET_TCLARGS)
{
int i;
char * s, * t , * u;
socket_t * socket;
node_t * node;
if (argc < 2)
return(TCL_ERROR);
for (i=0;i<argc;i++)
{
s=strdup(argv[i]);
/* look for (x) and point at it and the closing bracket */
if(t)
{
if(u)
{
*t++ = 0; /* terminate first half of string, point at second string */
*u = 0; /* terminate second string */
socket = find_socket(Ident,s,Search,&socket_head);
if(socket)
{
node = find_node(socket,Ident,t,Search);
if(node)
{
disconnect_node(socket,node);
}
else
{
Log(LOG_GENERAL,"-- No pin '%s' on socket '%s'\n",t,s);
}
}
else
{
Log(LOG_GENERAL,"-- No socket '%s'\n",s);
}
}
}
if(!t || !u)
{
Log(LOG_GENERAL,"-- Use chip(pin) instead of '%s'\n",argv[i]);
}
free(s
); /* free up allocated string */
}
return(TCL_OK);
}
/**********************************************************/
/*
@title
version
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
List out all of the RCS/CVS $header$ tagged modules present
in Vertical and the netlist readers. This allows for identification
of the exact versions of code used within a particular build of
Vertical.
@end
*/
int VersionHandler(ET_TCLARGS) {
list_versions(stdout);
return TCL_OK;
}
/**********************************************************/
/*
@title
require <minimum_version>
@application vertical_pin
@application vertical_hdl
@application vertical_pcb
@text
The lowest release version of Vertical required to run this script is the command argument.
@break
If the Vertical version is older than that required, then an error will appear. Before Version 16.0 the error is because the
require command does not exist. Above this version, the number given is checked
@end
*/
int RequireHandler(ET_TCLARGS) {
if (argc < 1)
{
return(TCL_ERROR);
}
if(strcmp(Vertical_Version
,argv
[0]) >= 0)
{
Log(LOG_GENERAL,"# Vertical version %s is OK, version %s required for this script\n",
Vertical_Version,argv[0]);
return(TCL_OK);
}
else
{
Log(LOG_ERROR,"# ERROR : Vertical version %s is too old , version %s required for this script\n",
Vertical_Version,argv[0]);
return(TCL_ERROR);
}
return TCL_OK;
}
/*********************** Top level menu driver ******************************/
CommandMenu TopMenu =
{
{"bye", 3, BYEHandler,NULL, "Leave program",NULL},
{"quit", 1, BYEHandler,NULL, "Leave program",NULL},
{"bundle", 3, BundleHandler,NULL, "Bundle together nets leaving connector","[<chip_name_template>*]",NULL},
{"modify_names",3, Modify_NamesHandler,NULL, "Rename nets to match chip pin identifiers"," <chip_name_template> <optional_prefix>",NULL},
{"equivalent",3, JumperEquivPairsHandler,NULL,"Connect together equivalent pins on devices by jumpers","",NULL},
{"elaborate", 3, ElaborateHandler,NULL,"VHDL style variable elaboration handler","",NULL},
{"exit", 3, BYEHandler,NULL, "Leave program",NULL},
{"extract_template", 3, ExtractTemplateHandler,NULL,"Extract component declarations from netlist","",NULL},
{"echoe", 5, ECHOEHandler,NULL, "Expand remainder of line and print it as an error",NULL},
{"echoq", 5, ECHOQHandler,NULL, "Expand remainder of line and print strings as quoted",NULL},
{"echo", 4, ECHOHandler,NULL, "Expand remainder of line and print it out",NULL},
{"edit_pins", 6, NULL,EditPinNamesMenu, "Rename pin identifiers on chips ","(more)",NULL},
{"edit_nets", 6, NULL,EditNetNamesMenu, "Rename net identifiers ","(more)",NULL},
{"do", 2, DOHandler,NULL, "Run a batch file","<do_file>",NULL},
{"read", 4, READHandler,NULL,"Read a data file in with <suffix> on net and socket IDs","<acf_file> [<suffix>] [ <args> ]",NULL},
{"list", 4, NULL,ListMenu, "Print information","(more)",NULL},
{"setenv", 4, SetEnvHandler,NULL,"set environment variable","<name> <value>",NULL},
{"set", 3, NULL,SetMenu, "Alter part of the database","(more)",NULL},
{"delete", 3, NULL,DeleteMenu, "Remove part of the database","(more)",NULL},
{"disconnect",3, DisconnectNodeHandler,NULL, "Remove a pin from a chip","chip(pin)",NULL},
{"write", 4, NULL,WriteMenu, "Write out a data file","(more)",NULL},
{"route", 4, ROUTEHandler,NULL,"Route the wiring",NULL},
{"preroute", 4, NULL,PrerouteMenu,"Partially route the wiring","(more)",NULL},
{"fix_nets", 3, FIXHandler,NULL, "Fix unrouted connections to External ports",NULL},
{"count_nets",3, COUNTNETSHandler,NULL, "Count nets with less than <limit> nodes","[<limit>]",NULL},
{"jumper", 4, JUMPERHandler,NULL,"Create new paths with unique jumpers","[<suffix>]",NULL},
{"partition", 3, PARTHandler,NULL,"Do the partition calculation","",NULL},
{"logging", 3, NULL,LoggingMenu,"Setup transcript logging file","(more)",NULL},
{"debug", 3, DEBUGHandler,NULL,"Internal debugging","<debug_flags>",NULL},
{"template", 3, EnsureTemplateHandler,NULL,"Ensure chips have correct pin directions only","[<chip_name_template>*]",NULL},
{"create_template", 3, EnsureCreateTemplateHandler,NULL,"Ensure chips have all possible pins","[<chip_name_template>*]",NULL},
{"match_template", 3, EnsureMatchTemplateHandler,NULL,"Ensure chips have all possible valid pins: disconnect extra pins ","[<chip_name_template>*]",NULL},
{"connection",3, ConnectionHandler,NULL,"Connect two connectors pin for pin","<socket1> <socket2>",NULL},
{"swap", 3, SwapIdHandler,NULL,"reverse chip pin id A23=>23A","<chip_template> <max_letters>",NULL},
{"reserve", 3, ReservePinsHandler,NULL,"reserve pins for Altera FPGA use after routing","",NULL},
{"require", 3, RequireHandler,NULL,"Require a given version (or later) of VERTICAL","<version>",NULL},
{"unbundle", 3, UnBundleHandler,NULL, "Unbundle nets leaving connector","[<chip_name_template>*]",NULL},
{"version", 3, VersionHandler,NULL,"list module versions to standard output","",NULL},
{NULL, 0, NULL,NULL,NULL,NULL},
};
/****************************************************************************/