5. PCB Design Automation with Perl

This chapter will be providing demonstrations of a novel script based schematic capture and board-level design application, called PCBScript, which enables designers to transition seamlessly between specification, pin table, schematic and board layout in an open, ASCII, single-file database. This tool automatizes design process enabling descriptive design entry using synthesis scripts. The functionality is based on a primitives library written in Perl.

PCBScript features:

The tool uses configuration parameters, pin lists of ICs, assignment and layout placement information typed in using a dedicated synthesis script. PCBScript is designed to work with Eagle, a conventional Schematic Entry, Place and Route tool.
PCBScript can create some parametrizable packages e.g. QFP packages, sockets, connectors, jumpers, a number of configurable symbols as well as the functionality to instantiate devices, to connect them with specified signals that allow to create the complete schematic of a board just by writing a script to provide all necessary information. Moreover, PCBScript allows placing the instantiated parts at board-level and routing the connections. The routing feature can be used to route signals or busses semi-automaticly, controlled by PCBScript commands that give coordinates or distances where to route. This can be done for any signal or part on the board. For more complex boards, routing busses in this way at least helps the autorouter of Eagle to route where you want.

5.1.1 Parsing Files

Note: For documentation purpose, most of the following examples are structured in more than one line. But PCBScript at this stage allows inline commands only. As PCBScript is based on the script language Perl, besides dedicated PCBScript commands, that basically instantiate classes, the complete command set of Perl can be used. Experience with Perl is not required but helpful. A basic knowledge of Perl will the user allow to use more advanced features of PCBScript, to enlarge functionality or for debugging.

Design information e.g. the pin out of ICs exist or can easily be written in list or table format. The best way to get a great number of design infos is to read and extract them from files. PCBScript supports file I/O of easy structured formats like lists that contain a seperator to identify each column. A possible format could be:

** CHIP IC1 **
GND	:	6	:	Pwr
addr4	:	7	:	In
addr5	:	8	:	In
VCC	:	9	:	Pwr optional

** CHIP IC2 **
...

To read this data set, a file parser has to be initialized. Example 1 schows the intantiation of a Parser. The Parser is implemented to read files by line.
To allow reading of different formats the Parser have to be configured.
Table 1 describes the parameters.

Example 1:
$parse_pins  = new Parser(	NAME => "pins",    
				NUM => 2, 
				SPLIT => "/ : /", 
				START => "/CHIP 1/", 
				STOP => "/CHIP 2/", 
				OFFSET => 0, 
				OFFSTOP => 1,
				GREP => "!/optional/" );

Table 1: parameters of Parser
Parameter Example Description
NAME "pins" after parsing a message of the number of got "pins" is given
NUM 2 the list has three columns, the Parser returns a double array, the third column is ignored
SPLIT "/ : /" the separator of the list is ' : ' the complete perl syntax can be used here
START "/CHIP 1/" if the string 'CHIP 1' occours in file, Parser begins reading next line
STOP /CHIP 1/ reading is stopped at the end of the file or if 'CHIP 2' occours
OFFSET 0 reading begins 0 number of lines after the start string
OFFSTOP 0 reading stops 0 lines after the stop string
GREP !/optional/ only lines with 'string' are returned, or ignores lines with 'optional' using '!'
TAKE 5 reads the first 5 characters of a line, this can be used if the text format has no separators
5.1.2 Package Definition

A package is generated by instantiating a generic package defined as a PCBScript class. The parameters of a Quad Flat Pad (QFP) package are described in table 2.

Example 2:
$PQFP208 = new PackQFP(	NAME => "PQFP208", 
			VALUE => "ALTERA", 
			NUM => "208", 
			PADL => "1.5", 
			PADB => "0.22", 
			PINL => "1.25", 
			PINB => "0.22", 
			DIST1 => "1.17", 
			DIST2 => "0.27", 
			DIST3 => "0.4", 
			DIST4 => "2", 
			DIST6 => "1.8", 
			RADIUS => "0.7", 
			CASEX => "14", 
			CASEY => "14", 
			FX => "12.75", 
			FY => "12.75", 
			BSC => "0.5", 
			FILE => "QFP_PACKAGE.scr");
klick to open PDF-Format
Fig.2 QFP Packages
Table 2: QFP package parameters
Parameter Example Description
NAME "PQFP208" a string representing the name of the package, if '>NAME' is used, the name can be changed in Eagle
VALUE "ALTERA" additional text describing the package, if '>VALUE' is used, the value can be changed in Eagle
NUM "208" number of pins
PINL "0.22" length of pin
PINB "0.22" width of pin
PADL "1.5" length of SMD pads
PADB "0.25" width of SMD pads
DIST1 "1.17" length of edge indicating pin 1
DIST2 "0.27" length of edge
DIST3 "0.4" distance between inner and outer border
DIST4 "2" length of coordinate cross
DIST6 "1.8" distance between circles and case
RADIUS "0.7" radius of screw holes
CASEX "14" length of case
CASEY "14" width of case
FX "12.75" (see Figure 1)
FY "12.75" (see Figure 1)
BSC "0.5" distance between pins
FILE "QFP_PACKAGE.scr" output file name

To create a QFP socket, PCBscript provides the SockQFP class. The parameters are described in table 3.

Example 3:
$SOCQFP208 = new SockQFP(	NAME => "SOCQ208", 
				NUM => "208", 
				PINL => "1.25", 
				PINB => "0.22", 
				PADL => "1.7", 
				PADB => "0.22", 
				DIST1 => "0.8",  
				DIST2 => "0.27", 
				DIST3 => "0.4",  
				DIST4 => "2", 
				DIST6 => "1.8", 
				RADIUS => "0.7", 
				TEXT => "YAMAICHI IC 149", 
				CASEX => "21.8",  
				CASEY => "21.8",  
				CASEPAD => "16.05", 
				FX => "12.75",  
				FY => "12.75", 
				BSC => "0.5", 
				ALIGNPIN => "12.4",  
				SCREW => "15.38", 
				FILE => ">PACKAGE_LIB.scr");
Table 3: QFP socket parameters
Parameter Example Description
CASEPAD "16.05" equals FX of QFP packages (see Figure 1)
ALIGNPIN "12.4" radius of alignment pin holes
SCREW "15.38" radius of scres holes
other parameters   see Table 2 QFP package

A Dual Inline (DIL) package is instantiated using the DILPack class. Table 4 describes the parameters.

Example 4:
$DIL32 = new DILPack();
Table 4: DIL package parameters
Parameter Example Description
parameters   see Table 2 QFP package

Connector packages are provided in the PackCon class. The parameters are the same as described in Table 2 QFP package.

Example 5:
$PackCon6  = new PackCon(	NAME => "CON6", 
				NUM => "6",  
				TEXT => ">NAME", 
				BSC => "2.54", 
				FILE => ">PACKAGE_LIB.scr");
5.1.3 Symbol generation

The same procedure as described in section 1 allows creation of symbols required to visualize connections between Pins or SMDs. Example 6 shows the instantiation of a standard symbol with one row of pins that can be used for most applications.

Example 6:
$TIMERSym = new Sym(	NAME => "TIMER", 
			VALUE => "TIMER", 
			DIST1 => "2.54",  
			DIST2 => "5", 
			DIST3 => "1.5", 
			CASEX => "10", 
			PINDATA => *TIMERPins,  
			BSC => "3");
Table 6: Standard1 symbol parameters
Parameter Example Description
CASEX "10" width of frame
PINDATA *TIMERPins list of pins that can be read in using the Parser function or typed in manually
Note: As this parameter is a list, a pointer ('*') to the list is used as a reference.
DIST1 "2.54" distance between border and case
DIST2 "5" distance between border and text
DIST3 "1.5" distance of net edge
other parameters   see section 1

Example 7 shows the instantiation of a connector symbol that can be used for connector packages, described in section 1. The parameters are the same as described in Table 6.

Example 7:
$Con6Sym  = new ConnectorP(	NAME => "CON6", 
				NUM => "6", 
				TEXT => ">NAME", 
				CASEX => "5.08", 
				DIST1 => "2.54", 
				DIST2 => "1.9", 
				BSC => "3");
5.1.4 Create Devices

A device connects each pin of a symbol with the equivalent pin of a package. Example 8 shows the instantiation of a device with one symbol.

Example 8:
create a Device
$lib = new Device(	NAME => "CON6", 
			SYMBOL => $Con6Sym, 
			PACKAGE => $PackCon6, 
			TYPE => "Always", 
			PREF => "CON", 
			FILE => "DEVICES.scr");
Table 8: Device creation
Parameter Example Description
NAME "CON6" name of the device
SYMBOL $Con6Sym reference to a symbol created bevore
PACKAGE $PackCon6 reference to a package created bevore
PREF "CON" prefix of the device, serves to number multiple instantiations of this device in schematics
FILE "DEVICES.scr" the output file for the generated the Eagle script

PCBscript allows to create devices with multiple symbols. For that, each symbol is added to the device using the Add function. Example9 describes the creation of a device with 3 symbols. Note: the print command.

Example 9:
add three instantiated Symbols to Device "FPGA1" and create Eagle output file.
$Device1 = new Device(	NAME => "FPGA1", 
				PACKAGE => $SOCQFP240, 
				PREF => "IC", 
				BSC => "40");
$Device->Add(-50, 55, "Always", $symbol1 );
$Device->Add(0, 55, "Always", $symbol2 );
$Device->Add(50, 55, "Always", $symbol3 );
$Device->Print("SYMBOL.scr");
Table 9: Add function
Parameter Example Description
X -50 x-position of symbol
Y 55 y-position of symbol
TYPE "Always" this symbol is always visible after instanting the device in schematics, see Eagle reference manual for more options
SYMBOL $symbol1 reference to a symbol
5.1.5 Create Schematics

After executing the procedures to create devices as described in section 1, the outputfiles, that are Eagle scripts, have to executed in Eagle to create a Library and saved.
The devices (Symbol + Package) can then be added in schematics. In PCBscript a Schematic class has to be instantiated that provides the functionality to emulate all actions a designer would perform manually in Eagle. The transfer between PCBscript and Eagle is done using Eagle scripts. In contrast to the Package and Symbol classes, which draw pins and lines as described in section 1, the Schematic class uses Eagle commands to add and place Devices and connect them with signals and busses corresponding to the script based design entry. Each Symbol class as a dedicated algoritm for drawing the connections.
After instantiating the Schematics, any Device can be added and placed anywhere on a sheet or on different sheets. Tables 10 and 11 describe the implemented parameters for adding Devices in PCBscript. The parameter LIB can be any device, created by PCBscript as well as, edited manually in Eagle or a Device from any Eagle library. To move symbols and connect them with each other, PCBscript needs the coordinates of the symbols and each pin. One way is to edit the connections manually but this is not the intention of PCBscript. The easiest way when using "external" Devices is configuring one of the provided PCBscript classes using exactly the parameters (NUM, BSC, CASEX, ...) of the "external" device. More advanced users of PCBscript may create its own Symbols and Packages derived from existing classes, using object oriented methods as described in section 3. This guaranties matching coordinates between Symbols and nets.

Example 10:
add Device "TIMER" from Library "BARRACUDA.lbr" to Schematics on coordinates (30, 300) on sheet 8 using the pin information from the instantiated Device $TIMERDevice.
$Barracuda = new Schematic(	NAME => "Barracuda", 
				TEXT => "Barracuda PreSilicon Prototype Board", 
				LIB => "BARRACUDA.lbr", 
				DIST1 => "15", 
				DIST2 => "-2", 
				BSC => "40");
$Barracuda->Add(8, 30, 300, "TIMER", $TIMERDevice );
Table 10: Schematics
Parameter Example Description
NAME "Barracuda" this could be the name of the project
LIB "BARRACUDA.lbr" the used Eagle library
DIST1 "15" length of nets (signals)
DIST2 "-2" length 2 of nets (signals)
BSC "40" distance between grouped symbols
Table 11: Add function
Parameter Example Description
SHEET 3 sheet number where the device is placed
X -50 x-position of device
Y 55 y-position of device
BUS 300 y-position of master bus that connects busses of each symbol
LIB "TIMER" name of device in Eagle library
DEVICE $TIMERDevice reference to a device

Devices with more than on symbol have to instantiated on sheet 1. Each Symbol can be placed to any position on any sheet using the Move function, but at least one Symbol must stay at sheet 1.
Placing Symbols can be simplified using the Group function, that allows multiple Symbols to be moved simultaneously and grouped together as shown in example 12.

Example 11:
move Symbol "PWR240" of Device "FPGA2" to sheet 4 at point (40, 40) 
and move Symbols "FPGA1S" and "FPGA2S" to (35, 160) and (85, 160) on sheet 2. $Barracuda->Move(4, 40, 40, "FPGA2.PWR240" ); $Barracuda->Group(2, 35, 160, 50, "FPGA1.FPGA1S", "FPGA2.FPGA2S" );
Table 12: Group function
Parameter Example Description
SHEET 3 sheet number where the symbol is placed
X 35 x-position of symbol
Y 160 y-position of symbol
BSC 50 distance between grouped symbols
SYMBOL "FPGA2.PWR240", "FPGA3.PWR240" list of Symbols (Device.Symbol delimited by point '.')

As described above, design entry, the circuitry, the connections between the pins, can be done using the file parser functionality to get lists of signals or typing the lists manually before instantiating the Symbols. This Symbols are dedicated, that means all signals are saved in the internal datastructure of the symbol.
To reuse standard symbols more than on time in Schematics, the Assign feature has been implemented.
This allows to connect single pins as well as bussed between devices with named signals. Table 13 shows the syntax.

Example 12:
assign Pin "MSEL0" of Symbol "FPGA1S" of Device "FPGA1" to "GND" and assign Pin "MSEL0" of Symbol "FPGA2S" of Device "FPGA2" to "GND"
Assign("GND", "FPGA1.FPGA1S.MSEL0", "FPGA2.FPGA2S.MSEL0");
Table 13: Assign feature
Parameter Example Description
SIGNAL "GND" signal that is assigned to each pin of the pin list
PIN "FPGA1.FPGA1S.MSEL0", "FPGA2.FPGA2S.MSEL0" list of pins (Device.Symbol.Pin delimited by point '.')

Busses can be assigned similarly as shown in example 13.

Example 13:
connect Pins "IO_7..IO_14" of Symbol "FPGA1A" of Device "FPGA1" with
Pins "IO_7..IO_14" of Symbol "FPGA2A" of Device "FPGA2" using the bus data[1..7].
Assign("data[1..7]", "FPGA1.FPGA1A.IO_[7..14]", "FPGA2.FPGA2A.IO_[1..8]");

PCBscript supports concatenation. Different bit signals or busses can be grouped and assigned as shown in example 14.

Example 14:
assign Pins "IO_7..IO_14" of Symbol "MCU" of Device "CON3" with
signals "MCU_15..MCU_18" using the signals "bdmact,freeze,bus_clk,wait_mod". The same works for busses.
Assign("bdmact,freeze,bus_clk,wait_mod", "CON3.MCU.MCU_[15..18]");
Assign("addbus[0..15],writdb[0..15],readdb[0..15]", "CON3.MCU.MCU_[1..48]");

Even more complicated constructs are supported to do whatever you want, as shown in example 15.

Example 15:
connect reverse Pins "ffxx15..ffxx0" and "GND","VCC","data0..data7 to the pins of Connector "CON3", Symbol "MCU" pins "MCU_1..MCU_26".
Assign("ffxx[15..0],GND,VCC,data[0..7], "CON3.MCU.MCU_[1..26]");

Assigning all Pins of an IC to VCC or GND is as easy as shown in example 16.

Example 16:
connect IO_1, IO_7, IO_21, IO_31, IO_32 to "VCC".
Assign("VCC", "FPGA2.FPGA2A.IO_[1,7,21,31..32]");
Assign("GND", "FPGA2.FPGA2A.IO_[3...4,11,15,30]");

The Connect function creates the nets for each pin of a Symbol. Additionally, for the Standard1 Symbol, all Symbols (parameters of a function call) are connected with each other by busses as shown in example 17.

Example 17:
create all nets for the Symbols "FPGA1.FPGA1S" and "FPGA2.FPGA2S" and connect themm with a bus labled "data[0..16]".
	
Connect(0, 171, 60,  "data[0..16]", "FPGA1.FPGA1S", "FPGA2.FPGA2S");
Table 14: Connect parameters
Parameter Example Description
X 0 x-coordinate of bus
Y 171 y-coordinate of bus
BSC 60 distance between vertical buslines
NAME "data[0..16]" name of the bus between all symbols
SYMBOL "FPGA1.FPGA1S", "FPGA2.FPGA2S" list of symbols to connect

After, the complete circuitry has been entried and all actions have been performed, an Eagle command file is created using the Print function as shown in Example 18.
To get the complete Schematics of the circuitry, the output script has just to be executed in Eagle. If Schematics are split in different sheets, each script have to be run in Eagle, beginning with sheet 1.

Example 18:
create for each sheet an Eagle script file.
	
Print("SCHEMATIC.scr", 1);
Table 15: Connect parameters
Parameter Example Description
FILE "SCHEMATIC.scr" output file name
SCHEETS 1 optional '1' indicates the output is split into different files each representing a sheet in Eagle, without this parameter, all sheets are arranged on one page
5.1.6 Component Placement

The board layout begins with placing the components. Each component is draged to the desired location on the board by typing the coordinates in form of a
Move command into the script.

Example 19:
move Connector 1 to x = 0.3, y = 2.5 inch
and rotate the connector three times (270 degree)
	
Move(CON1, 0.3, 2.5, 3);

Now the traces are added using the Route command.

Example 20:

route Connector 1 via the coordinates

	x = CON1.x, y = CON1.y
	x = 2.1, y = CON1.y
	x = 2.5, y = CON1.y
	x = 2.5, y = 7
	x = IC2.x, y = IC2.y
Route(CON1, 2.1x, 2.5x, 7y, IC2[1..3]);
5.2 Natur of Program Output

The basic concept of PCBscript is to read configuration information and produce a file output that another PCB design tool (Eagle) can input to create PCB Schematics and Layout. Eagle provides a script-interface that allows control of nearly every funtionality via script commands. PCBScript uses this interface and outputs different scripts that first create Symbols, Packages, second connect them and third create a board layout by placing the parts and routing the connections corresponding to the design entry of the PCBScript design script. To reach this, PCBScript converts design entry into different Eagle script files that are executed in Eagle.
At time of this paper, all functionality, neccessary to create the Barracuda Prototype board, has been implemented. This includes primitives to read any files to extract information as signal names, pin lists as well as IO information or assignment, routing and configuration information.
This version of PCBscript can not interact with Eagle. But Eagle privides a user language that allows writing out the internal data structure of Symbols, Packages.. . This output could be read in again by PCBscripts to create loopes of interaction between both tools to allow design optimization at a higher level. Examples 21 to 23 shows parts of PCBscript output.

Example 21: Eagle script to create Symbols
Edit E100Q24V.sym;
Layer 94;
Pin 'CONF_DONE' In Short R0 Both 0 (-2.54 -3);
Wire  0.254 (0 1.5) (0 -43.5);
Layer 96;
Change Size 2;
Change Ratio 8;
Text E100Q24V R0 (-8 -47);

Edit E100Q24V.dev;
Connect   'E100Q24V.TCK' '1'  'E100Q24V.CONF_DONE' '2'  'E100Q24V.nCEO' '3'  'E100Q24V.TDO' '4' \
	  'E100Q24V.IO/INTDONE' '26'  'E100Q24V.TMS' '58'  'E100Q24V.TRST' '59' \
	  'E100Q24V.nSTATUS' '60'  'E100Q24V.nCONFIG' '121'  'E100Q24V.MSEL1' '123' \
	  'E100Q24V.MSEL0' '124'  'E100Q24V.TDI' '177'  'E100Q24V.nCE' '178' \
	  'E100Q24V.DCLK' '179'  'E100Q24V.DATA0' '180';
Example 22: Eagle script to create Schematics
USE BARRACUDA.lbr;
Add DINA4_L R0 (0 0);
Name DINA4_L (0 0);

WINDOW FIT;
Invoke FPGA3 FPGA3A R0 (40 160);
Net RES3A_1 (40 160) (23 160) (21 162);
Label (32.5 160) (25 160);
Example 23: Eagle script to create Layout
WINDOW 0.8;
Display -19;
Layer 20;
Delete (6.25 2);
Wire  0.01 (0 0) (12 0) (12 7) (0 7) (0 0);
Move FPGA1 (5 5.2);
Rotate (5 5.2);

5.3 Adapting PCBscript to new functionality

Basic to PCBscript are its object oriented features, for detailed information, refer to the pan pages perlref, perlobj, and perlbot.

Creating a new Symbol is as easy as copying an empty standard package as shown in example 24, type the package name package NewSymbol;, type the package name of the Symbol which functionality for printing, connecting signals is to be copied and save all as file 'NewSymbol.pm'.
The functionality of the new Symbol that differs from the old Symbol have to be rewritten. Copy the old subrouting and change it.
Often changed are the sub create and sub print function.

Example 24:
package NewSymbol;

use Hash;
use Primitives;
use Pack;

@ISA = qw( Symbol );

sub new {
	my $type = shift;

	my %params = @_;
	my $self = {};
	my $i;

	@{$self->{SYMBOLS}} = [];

 	for ($i=0; $i <= $#_; $i+=2) {
		@{$self->{$_[$i]}} = $_[$i+1];
	}
	bless $self, $type;

	$#{$self->{SYMBOLS}} = -1;	# initialize to 0 elements

	&create($self);
}

sub create {
        my $self = shift;
	if ( @_ ) {
		@pins = ();
		for ($i=0; $i <= $params{$prop[$i]}; $s++)
		{
			push(@pins, $s);
		}
		@{$self->{PINS}} = @pins;
	}
}

1;  # so the require or use succeeds

5.4 Advantages of the generic method

The concept of PCBScript is to make designing electronics with printed circuit boards easy, fast, inexpensive and fun. Before now, manual design entry has been common that is a time consuming, error-prone process. Table 16 compares manual design entry with script-based design entry using PCBscript.

Table 16: Comparision of PCBscripts against Manual Design Entry
Action Manual Design Entry
using Eagle
Time Time PCBscript+Eagle
creating standard symbols, packages instantiate from library seconds minutes instantiate the class and configure the parameters
adapting, changing symbols, packages copy and modify existing objects from library hours (depending on size) minutes (independent of size) instantiate the class and configure the parameters
creating competely new symbols, packages drawing all from the scratch days (strongly depending on size) hours (independent of size, dependent of complexity) derive an existing class and modify the functionality
entry of connectivity drawing all manually days (strongly depending on size), error-prone hours (independent of size), basically no errors use pin files or assign connections manually using scripts
placing components in layout placing all manually minutes (depending on number of parts) minutes (parts can be grouped), a snap between parts is possible (relative positioning) type coordinates into script or snap parts together
routing connections route each signal manually days (depends strongly on size) hours (depends on complexity) type coordinates into script or snap signals together (relative routing)
change design change symbol in library and change signals manually days (strongly dependent on size) minutes (independent of size) just change some parameters in configuration script or pin file
change routing move connections manually hours (strongly dependent on size) minutes (if parts are snapped together) change some values in configuration script
add new ICs or change Symbols, Packages use library and create Schematics, Layout again days (strongly dependent on size) hours (independent of size) copy and past and adapt some commands in configuration script