An Automated Method for Data Path Construction by A.

advertisement
An Automated Method for Data Path Construction
by
Darren A. Schmidt
Submitted to the Department of Electrical Engineering
and Computer Science in Partial Fulfillment of the Requirements
for the Degrees of Master of Engineering and Bachelor of Science
in Electrical Engineering and Computer Science at the
Massachusetts Institute of Technology
May 1998
Copyright 1998 Darren A. Schmidt. All rights reserved.
The author hereby grants to M.I.T. permission to reproduce and
distribute publicly paper and electronic copies of this thesis
and to grant others the right to do so.
Author
Department of Eectrical Engineering and Computer Science
May 20, 1998
Certified bySChris
:
Terman
Thesis Supervisor
Accepted by
Arthur C. Smith
Chairman, Department Committee on Graduate Theses
An Automated Method for Data Path Construction
by
Darren A. Schmidt
Submitted to the Department of Electrical Engineering
and Computer Science in Partial Fulfillment of the Requirements
for the Degrees of Master of Engineering and Bachelor of Science
in Electrical Engineering and Computer Science
at the Massachusetts Institute of Technology
Abstract
The construction of custom data paths is a time-consuming and difficult problem.
Even with a library of standard cells, custom hand layout can take months. In addition,
minor design changes or revisions for next generation designs can be tedious and
difficult. By creating an automated system, data path design can be greatly simplified
and dramatically sped up. Not only does this aid in the initial design, but it also enhances
the designers ability to make design changes. Now these revisions involve simply
modifying lines of code, rather than the painful process of redoing a custom layout. In
addition, changes to new technology are easily accommodated. Rather than redo the
entire design, only the standard cells and the affected constants in the program need to be
revised. Then, the program can be rerun and a new design can be created. One of the
drawbacks of automation is that it reduces the designer's flexibility in layout. In
addition, many existing tools are complex and difficult to use. The goal of this project is
to create an easy-to-use, automated design tool that results in all of the benefits
previously mentioned, while at the same time giving the user maximum flexibility in
design. This thesis describes the implementation of such a system, as well as the results
of using this tool to create a substantial design.
Thesis Supervisor: Chris Terman
Title: Professor
Acknowledgements
There are many people without whom this thesis would not have been possible and to
them I give my thanks:
To Professor Gerry Sussman and Amorphous Computing, for giving me the
opportunity to work in their group.
To Professor Chris Terman, for not only being a great thesis advisor, but also a
great teacher and friend.
To my family, for providing me with their continued love and support.
To my roommates and friends, for helping me to enjoy my MIT experience.
Contents
1
2
1.1
Background ..................................................................... 7
1.2
Objectives ...................
1.3
Amorphous Computing ........................................... ....... 10
1.4
Thesis Outline ............................................
4
.................... 9
..........
....................
12
13
The Building Blocks: Standard Cells
2.1
System Overview ...........................................
2.2
A Basic Standard Cell .....................
2.3
Standard Cell Layout .....................................
2.4
3
7
Introduction
13
...................... 14
............. 16
16
.................
2.3.1
Facilitating Tiling .......................
2.3.2
Simplifying Routing ......................................... ...... 16
............. 17
Standard Cell Library .....................................
............... 17
2.4.1
Basic Gates .....................................
2.4.2
XOR and XNOR .......................
2.4.3
Registers ......................
2.4 .3
M ultiplexor ..................................................................................
..
................... 18
19
...................................
19
22
The Place and Route Tool
3.1
Program M ethodology ......................................... ........ 22
3.2
Performing Placement .......................
3.3
Performing Wiring .....................................
23
...........................
3.3.1
Routing Signals ....................
3.3.2
Routing Power and Ground .....................
24
................... 25
...... 27
30
Data Path Elements
4.1
4.2
32-Bit A dder Design ................................................................
..... 30
............
31
4.1.1
Binary Full Adder ....................
4.1.2
Ripple-Carry Adder ...................................
4.1.3
Carry-Skip Adder ....................
................. 32
4.1.4
Manchester Adder ....................
................
4.1.5
Binary Lookahead Carry Adder ........................................
36
4.1.6
Final Results ........................................
42
Layout of the 32-Bit Adder ........................
31
33
........... 42
4.3
5
... 43
A dditional B locks ................................................................
45
Taking the Tool for a Test Drive
A 32-B it C ounter .............................................................
5.2
Building the C ounter .............................................................. 46
5.2.1
32-Bit Multiplexor ................................................ 47
5.2.2
32-Bit Register ...........................
........ 47
...............
5.2.3 C ounter Logic .................................................................
5.2.4
5.3
6
45
5.1
Putting It All Together .......................
...
.........
48
48
Possible Im provem ents .............................................................. 52
5.3.1
Improving W iring ............................................................... 52
5.3.2
Enhancing the Routing of Power and Ground ......................... 53
5.3.3
Accepting Additional Input Styles .............................................. 54
55
Conclusion
56
Appendices
.............
A.1
magic.scm .................................
A .2
counter.scm .............................................
References
.. ...................
56
.....................
86
124
List of Figures
.... ................ 14
2-1
Basic Routing Plan .....................................
2-2
Basic Gate Layout ..................................... ....................
2-3
XNOR Schematic and Layout .....................................
2-4
2:1 Multiplexor Schematic and Layout .....................................
19
2-5
Jam Register Schematic and Layout ...........................................
20
4-1
Full Adder Schematic ..................................... ....
4-2
Manchester Carry Adder Schematic ......................................
4-3
Conflict-Free Manchester Carry-Skip Circuitry ........................... 34
4-4
32-Bit Manchester Carry-Skip Adder Schematic ......................... 35
4-5
Binary Look-Ahead Carry Adder Block Diagram ......................... 37
4-6
GP Block Schematic ..................................... .....
4-7
BA and BB Block Schematics ......................................
......
38
4-8
4-Bit BLCA Adder Schematic ......................................
.............
40
4-9
32-Bit BLCA Adder Schematic .....................................
4-10
32-Bit BLCA Adder Layout .......................................
5-1
32-Bit Counter Schematic ...........................................................
5-2
32-Bit Counter Layout .........................................
15
.......
18
............ 31
33
............. 38
.... 41
........ 44
46
........... 51
Chapter 1
Introduction
This thesis describes the implementation and test drive of a standard cell layout
tool for data paths. This chapter begins with a summary of previous work in the area of
automated placement and routing tools and a description of the goals of this project. It
then provides an introduction to the larger project for which this work is being done and
concludes with an outline of this thesis.
1.1 Background
The automated conversion of a VLSI design to layout has been an active area of
research for the last 15 to 20 years. This task entails three main phases, cell design,
placement and routing. A number of algorithms have been developed to solve the last
two of these problems.
There have been two main approaches to the problem of placement, the task of
placing modules adjacent to each other in order to minimize area or cycle time. The Mincut algorithm' performs placement by partitioning. It divides the blocks to be placed at
the top level of the design into two groups of approximately equal area, while minimizing
the number of connections required across this divide. This process is then repeated for
the two halves, splitting the layout into quarters, eighths, and so on, until the leaf cells are
reached. Another widely used technique is one in which the movement of modules is
likened to thermal annealing. 2
Modules are initially moved randomly, and the
"temperature" of the layout is evaluated by applying some measure such as routing area
or timing. As the layout "cools", the routing and/or timing improves. For each proposed
subblock movement, the resulting temperature is calculated.
If it is higher than the
current temperature, the move is not completed. To avoid local minima, the "melt" is
reheated and then recooled according to an "annealing schedule".
The lowest
temperature configuration found so far is saved before each movement, and the algorithm
stops when after a given number of tries a new minimum is not found. Both of these
methods have been widely used, although they require significant runtime.
A variety of routing tools have been developed as well. Routing is the task of
taking a module placement and a list of connections and connecting the modules with
wires. One common type of router is a channel router, which routes rectangular channels.
The greedy channel router3 wires up the channel in a left-to-right, column-by-column
manner.
Within each column the router tries to maximize the utility of the wiring
produced, using simple "greedy" heuristics.
Global routers4 are channel routers that
attempt to minimize the total number of wiring tracks required by examining the entire
design and generating all possible net segments for each net. Then, it chooses from
among all possible net connections in order to minimize the total channel density. There
are also more complicated routers, such as maze routers. These can route just about any
configuration, but have comparatively long running times. They are usually reserved for
very difficult routing problems. These routing methods have also been widely used, and
there are many custom routing tools as well.
There currently exist a number of tools that perform both routing and placement
for standard cell designs. One such tool that is in wide use is TimberWolf. 5 This tool
uses simulated annealing to perform the placement, and then a global router to perform
the routing. This package provides good results and substantial area savings, compared
to other standard cell layout methods.
The above mentioned placement and routing tools provide reasonable solutions to
the general VLSI design problem. However, they fall short in a few areas when it comes
to data path design. The current automated systems minimize the role of the designer. In
addition, they don't group standard cells by function, but rather to optimize area or
timing. Thus, it can be difficult to understand the resulting layout. Finally, they are
complicated to use and often require considerable amounts of run-time.
1.2 Objectives
The goal of this project is to create a tool that provides the best of both worlds.
That is, it should provide the benefits of automation and reduce design time. But, it
should do this while still giving the designer complete control over the layout. It should
also result in a logical grouping of standard cells, so that designs can be easily followed
and debugged. Finally, it should be easy to use and relatively fast. Since the designs of
data paths and their resulting layouts tend to be regular, placement and routing are often
quite straightforward from the designer's point of view. Thus, a designer-directed layout
strategy should perform very well without too much effort on the part of the designer. In
addition, this strategy would result in a logical placement of standard cells that could be
easily followed by the designer. And unlike many of the more complicated algorithms, it
would be relatively easy to use and have a very short run-time.
This thesis attempts to illustrate the usefulness of an automated system of the type
previously described. First, a prototype of such a system will be created.
This will
involve the layout of the standard cells that are necessary for data path construction, as
This method of
well as implementing a method for building with these cells.
construction will be created in the form of a Lisp program. Finally, a sample data path
will be constructed using this prototypical tool.
While by no means the optimal
implementation, this project is instead intended to prove the usefulness of such a tool.
Once the basic tool is built and tested, it can then be refined and the user-interface can be
improved upon at a later date.
1.3 The Amorphous Computing Project
One of the major current activities of the Mathematics and Computation Group of
the Artificial Intelligence Lab is the study of amorphous computing.
Drawing from
natural phenomenon such as a swarm of bees cooperating to construct a hive, this group
is attempting to address the fundamental organization of computer systems.
Two
fundamental questions they have raised are:
1) How do we obtain coherent behavior from the cooperation of large numbers of
unreliable parts that are interconnected in unknown, irregular, and time-varying ways?
2) What are the methods for instructing myriads of programmable entities to cooperate to
achieve particular goals?
The objective of this research is to create the system-architectural, algorithmic,
and technological foundations
for exploiting programmable
materials.
These
"programmable materials" are materials that incorporate vast numbers of programmable
elements that react to each other and the environment. In order to do this, the group is
attempting to identify engineering principles for organizing and instructing a myriad of
programmable entities to cooperate to achieve pre-established goals, even though the
individual entities are connected in unknown, irregular, and time-varying ways.
Amorphous computing is inspired by the recent developments in molecular
biology and in microfabrication. Each of these is the basis of a kernel technology that
makes it possible to build or grow huge numbers of almost-identical informationprocessing units, with integral actuators and sensors, at almost no cost. Microelectronic
components are so inexpensive that the group can imagine mixing them into materials
that are produced in bulk, such as paints, gels, and concrete. Such "smart materials" will
be used in structural elements and in surface coatings, such as skins or paints. 6
The role that the work of this thesis will play is to help create the second and third
generation of the amorphous computing hardware. The group hopes to incorporate all of
the necessary hardware for each individual element onto a single chip. This includes the
processor, memory, and a radio for communications. The tool developed and used for
this thesis will be used to create the processor portion of this chip. For the second
generation of hardware, an existing processor design will be created in our new design
environment. This will then be combined with memory and the radio, and put onto a
single chip.
It is hoped that this tool will eventually be used to implement a
microprocessor similar to the Hitachi SH-3, which the group is currently developing.
This enhanced processor would then be used for the third-generation of amorphous
computing hardware.
1.4 Thesis Outline
This chapter has presented a summary of past research in automated layout tools,
as well as an overview of this project.
Chapter 2 delves into the first part of this project, the creation of a library of
standard cells.
Chapter 3 then turns to the implementation of the layout tool that is used to put
these standard cells together to create circuits.
Chapter 4 focuses on using this tool to create larger data path elements.
Chapter 5 then describes the use of this tool to create a substantial data path
design and assesses the performance of this tool in performing this task.
Finally, Chapter 6 concludes this thesis with the author's comments on this
experience.
Chapter 2
The Building Blocks: Standard Cells
The first part of this thesis involved the creation of a standard cell library. This
chapter details the design of the standard cells, which form the building blocks for data
path construction. These are the only parts of any given design that are laid out by hand,
which was done using the Magic layout editor7 . The first section of this chapter gives a
brief overview of the new design tool, which will aid in the understanding of the standard
cell design. The second section details the common set of design rules to which all
standard cells adhere.
The third section details how the design of the standard cells
facilitates placement and routing, while the fourth section describes the components that
are included in the library.
2.1 System Overview
In order to understand the standard cells, it is useful to have a general knowledge
of the system in which they will be used. The designer will write a program that utilizes
this tool to generate their design. Within this program, they will specify the layout by
tiling and copying existing standard cells in a specific fashion. Thus, all placement will
be completely controlled by the designer. The designer will then connect these standard
cells by specifying which nodes they wish to connect, as well as the channel(s) in which
this connection should be made. The process currently being used has four independent
routing layers: one poly and three metal. The poly and metall layers are reserved for incell routing. Thus, the general inter-cell routing method used will be to divide the design
into a large grid of horizontal and vertical channels. Top-level routing will be done on
this two-dimensional grid, with metal2 runs in the vertical direction and metal3 runs in
the horizontal direction. Vertical metal2 runs will begin and end each wire by connecting
to the desired node within a standard cell. They will then be connected by a horizontal
metal3 run, in the horizontal channel specified by the user. In this way, the designer will
specify both the placement and the routing of their design. An example of the routing
scheme can be seen in Figure 2-1.
Figure 2-1: Basic Routing Plan
2.2 A Basic Standard Cell
A basic standard cell is illustrated in Figure 2-2.
This 2-input NAND gate
demonstrates some of the main properties of all standard cells.
Each standard cell
includes power and ground rails, which border the remaining circuitry. A row of PFET's
lines the top of the cell, while a row of NFET's complements it at the bottom.
In
between, the appropriate connections are made via poly or metal 1. Nodes that need to be
accessed in the next level up in a design are connected to metal2 contacts centered at the
intersection of a horizontal and a vertical channel, to allow for over-the-cell routing.
Transistors were sized with the following points in mind. For most data path
circuitry, transistors can be fairly small. As a result, many transistors are minimum size.
Since PFET's are weaker than NFET's, they are generally twice as wide as the
corresponding NFET. Gates were also designed to match the speed of a minimum sized
inverter. For example, if two transistors are in parallel, then their width is doubled, as
can be seen in the NAND gate. In most cases, this is the most that was done to optimize
transistor sizes.
This particular processor design is most concerned with functionality, so most
standard cell circuitry is kept simple and reliable. Most standard cells consist mainly of
complementary logic and transmission gates. There are no dynamic logic gates, so that
recharging is not an issue.
Figure 2-2: Basic Gate Layout
2.3 Standard Cell Layout
The standard cells were laid out in a way to facilitate two main functions. First,
features have been incorporated to facilitate the tiling of multiple standard cells. Second,
they were laid out in such a way as to ease the routing of wires between standard cells.
2.3.1 Facilitating Tiling
The main concern in the tiling of standard cells is the connection of power and
ground rails. This problem is addressed by incorporating a few features into the standard
cells. First, all standard cells have a common height. In addition, each has an identical
set of power and ground rails, as described in the previous section. The width of these
rails is half the minimum width, or 4 lambda. This is so that when cells are stacked
together vertically, a minimum width power line will be created. The layout tool has
features that place the power/ground contacts as well as the ability to space out stacked
cells if necessary. Finally, these power and ground rails extend two lambda past their
standard cell circuitry, so that when two cells are placed next to each other the rails make
a connection, with no design rule errors.
2.3.2 Simplifying the Routing
The most important aspect considered in coming up with a set of standard cell
design rules was how to make routing as simple as possible. In order to prevent conflicts
with wires running between cells, the standard cells do not contain any metal2 or metal3
wires. In addition, to make it easy for the program to connect wires, all of the metal2
contacts are placed in the center of an intersection of a vertical and a horizontal channel.
Finally, the height and width of all standard cells are multiples of the horizontal channel
height and vertical channel width, respectively. This is so that when multiple cells are
tiled together either vertically or horizontally, each cell remains "on grid" and the
contacts remain at a channel intersection, as described above. For our particular process,
the minimum width of contacted metal2 wires is 4, while the minimum width of
contacted metal3 wires is 6. In addition, the minimum spacing between metal2 or metal3
wires is 4. Thus, these standard cells were designed around vertical channels with a
width of 8 lambda and horizontal channels with a height of 10 lambda. Note that in order
to make the 8 lambda vertical channels work error-free, m2/m3 contacts in the same
horizontal channel and adjacent vertical channels must be offset to the left or right by
one. This offsetting is specified by the user, when necessary.
2.4 Standard Cell Library
The library of standard cells includes all leaf nodes that are necessary for the
construction of a processor data path.
This includes basic complementary gates,
registers, and muxes. As mentioned previously, no dynamic logic is used and most gates
are kept simple in order to insure functionality. It is hoped that this library can also be
used to implement other data paths as well.
2.4.1 Basic Gates
A considerable portion of the library consists of simple, complementary gates.
This includes inverters, NAND, NOR, AND, OR, and-or-invert, or-and-invert, and buffer
gates. Most of these are made up of minimum-width transistors, although there are also
larger versions. These gates with larger FET's are used mainly in places where large
drive is necessary.
2.4.2 XOR and XNOR
Rather than one of the smaller, exotic XNOR circuits that are widely known, a
more reliable, slightly larger design was chosen. The XNOR circuit used can be seen in
Figure 2-3. The feature that makes it attractive is that the input nodes are connected only
to gates. In addition, it is made up of only complementary logic, with no transmission
gates. Thus, it is fully restoring. This is important for standard cell design, since it
makes this issue transparent to the system level designer. In addition, it is capable of
driving a more substantial load than many of the other pass gate XNOR circuits.
SPVR-
M 9"
M1 0
Fu 2
Figure 2-3: XNOR Schematic and Layout
2.4.3 Registers
Once again simplicity and reliability were chosen over more complicated
circuitry, and a static "jam" register was chosen. 8 No dynamic gates are used, so
charging is not an issue. This design also employs weak feedback inverters, which
reduces the load on the clock. A schematic of this register can be seen in Figure 2-5.
2.4.4 Multiplexor
The standard two-input multiplexor was designed using transmission gates. It can
be seen in Figure 2-4.
.............
..
M0
UT
M I
-W5
Figure 2-4: 2:1 Mux Schematic and Layout
................
MZ2
CLK
Ml1
DUT
Ml1
LK. L
Figure 2-5: Jam Register Schematic and Layout
Table 2-1: Standard Cell List
Number of
Transistors
Width
(channels)
Inverter - 4/2
Inverter - 8/4
Inverter - 16/8
2
2
2
2
2
3
Inverter - 32/16
2
5
Inverter - weak
2
4
Buffer - 4/2, 8/4
Buffer - 8/4, 16/8
Buffer - 16/8, 32/16
Driver
Nand2
Nor2
And2
Or2
Aoi21
Aoi22
Aoi31
Oai21
Oai22
Jam Register
T-Gate
2:1 Mux
Tristate Driver
Tristate Inverter
Xnor
Xor
4
4
4
2
4
4
6
6
6
8
12
6
8
16
2
4
4
4
10
10
4
4
4
7
3
3
5
5
4
5
7
4
5
16
4
5
3
4
6
6
Standard Cell
Chapter 3
The Place and Route Tool
Once the standard cell library was in place, the next step was to create the
algorithm that would use these standard cells to create a design. This chapter focuses on
the Lisp program that was created by several people in order to perform this task. This
program, magic.scm, can be found in the appendix. An overview of the basic strategy
was presented in chapter 2, so one is not given here. The first section of this chapter
discusses the method adopted to solve this problem. Section two focuses on how this
algorithm performs placement. Section three then details how routing is done.
3.1 Program Methodology
The members of this group decided that the most natural way to think about the
various parts of this problem was as objects. Thus, the basic strategy employed is to
convert magic files into data objects, manipulate them to create a design, and then
convert this back into a Magic file. Finally, an attempt was made to make this tool
functional in any process, rather than just the particular one used by this project. As a
result, there is a section that assigns design rule parameters that are essential to this tool
to the corresponding values for a specific process. So if the designer changes processes,
they can simply change the value of these global variables, and the program will still
work optimally, without creating design errors.
The first section of magic.scm contains the object definitions, as well as
procedures to access these objects. One of the major objects is a magic-file. This object
consists of additional objects: layers, one of the possible paint layers in Magic, such as
poly; uses, or subcells; and labels, which are names used to label nodes in a circuit. Each
of these objects also has several procedures associated with it, such as instantiate-use,
which is used to add a subcell to the current layout. As the reader will see shortly, this
procedure is used in performing layout. Another object is a magic-box, which is a vector
consisting of coordinates for the four comers of a box. This object is used to specify
where to add paint to the layout, such as in wiring. Finally, there are two procedures,
read-magic-file and write-magic-file, which are used to convert between this data
representation of a layout and the Magic representation.
These are basically parsing
routines, which extract the desired information and format it appropriately.
3.2 Performing Placement
The next section of magic.scm deals with placement.
There are two main
procedures used to perform placement. The basic idea, as described previously, is to tile
together subcells. The approach taken here is to first create a horizontal row of cells,
which usually make up a single bit-slice. Then, these slices are tiled vertically, to create
the data path. This is done with two main procedures. First, instantiate-and-tile is used
to create a single bit, by specifying the horizontal direction. Then, one of two things is
done.
If the circuit being designed consists of identical bit-slices, then instantiate-
vertical-array can be used to create an array of the subcircuit just designed. If the bits are
different, then instantiate-and-tile can be used in the vertical direction. Instantiate-andtile-vertical-array was added after some use of this tool, in order to simplify the the task
of replicating a single subcircuit a large number of times.
Instantiate-and-tile takes in a number of arguments, including the direction in
which to tile. Most of the arguments are lists: uses-to-instantiate, or the subcells that the
designer wishes to tile together, in the order in which they will be tiled; instance-names,
or the names to be given to the particular instances of the uses you are tiling; transformgenerators, or transforms that you wish to apply to the instances you are tiling, such as
flipping them upsidedown or sideways; xoffsets and yoffsets, which are used to offset the
instances you are tiling in the x or y direction. The list of transforms is defined earlier in
this section of the code, and they are performed by transforming the coordinates of a use
appropriately. This algorithm then applies instantiate-use to each set of corresponding
entries of these lists. It also calculates the correct position at which to place the next
instance, by setting the variables xpos and ypos appropriately.
Instantiate-and-tile-
vertical-array is very similar, except that it does some things to simplify the process of
creating an array. It takes in the name of the use you wish to instantiate and the number
of times you wish to instantiate it.
It then creates the lists described above of the
appropriate length and calls instantiate-use on each set of the corresponding entries of
these lists. It does assume several things, such as the name for each instantiated use,
which is simply the name of the subcell with a number appended to it that corresponds to
the number of that particular instance in the array. By using these procedures, the user is
able to specify the exact placement of the subcells in their design.
3.3 Performing Wiring
The remainder of magic.scm deals with the task of connecting the placed uses
together. As described before, this tool divides the layout into vertical and horizontal
routing channels in order to perform the routing. There are two important routing tasks.
The first one is routing signals, or routing from one label to another. The second one is
routing power and ground via a large grid.
3.3.1 Routing Signals
Routing of signals is done via the procedure instantiate-wire.
This procedure
takes as arguments the magic file being edited, the name of the use and the label in that
use from which the wire will start, the name of the use and the label in that use where the
wire will terminate, and a horizontal channel index. A label is a term Magic uses to give
a name to a rectangular area on a particular layer. They are used to indicate where the
"pins" for each cell are located. The procedure then routes a wire consisting of a metal3
horizontal wire in the specified channel, and metal2 vertical wires from the specified
labels to this horizontal wire, with contacts at the intersections of these wires.
These
metal2 wires are painted in the vertical channel in which their labels occur.
As
mentioned previously, wires are created by making boxes and filling them in with the
appropriate metal.
Instantiate-wire performs the above task by calling several other procedures. It
uses instantiate-vertical-wire-segment to make the vertical wires. This procedure creates
a box that spans from the center of the specified starting horizontal channel to the center
of the specified ending horizontal channel in the specified vertical channel. This box is
centered in the vertical channel, and has a width equal to the minimum metal2 width.
This width is one of the previously mentioned global variables that is process-dependent.
The box is then filled with metal2. Next, instantiate-horizontal-wire-segment is used to
make the horizontal wire and the contacts. This routine is similar to instantiate-verticalwire, as it creates boxes and then fills them with the appropriate paint.
The only
difference is that this box spans from the center of the starting vertical channel to the
center of the ending vertical channel, in the specified horizontal channel. Again, this box
is centered in the horizontal channel, and has a width equal to the minimum metal3
width. This procedure also uses instantiate-contact to place the contacts at the ends of
this wire. Instantiate-contact takes a layer, height, width, and vertical and horizontal
channel indexes as arguments. It then creates a box of the desired height and width
centered in the intersection of the specified channels and fills it with the specified layer.
There are several other wiring procedures that allow for more complicated wiring.
Instantiate-five-segment-wire is very similar to instantiate-wire, except it contains two
more jogs. In other words, the user specifies a starting horizontal channel, a vertical
channel, and then an ending horizontal channel. As before, the procedure routes from the
specified labels to this wire with vertical wires. It works very similar to the way
instantiate-wire does. This procedure can be used when the vertical channel that one of
the labels is in is already in use by another wire. Instantiate-single-layer-wire is another
wiring procedure, and it can be used to make a wire on a single layer. This works similar
to instantiate-wire,
except it uses
instantiate-specified-vertical-wire-segment
instantiate-specified-horizontal-wire-segment
and
rather than instantiate-vertical-wire and
instantiate-horizontal-wire. This procedure is useful for routing between adjacent cells in
metall to save routing channels, where this is possible. There are two other procedures
instantiate-vertical-strap and instantiate-horizontal-strap that are very similar to one
another. They can be used to create a straight wire from one specified channel to the
next, in either the horizontal or vertical direction. These procedures create a
horizontal/vertical wire on the specified layer, in the specified horizontal/vertical channel,
and runs it from the left edge of the specified starting vertical/horizontal channel to the
right edge of the specified ending vertical/horizontal channel. This is useful for doing
things like tying a node to ground or VDD.
These procedures enhance the basic
instantiate-wire command by allowing the designer to route several different types of
wires.
3.3.2 Routing Power and Ground
Power and ground are distributed across the chip by a grid whose properties are
set by the designer. As explained in section 2, all standard cells include metall power
and ground rails bordering the top and bottom, respectively. Thus, when cells are tiled
together horizontally and vertically, these create horizontal power and ground wires,
which are shared by adjacent rows. In order to handle large power requirements, rather
than butting each vertical row up against its neighbor, these can be spaced out. Then, the
space can be filled in with metall, effectively creating wider power and ground rails.
Since this program relies on the contacts within standard cells being on a grid in order to
perform signal wiring, all standard cells have to remain on grid. Thus, the width of the
horizontal rails must be increased in increments equal to the horizontal channel height.
In order to make power distribution even more efficient, the designer also has the ability
to add vertical metal2 wires to connect these horizontal power and ground rails. The
designer therefore has several options when routing power: they have the flexibility to
set the width of both the horizontal and vertical wires, as well as how frequently to place
the vertical connections. The final task that needs to be handled is the placement of
substrate contacts, which are placed in the center of the horizontal power and ground
rails, the minimum distance apart. Note that this happens to correspond to the vertical
grid spacing.
The task of routing power and ground is performed by the function instantiatepower-grid. This procedure performs the three functions described above: it creates the
horizontal rails of the desired width, it places substrate contacts, and it routes the vertical
interconnections of the desired width and spacing. In order to do this, instantiate-powergrid takes in three arguments: horizontal-channel-span is used to specify the width of the
horizontal wires, vertical-rail-spacing is used to specify the frequency of vertical rails,
and vertical-rail-width is used to specify the width of the vertical rails. The procedure
can be divided into three main parts according to the task that each part performs.
The first part of this procedure creates the horizontal rails. This is done with the
named-let instantiate-horizontal-rails. This routine walks down the specified layout from
top to bottom, painting horizontal metal 1 wires at the appropriate places. This is done by
calculating the topmost channel of the design, and then moving down the appropriate
number of channels in between wires, depending on the desired horizontal-channel-span.
In order to do the painting, it calls the previously mentioned procedure instantiatehorizontal-strap. The starting and ending vertical channels are the leftmost and rightmost
channels of the design, which are also calculated by instantiate-power-grid.
The second part of this procedure is interleaved with the painting of these vertical
wires, and that is the placing of contacts. There are actually two types of contacts that
need to be placed, the substrate contacts and the metal2 contacts that will connect the
horizontal and vertical power wires together. These contacts are placed on a particular
horizontal channel after it has been painted. This is done with the named-let instantiatesubstrate-contacts. This section of the code walks across the particular horizontal wire in
minimum contact spacing increments, determines which type of contact to paint at each
location, and paints that contact.
The determination of contact type is based on the
vertical-channel-spacing argument, which tells the program where vertical wires will be
going and thus where metal2 contacts need to be placed. The actual painting of the
contacts is done with the append-box routine, which creates a box at the specified
location and fills it with paint from the specified layer.
The final part of this routine is the painting of the vertical wires where
specified by the designer. These are painted by the named-let instantiate-vertical-rails.
This code once again walks across the entire layout horizontally. Only this time it paints
pairs of adjacent vertical metal2 wires, one from the topmost power rail to the
bottommost power rail and one from the topmost ground rail to the bottommost ground
rail, with each pair of wires spaced apart by the specified vertical-rail-spacing.
painting of the vertical wires is done with instantiate-vertical-strap.
The
The leftmost and
rightmost vertical rails are created separately, by another let function called instantiatevertical-boundary. This procedure walks down the entire design and paints two pairs of
metal2 wires at each standard cell row location. It uses instantiate-vertical-strap to add
wires from the current set of horizontal power and ground rails to the power and ground
rails just below, on both sides of the design. This in effect creates vertical wires that run
the length of the design and are connected to every horizontal power or ground rail. It is
in this way that the power grid is created on a given layout.
Chapter 4
Data Path Elements
After developing the standard cell library and place-and-route tool, the next step
was to use these to construct the components necessary for data path design. The idea
was to create a set of data path elements that would be used in the processor, as well as
future data path designs. These included elements such as a 32-bit adder and a 32-bit
register. Rather than describe each of these blocks, this chapter will instead focus on the
design and construction of one such component, the 32-bit adder. It is hoped that this
will give the reader a better understanding of how this tool is used to construct circuits.
The first section will describe the types of adder designs investigated for this project, and
explain the design of the adder circuit that was finally chosen. Section two will then
explain how the new tool was used to construct this adder out of standard cells. Section
three concludes the chapter by commenting on other blocks that were constructed in a
similar fashion.
4.1 32-Bit Adder Design
Addition is the basis for many processing operations. As a result, an adder is an
important part of a data path cell library. A wide variety of implementations exist, and
the choice as to which one to use depends on speed and density requirements. A variety
of adders were designed and simulated for this project, and in the end a binary look-ahead
carry adder was chosen.
4.1.1 Binary Full Adder
The familiar equations for a binary adder, where A and B are the summands, Cin
is the carry input, S is the sum output, and Cot is the carry output are:
S
=
A
Cout
=
AB + Cin(B+A)
B
@
Cin
These can be factored into the alternative form:
S
=
P
Cin
Cout
=
G
+ PCin
G
=
AB
P
=
A
where
generate signal
propagatesignal
B
4.1.2 Ripple-Carry Adder
The simplest 32-bit adder design consists of 32 full adders chained together. The
above full adder equations can be implemented with the following gates:
F
-
A
c
Figure 4-1: Full Adder Schematic
While small and simple, this adder is slow, due to the long carry chain. However, it does
provide a base on which to compare the speed of more complicated adders.
4.1.3 Carry-Skip Adder
The worst-case delay for a ripple-carry adder occurs when a carry is generated in
the lowest order bit and must propagate through the entire adder. One way to improve
this delay is to "skip" the carry over a block of full adders if the propagate signals for
each bit in the block are high. 9 This design consists of a ripple-carry adder divided into
blocks, where a special circuit associated with each block quickly detects if all the bits to
be added are different (Pi = 1 for all bits). In this case, the carry entering into the block
may directly bypass it and be transmitted into the next block. It is also worth noting that
if Ai=Bi for some i in the block (Pi = 0), no block is skipped, but a carry is generated in
that block. Thus, the carries are propagated in parallel, and the total time of computation
is bound by the time of carry propagation in the largest block.
The carry-skip block is actually just the AND of every Pi in a given block. Since
the fan-in of this AND gate equals the number of bits in a block, optimal block sizes are 3
or 4 bits. Additional improvement can be achieved by adding additional layers of skip.
These layers would then skip multiple blocks, and they are conveniently identical in
construction to lower skip levels. An optimal scheme consisting of two levels of skips
was determined and tested.
It was found that the speed of this adder was limited
primarily by the speed of the skips, which become slow with high fan-in.
4.1.4 Manchester Adder
Another method commonly used to improve the speed of addition is a Manchester
carry chain. '1
The objective behind this design is to propagate the carry as fast as
possible, by using Pi and Ci to either propagate or generate a carry for each bit. One way
to do this is with a multiplexor in the following configuration:
-?II
Figure 4-2: Manchester Carry Adder Schematic
However, such circuits rapidly slow down as bits are chained together, due to the
resulting chain of transmission gates. So once again, the adder is divided into blocks and
separated with restoring inverters. With the gates used for this project, the optimal block
size was found to be 3. A further improvement can also be gained by applying the skip
idea from before. Once again, blocks of bits can be skipped if all of the bits in a block
are propagating a carry. The skip circuitry chosen for this design was a "conflict-free"
circuit, which improves the speed by using a 3-input multiplexer that prevents conflicts at
the wired OR node in the adder. This can be seen in Figure 4-3. The control signals T1,
T2, and T3 are generated as follows: T1 = -(PoP 1)P2 , T2 = -P2 , T3 = PoPIP2 •
-Pi
-Ti
Figure 4-3: Conflict-Free Manchester Carry Skip Circuitry
This idea of skipping bits can also be applied to the resulting blocks.
A 32-bit
manchester adder with carry skip as described was constructed, and it turned out to be
quite fast. This design consists of ten 3-bit manchester-skip blocks in series, with a full
adder tacked onto the front and rear of this array. Then, block-skip circuitry is added on
top of this, as can be seen in Figure 4-4. Once again, the rate-determining element turned
out to be the skip circuitry, which became slow for large fan-in or significant loads.
Thus, the buffering inverters must be kept small.
Figure 4-4: 32-Bit Manchester Carry-Skip Adder Schematic
35
4.1.5 Binary Lookahead Carry Adder
The idea behind this adder is to improve the linear growth of carry delay with the
size of the input for an n-bit adder by calculating the carries for each stage in parallel.
The carry for the ith stage, Ci, may be expressed as
Ci
=
Gi + PiCi-I
Expanding this yields
Ci
=
Gi + PIG,1 + PiP,-G,-2+ ... + P...P1C 0
The size and fan-in of the gates needed to implement this carry-lookahead scheme
becomes quite large as the number of bits increases. One alternative to this method is to
compute the carries in a binary fashion." Define a new operator # such that :
(g1,p1) # (g2, 2) = (g1 + 91gl, P1P2). It can be seen that the carry signals can be determined
by G,, where
(Gi,P,) =
(gl,p 1 )
if i=1
(g,p,) ... # ... (G,,Pi.)
if 2 <i < n
(g,, p,) # (g,- ,P,-1) ... # ... (gi,pi)
In other words, by combining the p,'s and g,'s from two input bits, or the results
from two previous combinations of such signals, the carry bits are constructed in a binary
fashion. Such an adder can be divided up into sections, as shown in Figure 4-5.
C
G
PG
BLOCK
32
P
CARRY
EVALUATION
BLOCK
32
SUM
BLOCK
32
Figure 4-5: Binary Look-Ahead Carry Adder Block Diagram
The generate/propagate block simply consists of the logic required to compute P
and G and can be seen in Figure 4-6. The sum block consists of an array of XNOR's.
The carry block consists of the logic required to implement the # function. In order to
improve speed and reduce the number of gates, we can complement alternating # blocks.
These blocks can be seen in Figure 4-7, as BA and BB.
Figure 4-6: GP Block Schematic
Figure 4-7: BA and BB Block Schematics
The carry evaluation block then looks like Figure 4-8 for a four-bit adder. This
pattern is then iterated to create the carry block for an adder of the desired size. Since
two bits are combined at each stage, a binary tree is formed, and thus the speed of this
adder is proportional to log 2(n).
Another nice feature of this adder is that it is very
regular, and thus not too difficult to layout, especially with multiple layers of signal
wiring. Such an adder was designed and built, and it was the fastest of the previously
mentioned adders.
One of the limiting factors of such an n-bit adder is that the most significant '#'
operator in each of the j columns of the carry evaluation block must drive 2 "#" blocks in
the next stage. As n gets large, this can be a considerable load, as j=log 2(n). Thus,
buffering of such signals becomes very important. One approach to this problem is to run
these outputs directly to the most-significant "#" block in the next stage, while
simultaneously buffering them to the remaining "#" blocks.
This will maximize the
speed at which these outputs reach the most significant block, which turns out to be the
critical path. In the design used for this project, various sizes of inverters were used to
perform this buffering. In the second to last stage, for example, a buffer consisted of a
16/8 inverter followed by a 32/16 inverter. A schematic for the 32-bit BLCA Adder can
be seen in Figure 4-9.
-CD
0P30UT
>3PUA
c
BA
c
c"
P
P
PH
P
P34
C
POUT
C34
PU-
cUT ..-
P
P UT
CO
C 0
0T
C3OUT
P30 UT
l
93
Figure 4-9: 32-Bit BLCA Adder Schematic
41
4.1.6 Final Results
Table 4-1: 32-Bit Adder Results
32-Bit Adder Style
Ripple-Carry Adder
Carry-Skip
Manchester Carry Chain
Manchester Carry Chain with skip
Binary Carry-Lookahead
Computation Time (ns)
8.5
3.5
6
2.7
2.1
These results are from a schematic-capture program, which was then used to generate
Spice files. This program does not take all capacitances into account. Each circuit was
tested in the bottom left process corner, with a Vdd of 3V and a temperature of 125 C.
4.2 Layout of the 32-Bit Adder
The organization of the adder in layout corresponds very closely to the schematic.
The generate/propagate logic lines the far left, the array of XNOR's is on the far right,
and the columns of the carry block are in the middle. One convenient feature of this
adder is that the carry buffers fit nicely under the subsequent columns of the carry block,
as can be seen in the Figure 4-10.
All of the necessary leaf cells already existed in the standard cell library, so the
only thing that needed to be done was to place and route them. The 32-bit adder contains
large amounts of redundancy, so it was constructed in such a way as to maximize the
power of the place-and-route tool. First, the GP, BA, and BB blocks were constructed.
One feature worth pointing out is the overlap of the two cells that make up BA, which is
a nice feature supported by the place-and-route algorithm. Then, the carry block for a
two-bit adder was constructed out of these pieces and connected to two GP blocks. As
can be seen from the schematics, the carry block for a four-bit adder is simply a pair of
two-bit adders, with an additional column of BA's on the top two bits. Moreover, an
eight-bit adder consists of a pair of four-bit adders, with an additional column of BB's on
the top four bits, and so on. This is the method that was used to construct the GP and
carry block sections of the 32-bit adder. One detail that must be attended to is the
polarity of the inputs to the BA and BB blocks. If there are ever two consecutive BA or
BB blocks, then the outputs of the first one must be inverted before they are input into the
second one.
These inverters were put wherever there was space, which was usually
underneath the carry buffers.
Finally, an array of 31 XNOR's and an inverter were
appended to the right of the carry block, in order to generate the SUM and C31 outputs
(only 31 XNOR's are required because SO is just PO when there is no Cin).
4.3 Additional Blocks
The other necessary blocks were constructed in a similar manner. However, the
adder was the one block that involved significant research in the area of circuit design.
Unlike the adder, the other blocks were based on the schematics for a previouslydesigned processor. The only major difference between these is transistor sizes, due to
the switch from custom hand layout to standard cells.
IIWO
Figure 4-10: 32-Bit
BLCA
Adder Layout
8~~
thiM
MD ~tdWrd
am_•..
'M
......
V!,
i.
a
x -1
RA
a
I
lxx
,V4%
M
-:i d
l-
Figure 4-10: 32-Bit BLCA Adder Layout
Chapter 5
Taking the Tool for a Test Drive
Once a standard cell library and a functional tool were in place, the next step was
to test them out on a substantial design. By using this new design methodology to create
an example design, it was hoped that its performance could be evaluated. It was also
hoped that this exercise would lead to the identification of improvements for future
versions of this tool. This chapter documents the testing of this new system. The first
section describes the design that was built. Section two comments on how this circuit
was built. Finally, section three suggests some possible improvements that could be
implemented in the future.
5.1 A 32-Bit Counter
Rather than building a complete data path, it was decided to first test out this tool on
a smaller, but still substantial design. A 32-bit counter was chosen for this task. A
schematic for this counter can be seen in Figure 5-1.
It consists of a 32-bit 2:1
multiplexor, the previously described 32-bit adder, a 32-bit register, and some control
logic. The output of the mux, which is either the value in the register or 0 depending on
the output of the control logic, is input into the adder as addend A. Addend B is hardwired to be 1. The result of this addition is then stored in the register. The control logic
detects when the value 231 is in the register. Thus, this counter counts up by 1 until it
reaches 231, at which point it is reset to 0.
Figure 5-1: 32-Bit Counter Schematic
5.2 Building the Counter
The basic approach used in constructing the counter is the one that would be taken
when constructing any data path. Each block was built from the bottom up, and then the
blocks were put together. The file containing the counter design, counter.scm, can be
found in the appendix.
5.2.1 32-bit Multiplexor
As mentioned previously, all blocks were constructed from the bottom up. Thus,
a single bit-slice of a particular block was constructed out of standard cells. This bit-slice
also included as much of the wiring as possible. Then, this slice was copied to construct
a 32-bit unit. Including wires where possible allows them to be duplicated when the
larger array is built, rather than having to route them for each slice. One of the keys to
maximizing the utility of this tool is to take advantage of replication wherever possible.
When building bit-slices, and doing any wiring, the basic approach taken is to have
Magic and Scheme running side by side. Then, you can look at the layout you have just
done and make changes, and then view them, on the fly. This is especially helpful in
choosing which channels to use for routing.
This is the approach that was used to build the mux, in which all 32 bit-slices are
identical. First, a single bit slice was built, tgmux_gnd. This is one of the standard cells,
tgmux, with one of its inputs wired to ground.
This was then duplicated, using
instantiate-and-tile-vertical-array, in order to create a 32-bit mux. Finally, all of the S
nodes and all of the -S nodes were wired together, by running a wire from these nodes in
the topmost bit to the corresponding nodes in the bottommost bit.
5.3.2 32-bit Register
The 32-bit register also consists of 32 identical bit-slices, and it was constructed
in a similar fashion. A single bit-slice was replicated with instantiate-and-tile-verticalarray to create a 32-bit register.
5.2.3 Counter Logic
The logic required for resetting the counter is basically a big AND tree. This was
constructed out of a vertical array of NAND and NOR gates, which was built from the
bottom up. First, a small two-level tree was built out of two NOR gates and a NAND
gate. Then, this was copied twice and another NOR was added to create a three-level
tree.
This same process was used until eventually a five-level, 32-input tree was
constructed. Since most of the inputs to this tree need to be inverted, an array of 32
inverters was tiled horizontally with this logic.
5.2.4 Putting It All Together
Once all of the individual blocks were constructed, the next step was to put them
all together. The counter was laid out the same way it is drawn in the schematic, as can
be seen in Figure 5-2. All of the blocks were tiled together using instantiate-and-tile.
Since wires need to run across the data path and there are no free horizontal channels
across the adder, the bit-slices were all spaced apart by one channel width. This was
done by assigning a global variable, row-spacing, to be 1. Using this as an argument for
instantiate-and-tile allows the entire design to be spaced appropriately by simply
changing this variable.
Next, all of the necessary connections were made.
These
constitute the bulk of the counter.scm file, as well as the bulk of work that went into
building the counter.
The A inputs to the adder were tied to VDD and GND with instantiate-verticalstrap. All of the wires for even-numbered bits are nearly identical, as are all of the wires
for odd-numbered bits. The difference between these two groups of bits is the direction
from them to the nearest GND rail. The only difference between nearly identical bits was
the specified horizontal channel. So, it was possible to wire bitl and bit2 and then copy
the description of these wires sixteen times each. Then, the horizontal-channel-index just
had to be changed for each bit to the appropriate value. Finally, bit0 had to be wired,
since it is the one bit that actually needs to be connected to Vdd.
The output of the mux was wired to the other input of the adder using instantiatewire. These wires were more time-consuming since the ending-use-ids were all different.
The starting-use-ids were identical, except for the number of the mux. The only other
difference was again the horizontal-channel-index. But changing these was fairly easy,
since there is a pattern to them.
The output of the adder was wired to the register similar to the way the mux was
wired to the adder input. This was done with instantiate-wire. The descriptions of most
of these wires are also very similar to one another. In this case, they are even more
similar than before. The only differences in use-ids are the numbers of the xnor in the
adder and the reg_bit in the register, and of course the horizontal-channel-index.
So it
was possible to copy one wire 31 times, and then change the numbers on the xnor and
reg_bit appropriately. Once again, there is a pattern to the horizontal-channel-index, with
each subsequent wire being seven channels above the previous one. The only different
wire is the first one, from CO to the register. As described previously, this is generated in
the GP block of the adder, and doesn't come from an XNOR.
Again, the output from the register to the inverter array of the logic block was
done in a similar manner. This time, though, since the two contacts to be connected were
adjacent, it was possible to conserve metal-2 and metal-3 channels by wiring these in
metal-1. This was done with the instantiate-single-layer-wire command. Again, the only
differences are the number indexes on the starting and ending use-ids, and the horizontalchannel-indexes. These are handled the same way as before - one wire is done and then
copied 32 times, and then the appropriate numbers are changed for each wire.
The output of the inverters were then wired to the NOR gates in the first level of
the logic tree.
For half of the inputs, the inverter is adjacent to the nor gate, so
instantiate-single-layer-wire can be used as before. The other half of the inputs are in
different horizontal rows, so they must be wired with instantiate-wire. Again, the first
two inputs were wired, one of each type, and these were then copied. These wires were
similar to those from the mux to the adder, in that the ending-use-ids were significantly
different from wire to wire, and they required more attention.
The output of the register also had to be fed back to the input of the mux. This
was done with instantiate-wire, and these wires were placed in the space between
horizontal rows of standard cells in the design. They were done similar to all previous
wires. The final wire that had to be added, was from the two outputs of the logic block
to the select bits (S and -S) on the mux. These were placed at the bottom of the design.
The last thing that had to be done was the creation of the power grid.
The
horizontal width was set by row-spacing, to be 1, since all rows of standard cells were
spaced 1 channel apart, as previously mentioned. It was decided to distribute power with
one set of vertical wires of width 4, based on some rough calculations.
;rr
~
q .7i
14'
-J, 04
i
Wei
q ll
ozf
iV
wo,"A
r
%.
*4
0_,r ov, M-6
0 lo
Figure 5-2: 32-Bit Counter Layout
!i
The final part of counter.scm is several "make" definitions. These call the
previously written procedures, which build the necessary blocks. This makes it simple to
rebuild things, if changes are made. The file can simply be reloaded and these "make"
procedures can be called, rather than calling each procedure individually. For example, if
a change is made at a very low level, calling make-counter rebuilds the entire counter
from the bottom up and the counter will therefore include this change. It takes about a
minute to rerun counter.scm and rebuild the entire counter.
5.3 Possible Improvements
The process of designing and using this tool has offered valuable insight into
ways in which it could be improved. Like most projects numerous decisions had to be
made as to how to implement certain things. Since this was my first time working with
CAD tools, many of these were made with little experience on which to base them.
Looking back, I think that some things could be done differently in order to improve
performance. In addition, some features could be further augmented.
5.3.1 Improving Wiring
As mentioned in chapter 4, the most time-consuming part of building the counter
was wiring between the individual 32-bit blocks. This difficult task presents several
challenges. One thing that slows down this wiring is the fact that the designer has to
enter all of the use-ids. And as was the case with the counter, these can be different from
one bit to the next. One possible way to deal with this would be to create a function that
takes a given wire and copies it, based on its geometric properties. So, you could make a
wire and then copy it, but move this copy to a different horizontal channel. Then, you
wouldn't have to enter all of the use-ids, but could instead just copy the wire in the
appropriate places.
Another problem with the wiring is that changing the amount of space between
rows of standard cells can result in wires violating design rules. This is because the
designer places wires by specifying a horizontal channel. While this channel may be free
for one row spacing, it may not be for another spacing. This results in the designer
having to go back and change the horizontal-channel-index for wires if they don't plan
out the appropriate row-spacing before they do the wiring. One way this problem might
be dealt with is to add more "intelligence" to the wiring routines. It may not be necessary
to specify the horizontal channel for all wires, since this may not be that important.
Adding something like a "greedy" channel router to automatically route these in open
channels, and routing only the more important wires explicitly might be a good
alternative. This would probably save considerable time and effort at little cost.
5.3.2 Enhancing the Routing of Power and Ground
Another area in which additional work could be done is in the routing of power
and ground. The current routine requires the user to calculate the power requirements of
the various parts of the design and then specify the horizontal wire width and vertical
wire spacing. More "intelligence" might also be added to this routine in the future, so
that it could estimate the power requirements of the design and then pick the appropriate
values for horizontal wire width and vertical wire spacing. This would save time and
effort and help speed up the design process even more.
5.3.3 Accepting Additional Input Styles
The current tool requires the user to input their design in the Lisp-like form
described in chapter 3. This form is fairly simple, but it might be nice to allow this tool
to take in other forms of input as well.
With the widespread use of VHDL, one
possibility would be to allow it to take in VHDL descriptions and then convert them into
layout. Another possibility might be that it could take in a netlist that is generated by
some schematic capture tool such as ViewLogic. This might also save substantial effort,
as the designer would no longer have to enter the bulk of the information by hand.
Chapter 6
Conclusion
The design, implementation, and test drive of a tool for data path construction
have been described in this thesis. Most of the goals for this project were met. This tool
provides an automated method for design that reduces design time over custom hand
layout. At the same time, it provides design control by allowing the designer to specify
placement and routing. This enables standard cells to be placed in logical groupings,
resulting in readable layouts. In addition, this tool is fairly easy to use. Finally, this
program runs relatively quickly, as once a design file is written it can be converted to a
Magic layout in a few minutes at most. Although these goals were met, there is plenty of
room for improvement.
Additional functions could be added to further reduce design
time, as mentioned in chapter 5.
I have learned several things from this project. As my first experience in CAD
tool design, it has given me insight into how these tools work. It has also given me
exposure to standard cell design, and I have learned how to make the implementation of
these cells as transparent as possible to the designer at the next level. This work has also
shown me the complexity involved in the tasks placement and routing, and the many
different approaches to performing these tasks. This has reminded me that there are often
many different ways to solve a problem, all of which may be viable solutions.
Appendix
A.1 magic.scm
(declare (usual-integrations))
;Useful constants
(define infinity 999999999)
(define minus-infinity (- infinity))
;Design
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
(define
rule parameters
metall-spacing 8)
metall-width 4)
half-metall-width (/ metall-width 2))
horizontal-metall-channel-height metall-spacing)
metall-height 4)
half-metall-height (/ metall-height 2))
metal2-spacing 8)
vertical-channel-width metal2-spacing)
metal2-width 4)
half-metal2-width (/ metal2-width 2))
metal3-spacing 10)
horizontal-channel-height metal3-spacing)
metal3-width 6)
half-metal3-width (/ metal3-width 2))
metal3-height 6)
half-metal3-height (/ metal3-height 2))
m3contact-width 6)
half-m3contact-width (/ m3contact-width 2))
m3contact-height 6)
half-m3contact-height (/ m3contact-height 2))
m2contact-width 4)
half-m2contact-width (/ m2contact-width 2))
m2contact-height 4)
half-m2contact-height (/ m2contact-height 2))
;Object definitions
(define-structure (magic-file
(keyword-constructor make-magic-file)
(conc-name magic-file/)
(print-procedure
(standard-unparser-method
'MAGIC-FILE
(lambda (mf port)
(write-char #\space port)
(write (magic-file/filename mf) port)))))
(filename #f)
(tech #f)
(timestamp #f)
(layers '())
(uses '())
(labels '()))
(define (find-use mf use-id)
(let ((result #f))
(let loop ((uses (magic-file/uses mf)))
(if (not (equal? uses '()))
(if (equal? use-id (magic-use/use-id (car uses)))
(set! result (car uses))
(loop (cdr uses)))
(error "Unable to find requested use")))
result))
(define (find-label mf label-name)
(let ((result #f))
(let loop ((labels (magic-file/labels mf)))
(if (not (equal? labels '()))
(if (equal? label-name (magic-label/label-name (car labels)))
(set! result (car labels))
(loop (cdr labels)))
(error "Unable to find requested label")))
result))
(define-structure (magic-layer
(keyword-constructor make-magic-layer)
(conc-name magic-layer/)
(print-procedure
(standard-unparser-method
'MAGIC-LAYER
(lambda (layer port)
(write-char #\space port)
(display (magic-layer/layer-name layer) port)
(write-char #\space port)
(write (magic-layer/boxes layer) port)))))
(layer-name #f)
(boxes '()))
(define (get-layer magic-file layer-name)
(let loop ((layers (magic-file/layers magic-file)))
(if (not (equal? layers '()))
(if (eq? layer-name (magic-layer/layer-name (car layers)))
(car layers)
(loop (cdr layers)))
;didn't find it, make one
(instantiate-layer magic-file layer-name))))
(define (instantiate-layer magic-file layer-name)
(let ((layer (make-magic-layer 'layer-name
layer-name)))
(set-magic-file/layers! magic-file
(cons layer
(magic-file/layers magic-file)))
layer))
(define-structure (magic-box (type vector) (constructor #f)
(conc-name magic-box/))
(xleft #f)
(ybot #f)
(xright #f)
(ytop #f))
(define (make-magic-box xl yl x2 y2)
(vector (min xl x2) (min yl y2) (max xl x2)
(max yl y2)))
(define (magic-box/width box)
(- (magic-box/xright box) (magic-box/xleft box)))
(define (magic-box/height box)
(- (magic-box/ytop box) (magic-box/ybot box)))
(define (horizontal-center magic-box)
(/ (+ (magic-box/xright magic-box) (magic-box/xleft magic-box))
(define (vertical-center magic-box)
(/ (+ (magic-box/ytop magic-box) (magic-box/ybot magic-box))
(define (append-box layer box)
(set-magic-layer/boxes!
layer
(cons box
(magic-layer/boxes layer)))
box)
(define (instantiate-box layer xl yl x2 y2)
(let ((box (make-magic-box xl yl x2 y2)))
(append-box layer box)))
(define-structure (magic-use (conc-name magic-use/)
(keyword-constructor make-magic-use)
(print-procedure
(standard-unparser-method 'MAGIC-USE
(lambda (use port)
(write-char #\space port)
(display (magic-use/use-id use) port)
(write-char #\space port)
(write (magic-use/box use) port)))))
(filename #f)
(use-id #f)
(array #f)
(timestamp #f)
(transform #f)
(box #f)
(transform-generator #f))
(define (magic-use/width use)
(magic-box/width (magic-use/box use)))
(define (magic-use/height use)
(magic-box/height (magic-use/box use)))
(define (append-use magic-file use)
(set-magic-file/uses! magic-file
(cons use
(magic-file/uses magic-file)))
use)
2))
2))
(define (instantiate-use magic-file
use-file
use-id
transform-generator
xorg
yorg
#!optional array)
(let ((new-use (make-magic-use
'filename use-file
'use-id use-id
'array (if (default-object? array)
#f
array)
'transform-generator transform-generator
(subcell-mf (read-magic-file use-file)))
;Set bounding box
(set-magic-use/box! new-use (magic-file-bounding-box subcell-mf))
;Set transform
(set-magic-use/transform! new-use
(compose-magic-transforms
(transform-generator new-use)
(magic-translate
(- xorg (magic-box/xleft
(magic-use/box new-use)))
(- yorg (magic-box/ybot
(magic-use/box new-use))))))
(append-use magic-file new-use)
(define-structure (magic-label (conc-name magic-label/))
(layer #f)
(box #f)
(position #f)
(label-name #f))
(define (instantiate-label magic-file layer-name box position labelname)
(let ((label (make-magic-label layer-name box position label-name)))
(set-magic-file/labels! magic-file
(cons label
(magic-file/labels magic-file)))
label))
(define-structure (magic-use-array (conc-name magic-use-array/))
(xlo #f)
(xhi #f)
(xsep #f)
(ylo #f)
(yhi #f)
(ysep #f))
(define-structure (magic-transform (conc-name magic-transform/))
(a #f)
(b #f)
(c #f)
(d #f)
(e #f)
(f #f))
(define magic-label-position-names
'#(CENTER NORTH NORTHEAST EAST SOUTHEAST SOUTH SOUTHWEST WEST
NORTHWEST))
(define (read-magic-file filename)
(let ((pathname (pathname-new-type (merge-pathnames filename)
"mag")))
(call-with-input-file pathname
(lambda (port)
(let ((magic-file (make-magic-file
'filename (->namestring
(if (equal? "mag"
(pathname-type filename))
(pathname-new-type filename #f)
filename)))))
(define (parse-tech line)
(parse-optional line "tech " parse-timestamp
(lambda (line)
(set-magic-file/tech! magic-file
(string-tail line 5)))))
(define (parse-timestamp line)
(parse-optional line "timestamp " parse-body
(lambda (line)
(set-magic-file/timestamp!
magic-file
(parse-time (string-tail line 10))))))
(define (parse-body line)
(cond ((string=?
"<< end >>" line)
(done))
((string=?
"<< labels >>"
line)
(parse-label (get-line)))
((and (string-prefix? "<< " line)
(string-suffix? " >>" line))
(parse-layer line))
((string-prefix? "use " line)
(parse-use line))
(else
(syntax-error line "unknown line type"))
(define (parse-layer line)
(let ((layer-name
(intern (substring line 3 (fix:- (string-length line)
3)))))
(let loop ()
(let ((line (get-line)))
(if (string-prefix? "rect " line)
(begin
(apply
instantiate-box
(get-layer magic-file layer-name)
(map parse-integer
(burst-line line 4)))
(loop))
(parse-body line))))))
(define (parse-use line)
(let ((use (make-magic-use)))
(define (parse-array line)
(parse-optional line "array " parse-timestamp
(lambda (line)
(set-magic-use/array!
use
(apply make-magic-use-array
(map parse-integer
(burst-line line 6)))))))
(define (parse-timestamp line)
(parse-optional line "timestamp " parse-transform
(lambda (line)
(set-magic-use/timestamp!
use
(parse-time (string-tail line 10))))))
(define (parse-transform line)
(parse-required line "transform " parse-box
(lambda (line)
(set-magic-use/transform!
use
(apply make-magic-transform
(map parse-integer
(burst-line line 6)))))))
(define (parse-box line)
(parse-required line "box " continue
(lambda (line)
(set-magic-use/box!
use
(apply make-magic-box
(map parse-integer
(burst-line line 4)))))))
(define (continue line)
(append-use
magic-file
use)
(parse-body line))
(let ((strings (burst-line line #f)))
(if (not (and (pair? strings)
(or (null? (cdr strings))
(and (pair? (cdr strings))
(null? (cddr strings))))))
(syntax-error line "wrong number of arguments on
line"))
(set-magic-use/filename! use (car strings))
(set-magic-use/use-id!
use
(if (null? (cdr strings))
#f
(cadr strings))))
(parse-array (get-line))))
(define (parse-label line)
(let loop ((line line))
(if (string-prefix? "rlabel " line)
(let ((strings (burst-line line 7)))
(instantiate-label
magic-file
(intern (car strings))
(make-magic-box
(parse-integer (cadr strings))
(parse-integer (caddr strings))
(parse-integer (cadddr strings))
(parse-integer (car (cddddr strings))))
(translate-position
(parse-integer (cadr (cddddr strings))))
(caddr (cddddr strings)))
(loop (get-line)))
(parse-body line))))
(define (translate-position position)
(if (not (< -1 position
(vector-length magic-label-position-names)))
(syntax-error position "illegal label position"))
(vector-ref magic-label-position-names position))
(define (done)
magic-file)
(define read-line
(let ((eol (char-set #\newline)))
(lambda (port)
(let ((return (read-string eol port)))
(read-char port)
return)
(define (get-line)
(let ((line (read-line port)))
(if (eof-object? line)
(syntax-error line "premature end-of-file"))
line))
(define (syntax-error line message)
(error (string-append "Syntax error in magic file ("
message
line))
(define (parse-optional line prefix next-state parser)
(next-state
(if (string-prefix? prefix line)
(begin
(parser line)
(get-line))
line)))
(define (parse-required line prefix next-state parser)
(if (not (string-prefix? prefix line))
(syntax-error line (string-append "expected " prefix)))
(parser line)
(next-state (get-line)))
(define (burst-line line n)
(let ((end (string-length line)))
(let loop
((start (fix:+ (string-find-next-char line #\space) 1))
(segments '()))
(let ((space
(substring-find-next-char line start end #\space)))
(if space
(loop (fix:+ space 1)
(cons (substring line start space) segments))
(let ((segments
(reverse!
(cons (substring line start end) segments))))
(if (and n (not (fix:= n (length segments))))
(syntax-error line "incorrect burst number"))
segments))))))
(define (parse-time string)
(+ epoch (parse-integer string)))
(define (parse-integer string)
(let ((n (string->number string)))
(if (not (exact-integer? n))
(syntax-error string "not an integer"))
n))
(let ((line (get-line)))
(if (not (equal? "magic" line))
(syntax-error line "not a magic file")))
(parse-tech (get-line)))))))
(define (write-magic-file mf)
;; Note: this code assumes that the caller will provide an
;; appropriate "checkpaint" layer if needed.
(define (write-box box port)
(write (magic-box/xleft box) port)
(write-char #\space port)
(write (magic-box/ybot box) port)
(write-char #\space port)
(write (magic-box/xright box) port)
(write-char #\space port)
(write (magic-box/ytop box) port))
(define (translate-position position)
(let ((end (vector-length magic-label-position-names)))
(let loop ((i 0))
(if (fix:= i end)
(error "Illegal label position:" position))
(if (eq? position (vector-ref magic-label-position-names
i))
i
(loop (fix:+
i 1))))))
(let ((pathname (pathname-new-type (merge-pathnames (magicfile/filename mf)) "mag")))
(call-with-output-file pathname
(lambda (port)
(write-string "magic" port)
(newline port)
(if (magic-file/tech mf)
(begin
(write-string "tech " port)
(write-string (magic-file/tech mf) port)
(newline port)))
(if (magic-file/timestamp mf)
(begin
(write-string "timestamp " port)
(write (- (magic-file/timestamp mf) epoch) port)
(newline port)))
(for-each (lambda (layer)
(if (not (null? (magic-layer/boxes layer)))
(begin
(write-string "<< " port)
(write (magic-layer/layer-name layer) port)
(write-string " >>" port)
(newline port)
(for-each (lambda (box)
(write-string "rect " port)
(write-box box port)
(newline port))
(magic-layer/boxes layer)))))
(magic-file/layers mf))
(for-each (lambda (use)
(write-string "use " port)
(write-string
(->namestring
(let ((filename (magic-use/filename use)))
(if (pathname=? (directory-pathname "")
(directory-pathname filename))
(file-pathname filename)
(merge-pathnames
(file-pathname filename)
(relative-pathname (directory-pathname filename)
pathname)))))
port)
(if (magic-use/use-id use)
(begin
(write-char #\space port)
(write-string (magic-use/use-id use) port)))
(newline port)
(let ((array (magic-use/array use)))
(if array
(begin
(write-string "array " port)
(write (magic-use-array/xlo array) port)
(write-char #\space port)
(write (magic-use-array/xhi array) port)
(write-char #\space port)
(write (magic-use-array/xsep array) port)
(write-char #\space port)
(write (magic-use-array/ylo array) port)
(write-char #\space port)
(write (magic-use-array/yhi array) port)
(write-char #\space port)
(write (magic-use-array/ysep array) port)
(newline port))))
(if (magic-use/timestamp use)
(begin
(write-string "timestamp " port)
(write (- (magic-use/timestamp use) epoch) port)
(newline port)))
(let ((t (magic-use/transform use)))
(write-string "transform " port)
(write (magic-transform/a t) port)
(write-char #\space port)
(write (magic-transform/b t) port)
(write-char #\space port)
(write (magic-transform/c t) port)
(write-char #\space port)
(write (magic-transform/d t) port)
(write-char #\space port)
(write (magic-transform/e t) port)
(write-char #\space port)
(write (magic-transform/f t) port)
(newline port))
(write-string "box " port)
(write-box (magic-use/box use) port)
(newline port))
(magic-file/uses mf))
(if (not (null? (magic-file/labels mf)))
(begin
(write-string "<< labels >>" port)
(newline port)
(for-each (lambda (label)
(write-string "rlabel " port)
(write (magic-label/layer label) port)
(write-char #\space port)
(write-box (magic-label/box label) port)
(write-char #\space port)
(write (translate-position
(magic-label/position label))
port)
(write-char #\space port)
(write-string (magic-label/label-name label) port)
(newline port))
(magic-file/labels mf))))
(write-string "<< end >>" port)
(newline port)))))
(define (transform-magic-label t label)
(make-magic-label (magic-label/layer label)
(transform-magic-box t (magic-label/box label))
(magic-label/position label)
(magic-label/label-name label)))
(define (transform-magic-box t box)
(call-with-values
(lambda ()
(transform-magic-coordinates t
(magic-box/xleft box)
(magic-box/ybot box)))
(lambda (xl yl)
(call-with-values
(lambda ()
(transform-magic-coordinates t
(magic-box/xright box)
(magic-box/ytop box)))
(lambda (x2 y2)
(make-magic-box (min xl x2) (min yl y2) (max xl x2)
(max yl
y2)))))))
(define (transform-magic-coordinates t x y)
(values (+ (* x (magic-transform/a t))
(* y (magic-transform/b t))
(magic-transform/c t))
(+ (* x (magic-transform/d t))
(* y (magic-transform/e t))
(magic-transform/f t))))
(define (compose-magic-transforms . transforms)
(reduce
(lambda (f g)
;; Create a transform that is equivalent to
X))).
(LAMBDA (X) (G (F
(make-magic-transform (+ (* (magic-transform/a f) (magictransform/a g))
(* (magic-transform/d f) (magic-transform/b
g)))
(+ (* (magic-transform/b f) (magic-transform/a g))
(* (magic-transform/e f) (magic-transform/b
g)))
(+ (* (magic-transform/c
(* (magic-transform/f
(magic-transform/c g))
(+ (* (magic-transform/a
(* (magic-transform/d
f) (magic-transform/a g))
f) (magic-transform/b g))
f) (magic-transform/d g))
f) (magic-transform/e
g)))
(+ (* (magic-transform/b f) (magic-transform/d g))
(* (magic-transform/e f) (magic-transform/e
g)))
(+ (* (magic-transform/c f) (magic-transform/d g))
(* (magic-transform/f f) (magic-transform/e g))
(magic-transform/f g))))
magic-rotate-0
transforms))
(define magic-rotate-0
(make-magic-transform
1
0
0
0
1
0))
(define
(define
(define
(define
(define
magic-rotate-90
magic-rotate-180
magic-rotate-270
magic-reflect-x
magic-reflect-y
(make-magic-transform 0 1
(make-magic-transform -1 0
(make-magic-transform 0 -1
(make-magic-transform -1 0
(make-magic-transform 1 0
0
0 -1
0 -1
0
0
1 0
0 1
0
0
0 -1
0))
0))
0))
0))
0))
(define (magic-translate dx dy) (make-magic-transform 1 0 dx 0 1 dy))
(define (generate-identity-transform #!optional
magic-rotate-0)
new-use)
(define identity generate-identity-transform)
(define (generate-sideways-transform new-use)
(compose-magic-transforms
magic-reflect-x
(magic-translate (+ (* 2 (magic-box/xleft (magic-use/box new-use)))
(magic-use/width new-use))
0)))
(define sideways generate-sideways-transform)
(define (generate-upsidedown-transform new-use)
(compose-magic-transforms
magic-reflect-y
(magic-translate 0 (+ (* 2 (magic-box/ybot (magic-use/box new-use)))
(magic-use/height new-use)))))
(define upsidedown generate-upsidedown-transform)
(define (generate-upsideways-transform new-use)
(compose-magic-transforms
magic-rotate-180
(magic-translate (+ (* 2 (magic-box/xleft (magic-use/box new-use)))
(magic-use/width new-use))
(+ (* 2 (magic-box/ybot (magic-use/box new-use)))
(magic-use/height new-use)))))
(define upsideways generate-upsideways-transform)
(define (magic-file-bounding-box mf)
(let ((xleft #f)
(ybot #f)
(xright #f)
(ytop #f))
(let ((do-box
(lambda (box)
(if (not xleft)
(begin
(set! xleft (magic-box/xleft box))
(set! ybot (magic-box/ybot box))
(set! xright (magic-box/xright box))
(set! ytop (magic-box/ytop box)))
(begin
(if (fix:< (magic-box/xleft box) xleft)
(set! xleft (magic-box/xleft box)))
(if (fix:< (magic-box/ybot box) ybot)
(set! ybot (magic-box/ybot box)))
(if (fix:> (magic-box/xright box) xright)
(set! xright (magic-box/xright box)))
(if (fix:> (magic-box/ytop box) ytop)
(set! ytop (magic-box/ytop box))))))))
(for-each (lambda (layer)
(for-each (lambda (box)
(do-box box))
(magic-layer/boxes layer)))
(magic-file/layers mf))
(for-each (lambda (use)
(do-box (transform-magic-box (magic-use/transform use)
(magic-use/box use))))
(magic-file/uses mf))
(for-each (lambda (label)
(do-box (magic-label/box label)))
(magic-file/labels mf)))
(make-magic-box xleft ybot xright ytop)))
(define (instantiate-and-tile-horizontally magic-file
uses-to-instantiate
instance-names
transform-generators
xorg
xoffset
yorg)
(let ((new-instance)
(xpos xorg))
(for-each (lambda (use-to-instantiate instance-name transformgenerator)
(set! new-instance (instantiate-use
magic-file
use-to-instantiate
instance-name
transform-generator
xpos
yorg))
(set! xpos (+ xpos xoffset (magic-use/width new-instance)))
uses-to-instantiate
instance-names
transform-generators)))
magic-file
(define (instantiate-and-tile
uses-to-instantiate
instance-names
tile-direction ; horizontal or vertical
transform-generators
xorg
yorg
xoffsets
yoffsets)
(let ((new-instance)
(xpos xorg)
(ypos yorg))
(cond ((equal? tile-direction 'horizontal)
(for-each (lambda (use-to-instantiate instance-name transformgenerator xoffset yoffset)
(set! new-instance (instantiate-use
magic-file
use-to-instantiate
instance-name
transform-generator
xpos
(set! xpos
ypos))
(+ xoffset xpos
(set! ypos
(+ ypos yoffset))
(magic-use/width new-
instance)))
uses-to-instantiate
instance-names
transform-generators
xoffsets
yoffsets))
((equal? tile-direction 'vertical)
(for-each (lambda (use-to-instantiate instance-name transformgenerator xoffset yoffset)
(set! new-instance (instantiate-use
magic-file
use-to-instantiate
instance-name
transform-generator
xpos
(set! ypos
ypos))
(+ yoffset ypos
(set! xpos
(+ xpos xoffset))
(magic-use/height new-
instance)))
uses-to-instantiate
instance-names
transform-generators
xoffsets
yoffsets))
(else error "Invalid tile direction"))))
; creates a vertical array made up of the specified number of
; copies of a given cell
(define (instantiate-and-tile-vertical-array magic-file
use-to-instantiate
number-of-copies
xorg
yorg
xoffset
yoffset)
(define (rename->vector name size)
(make-initialized-vector
size
(lambda (i)
(string-append name "-" (number->string i)))))
(let ((new-instance)
(xpos xorg)
(ypos yorg)
(uses-to-instantiate (make-list number-of-copies use-toinstantiate))
(instance-names
(vector->list
(rename->vector use-to-instantiate number-of-copies)))
(transform-generators (apply append
(make-initialized-list
(/ number-of-copies 2)
(lambda (i) (list identity
upsidedown)))))
(xoffsets (make-list number-of-copies xoffset))
(yoffsets (make-list number-of-copies yoffset)))
(for-each (lambda (use-to-instantiate instance-name transformgenerator xoffset yoffset)
(set! new-instance (instantiate-use
magic-file
use-to-instantiate
instance-name
transform-generator
xpos
ypos))
(set! ypos (+ yoffset ypos (magic-use/height newinstance)))
(set! xpos (+ xpos xoffset))
uses-to-instantiate
instance-names
transform-generators
xoffsets
yoffsets)))
;Wiring stuff
;Given a vertical wiring channel index (0-<nchans-l>), returns an
infinitely
;tall box that covers that channel. This is assumed to be taking place
in
;the coordinates of the cell under construction, the origin of whose
;channels is assumed to be (0,0).
(define (vertical-channel-box channel-index)
(let ((xleft (* vertical-channel-width channel-index)))
(make-magic-box xleft
minus-infinity
(+ xleft vertical-channel-width)
infinity)))
;Given a horizontal wiring channel index (0-<nchans-l>), returns an
;infinitely wide box that covers that channel. This is assumed to be
;taking place in the coordinates of the cell under construction,
;the origin of whose channels is assumed to be (0,0).
(define (horizontal-channel-box channel-index)
(* horizontal-channel-height channel-index)))
(let ((ybot
(make-magic-box minus-infinity
ybot
infinity
(+ ybot horizontal-channel-height))))
(define (intersect-channel-boxes vertical-box horizontal-box)
(make-magic-box (magic-box/xleft vertical-box)
(magic-box/ybot horizontal-box)
(magic-box/xright vertical-box)
(magic-box/ytop horizontal-box)))
(define (channel-intersection-box vertical-channel-index
horizontal-channel-index)
(let ((vertical-channel-box
(vertical-channel-box vertical-channel-index))
(horizontal-channel-box
(horizontal-channel-box horizontal-channel-index)))
(intersect-channel-boxes vertical-channel-box horizontal-channelbox)))
(define (point->channel-indices x y)
(cons (quotient
x
vertical-channel-width)
(quotient
y
horizontal-channel-height)))
(define (channel-indices/vertical-channel-index channel-indices)
(car channel-indices))
(define (channel-indices/horizontal-channel-index channel-indices)
(cdr channel-indices))
#IThis routine creates a vertical strap on the specified layer in the
specified
vertical channel. It is assumed that the starting-horizontal-channel is
below the ending-horizontal-channel. The strap will extend from the
bottom edge
of the starting-horizontal-channel to the top edge of the
ending-horizontal-channel.l#
(define (instantiate-vertical-strap
mf layer width
vertical-channel-index
starting-horizontal-channel-index
horizontal-channel-index xoffset yoffset yoffsettop)
;These boxes are in the coordinate system of the top-level cell
(let ((vertical-channel-box
(vertical-channel-box vertical-channel-index))
(starting-horizontal-channel-box
(horizontal-channel-box starting-horizontal-channel-index))
(ending-horizontal-channel-box
(horizontal-channel-box horizontal-channel-index))
(half-width (/ width 2)))
(let ((starting-box (intersect-channel-boxes
vertical-channel-box
starting-horizontal-channel-box))
(ending-box (intersect-channel-boxes
vertical-channel-box
ending-horizontal-channel-box)))
(append-box (get-layer mf 'metal2)
(make-magic-box
(- (horizontal-center starting-box)
half-width (- xoffset))
(- (magic-box/ybot starting-box) yoffset)
(+ (horizontal-center ending-box)
half-width xoffset)
(+ (magic-box/ytop ending-box) yoffset yoffsettop)))
;add contacts
(append-box (get-layer mf 'm2contact)
(make-magic-box
(- (horizontal-center starting-box)
half-width (- xoffset))
(- (magic-box/ybot starting-box) yoffset half-width)
(+ (horizontal-center ending-box)
half-width xoffset)
(+ (- (magic-box/ybot starting-box) yoffset) halfwidth)))
(append-box (get-layer mf 'm2contact)
(make-magic-box
(- (horizontal-center starting-box)
half-width (- xoffset))
(- (+ (magic-box/ytop ending-box) yoffset yoffsettop)
half-width)
(+ (horizontal-center ending-box)
half-width xoffset)
(+ (magic-box/ytop ending-box) yoffset yoffsettop halfwidth)))
)))
#IThis routine creates a horizontal strap on the specified layer in the
specified horizontal channel. It is assumed that the starting-verticalchannel is left of the ending-vertical-channel. The strap will extend
from the left edge of the starting-vertical-channel to the right edge
of the ending-vertical-channel. #
(define (instantiate-horizontal-strap mf layer width starting-verticalchannel-index
ending-vertical-channel-index
horizontal-channel-index
yoffset)
(let ((horizontal-channel-box (horizontal-channel-box
horizontal-channel-index))
(starting-channel-box (vertical-channel-box
starting-vertical-channel-index))
(ending-channel-box (vertical-channel-box
ending-vertical-channel-index))
(half-width (/ width 2)))
(append-box
(get-layer mf layer)
(make-magic-box (magic-box/xleft starting-channel-box)
(+ yoffset
(- (vertical-center horizontal-channel-box)
half-width))
(magic-box/xright ending-channel-box)
(+ (vertical-center horizontal-channel-box)
half-width yoffset)))))
(define (instantiate-channel-intersection-label
mf
layer
vertical-channel-index
horizontal-channel-index
height
width
position
text)
(let ((channel-intersection-box
(channel-intersection-box vertical-channel-index horizontalchannel-index))
(instantiate-label mf
layer
(make-magic-box (- (horizontal-center
channel-intersection-box)
(/ width 2))
(-
(vertical-center
channel-intersection-box)
(/ height 2))
(+ (horizontal-center
channel-intersection-box)
(/ width 2))
(+ (vertical-center
channel-intersection-box)
(/ height 2)))
position
text)))
(define (instantiate-contact mf layer height width vertical-channelindex horizontal-channel-index xoffset yoffset)
(let ((contact-box (channel-intersection-box vertical-channel-index
horizontal-channel-index))
(half-height (/ height 2))
(half-width (/ width 2)))
(append-box (get-layer mf layer)
(make-magic-box
(- (+ xoffset (horizontal-center contact-box))
half-width)
(- (+ yoffset (vertical-center contact-box))
half-height)
(+ (+ xoffset (horizontal-center contact-box))
half-width)
(+ (+ yoffset (vertical-center contact-box))
half-height)))))
;Creates a vertical wire in metal2
(define (instantiate-vertical-wire-segment
mf
vertical-channel-index
starting-horizontal-channel-index
horizontal-channel-index)
;These boxes are in the coordinate system of the top-level cell
(let ((vertical-channel-box
(vertical-channel-box vertical-channel-index))
(starting-horizontal-channel-box
(horizontal-channel-box starting-horizontal-channel-index))
(ending-horizontal-channel-box
(horizontal-channel-box horizontal-channel-index))
(let ((starting-box (intersect-channel-boxes
vertical-channel-box
starting-horizontal-channel-box))
(ending-box (intersect-channel-boxes
vertical-channel-box
ending-horizontal-channel-box)))
(append-box (get-layer mf 'metal2)
(make-magic-box
(- (horizontal-center starting-box)
half-metal2-width)
(vertical-center starting-box)
(+ (horizontal-center ending-box)
half-metal2-width)
(vertical-center ending-box))))))
;Creates a horizontal wire in metal3, optionally with metal3 contacts
;at each end (the default is to supply the contacts if the optional
;arguments are omitted)
(define (instantiate-horizontal-wire-segment
mf
starting-vertical-channel-index
ending-vertical-channel-index
horizontal-channel-index #!optional starting-contact? endingcontact?)
;These boxes are in the coordinate system of the top-level cell
(let ((starting-vertical-channel-box
(vertical-channel-box starting-vertical-channel-index))
(ending-vertical-channel-box
(vertical-channel-box ending-vertical-channel-index))
(horizontal-channel-box
(horizontal-channel-box horizontal-channel-index))
(let ((starting-box (intersect-channel-boxes
starting-vertical-channel-box
horizontal-channel-box))
(ending-box (intersect-channel-boxes
ending-vertical-channel-box
horizontal-channel-box)))
(let ((starting-box-horizontal-center (horizontal-center
starting-box))
(starting-box-vertical-center (vertical-center starting-box))
(ending-box-horizontal-center (horizontal-center ending-box))
(layer)
(half-height))
(cond ((and (= (abs (- (magic-box/xleft starting-box) (magicbox/xleft ending-box)))
vertical-channel-width)
(or (default-object? starting-contact?) startingcontact?)
(or (default-object? ending-contact?) ending-contact?)
;The wire spans adjacent vertical channels, and both contacts have
;been requested. To avoid a bogus design rule error in Magic,
;just make one big metal3 contact, rather than two contacts and a short
So, substitute this contact fragment for the wire
;wire.
(set!
(set!
(else
(set!
(set!
layer 'm3contact)
half-height half-m3contact-height))
layer 'metal3)
half-height half-metal3-height)))
(append-box (get-layer mf layer)
(make-magic-box
starting-box-horizontal-center
(- starting-box-vertical-center
half-height)
ending-box-horizontal-center
(+ starting-box-vertical-center
half-height)))
;Now do the contacts at the ends of the wire
(if (or (default-object? starting-contact?) starting-contact?)
(instantiate-contact mf 'm3contact m3contact-height m3contactwidth starting-vertical-channel-index
horizontal-channel-index 0 0))
ending-contact?) ending-contact?)
(default-object?
(if (or
(instantiate-contact mf 'm3contact m3contact-height m3contactwidth ending-vertical-channel-index
horizontal-channel-index 0 0))
;Runs a wire from one label to another, using a vertical run from a
;starting label, a horizontal run
;in the specified horizontal channel, and then a
;vertical run to the ending label
(define (instantiate-wire mf starting-use-ids starting-label-name
ending-use-ids ending-label-name
horizontal-channel-index)
(define (label->box mf use-ids label-name)
(let ((transforms (list (identity)))
(use))
(for-each (lambda (use-id)
(set! use (find-use mf use-id))
(set! transforms
(cons (magic-use/transform use) transforms))
(set! mf (read-magic-file (magic-use/filename use)))
use-ids)
(transform-magic-box
(apply compose-magic-transforms transforms)
(magic-label/box (find-label mf label-name)))))
(if (not (or (pair? starting-use-ids) (null? starting-use-ids)))
(set! starting-use-ids (list starting-use-ids)))
(if (not (or (pair? ending-use-ids) (null? ending-use-ids)))
(set! ending-use-ids (list ending-use-ids)))
(let ((starting-label-box (label->box mf starting-use-ids
starting-label-name))
(ending-label-box (label->box mf ending-use-ids
ending-label-name)))
(let ((starting-channel-indices
(point->channel-indices
(magic-box/xleft
starting-label-box)
(magic-box/ybot
starting-label-box)))
(ending-channel-indices
(point->channel-indices
(magic-box/xleft
ending-label-box)
(magic-box/ybot
ending-label-box)))
;Hokay, we're finally ready to make the wire
(cond ((eq? (channel-indices/vertical-channel-index startingchannel-indices)
(channel-indices/vertical-channel-index endingchannel-indices))
;the wire only has a vertical segment
(instantiate-vertical-wire-segment
mf
(channel-indices/vertical-channel-index
starting-channel-indices)
(channel-indices/horizontal-channel-index
starting-channel-indices)
(channel-indices/horizontal-channel-index
ending-channel-indices))
(else
;Do the starting vertical wire
(instantiate-vertical-wire-segment
mf
(channel-indices/vertical-channel-index
starting-channel-indices)
(channel-indices/horizontal-channel-index
starting-channel-indices)
horizontal-channel-index)
;and while we're at it, do the ending
vertical wire
(instantiate-vertical-wire-segment
mf
(channel-indices/vertical-channel-index
ending-channel-indices)
(channel-indices/horizontal-channel-index
ending-channel-indices)
horizontal-channel-index)
;and now the horizontal wire
(instantiate-horizontal-wire-segment
mf
(channel-indices/vertical-channel-index
starting-channel-indices)
(channel-indices/vertical-channel-index
ending-channel-indices)
horizontal-channel-index
;Runs a wire from one use to another, using a vertical run from a
;starting label, a horizontal run in the specified horizontal channel,
;a vertical run in the specified vertical channel, a horizontal run
;in the other specified horizontal channel, and then a vertical run
;to the ending label
(define (instantiate-five-segment-wire mf starting-use-ids startinglabel-name
ending-use-ids ending-label-name
starting-horizontal-channel-index
ending-horizontal-channel-index
middle-vertical-channel-index)
(define (label->box mf use-ids label-name)
(let ((transforms '())
(use))
(for-each (lambda (use-id)
(set! use (find-use mf use-id))
(set! transforms
(cons (magic-use/transform use) transforms))
(set! mf (read-magic-file (magic-use/filename use)))
use-ids)
(transform-magic-box
(apply compose-magic-transforms transforms)
(magic-label/box (find-label mf label-name)))))
(if
(not (pair? starting-use-ids))
(set! starting-use-ids (list starting-use-ids)))
(if (not (pair? ending-use-ids))
(set! ending-use-ids (list ending-use-ids)))
(let ((starting-label-box (label->box mf starting-use-ids
starting-label-name))
(ending-label-box (label->box mf ending-use-ids
ending-label-name)))
(let ((starting-channel-indices
(point->channel-indices
(magic-box/xleft
starting-label-box)
(magic-box/ybot
starting-label-box)))
(ending-channel-indices
(point->channel-indices
(magic-box/xleft
ending-label-box)
(magic-box/ybot
ending-label-box)))
;Hokay, we're finally ready to make the wire
;Do the starting vertical wire
(instantiate-vertical-wire-segment
mf
(channel-indices/vertical-channel-index
starting-channel-indices)
(channel-indices/horizontal-channel-index
starting-channel-indices)
starting-horizontal-channel-index)
;and while we're at it, do the ending vertical wire
(instantiate-vertical-wire-segment
mf
(channel-indices/vertical-channel-index
ending-channel-indices)
(channel-indices/horizontal-channel-index
ending-channel-indices)
ending-horizontal-channel-index)
;and now the first horizontal wire
(instantiate-horizontal-wire-segment
mf
(channel-indices/vertical-channel-index
starting-channel-indices)
middle-vertical-channel-index
starting-horizontal-channel-index
;followed by the second horizontal wire
(instantiate-horizontal-wire-segment
mf
middle-vertical-channel-index
(channel-indices/vertical-channel-index
ending-channel-indices)
ending-horizontal-channel-index
;finally, add the connecting vertical wire
(instantiate-vertical-wire-segment
mf
middle-vertical-channel-index
starting-horizontal-channel-index
ending-horizontal-channel-index))))
#I This routine creates a horizontal wire on the specified layer in the
I#
It assumes you wire left to right
specified horizontal channel.
(define (instantiate-specified-horizontal-wire-segment
mf layer width
starting-vertical-channel-index
ending-vertical-channel-index
horizontal-channel-index)
;These boxes are in the coordinate system of the top-level cell
(let ((starting-vertical-channel-box
(vertical-channel-box starting-vertical-channel-index))
(ending-vertical-channel-box
(vertical-channel-box ending-vertical-channel-index))
(horizontal-channel-box
(horizontal-channel-box horizontal-channel-index))
(let
((starting-box (intersect-channel-boxes
starting-vertical-channel-box
horizontal-channel-box))
(ending-box (intersect-channel-boxes
ending-vertical-channel-box
horizontal-channel-box)))
(let ((starting-box-horizontal-center (horizontal-center
starting-box))
(starting-box-vertical-center (vertical-center starting-box))
(ending-box-horizontal-center (horizontal-center ending-box))
(half-height))
(append-box (get-layer mf layer)
(make-magic-box
(- starting-box-horizontal-center
(/ width 2))
(- starting-box-vertical-center
(/ width 2))
(+ ending-box-horizontal-center
(/ width 2))
(+ starting-box-vertical-center
(/ width 2))))
#I This routine creates a vertical wire on the specified layer in the
specified vertical channel. I#
(define (instantiate-specified-vertical-wire-segment
mf layer width
vertical-channel-index
starting-horizontal-channel-index
horizontal-channel-index)
;These boxes are in the coordinate system of the top-level cell
(let ((vertical-channel-box
(vertical-channel-box vertical-channel-index))
(starting-horizontal-channel-box
(horizontal-channel-box starting-horizontal-channel-index))
(ending-horizontal-channel-box
(horizontal-channel-box horizontal-channel-index))
(let ((starting-box (intersect-channel-boxes
vertical-channel-box
starting-horizontal-channel-box))
(ending-box (intersect-channel-boxes
vertical-channel-box
ending-horizontal-channel-box)))
(append-box (get-layer mf layer)
(make-magic-box
(- (horizontal-center starting-box)
(/ width 2))
(vertical-center starting-box)
(+ (horizontal-center ending-box)
(/ width 2))
(vertical-center ending-box))))))
#I This routine creates a wire on the specified layer in the specified
It uses instantiatehorizontal channel between two contacts.
horizontal-strap
and instantiate-vertical-strap and assumes that you are wiring from
left to
right I#
(define (instantiate-single-layer-wire mf starting-use-ids startinglabel-name
ending-use-ids ending-label-name
layer width
horizontal-channel-index)
(define (label->box mf use-ids label-name)
(let ((transforms (list (identity)))
(use))
(for-each (lambda (use-id)
(set! use (find-use mf use-id))
(set! transforms
(cons (magic-use/transform use) transforms))
(set! mf (read-magic-file (magic-use/filename use)))
use-ids)
(transform-magic-box
(apply compose-magic-transforms transforms)
(magic-label/box (find-label mf label-name)))))
(if
(not (or (pair? starting-use-ids) (null? starting-use-ids)))
(set! starting-use-ids (list starting-use-ids)))
(if (not (or (pair? ending-use-ids) (null? ending-use-ids)))
(set! ending-use-ids (list ending-use-ids)))
(let ((starting-label-box (label->box mf starting-use-ids
starting-label-name))
(ending-label-box (label->box mf ending-use-ids
ending-label-name)))
(let
((starting-channel-indices
(point->channel-indices
(magic-box/xleft
starting-label-box)
(magic-box/ybot
starting-label-box)))
(ending-channel-indices
(point->channel-indices
(magic-box/xleft
ending-label-box)
(magic-box/ybot
ending-label-box)))
;Hokay, we're finally ready to make the wire
(cond ((eq? (channel-indices/vertical-channel-index startingchannel-indices)
(channel-indices/vertical-channel-index endingchannel-indices))
;the wire only has a vertical segment
(instantiate-specified-vertical-wire-segment
mf
layer width
(channel-indices/vertical-channel-index
starting-channel-indices)
(channel-indices/horizontal-channel-index
starting-channel-indices)
(channel-indices/horizontal-channel-index
ending-channel-indices))
(else
;Do the starting vertical wire
(instantiate-specified-vertical-wire-segment
mf layer width
(channel-indices/vertical-channel-index
starting-channel-indices)
(channel-indices/horizontal-channel-index
starting-channel-indices)
horizontal-channel-index)
;and while we're at it, do the ending vertical wire
(instantiate-specified-vertical-wire-segment
mf layer width
(channel-indices/vertical-channel-index
ending-channel-indices)
(channel-indices/horizontal-channel-index
ending-channel-indices)
horizontal-channel-index)
;and now the horizontal wire
(instantiate-specified-horizontal-wire-segment
mf layer width
(channel-indices/vertical-channel-index
starting-channel-indices)
(channel-indices/vertical-channel-index
ending-channel-indices)
horizontal-channel-index
; routes a power grid on the specified magic file, consisting of the
number of
; specified vertical rails and horizontal rails of the specified width
; Also places substrate contacts
; This routine assumes that the topmost and bottommost rails are both
GND
(define (instantiate-power-grid mf horizontal-channel-span contactspacing vertical-rail-spacing vertical-rail-width)
(let* ((boundary-box (magic-file-bounding-box mf))
(left-boundary-channel (/ (vector-first boundary-box) 8))
(bottom-boundary-channel (/ (vector-second boundary-box) 10))
(right-boundary-channel (- (/ (vector-third boundary-box) 8) 1))
(top-boundary-channel (- (/ (vector-fourth boundary-box) 10) 1))
(horizontal-rail-index (+ top-boundary-channel 1))
(substrate-contact-type 'ndc)
(contact-type 'ndc)
(xposition (/ contact-spacing 2))
(rail-yoffset (* 5 (- horizontal-channel-span 1)))
(rail-xoffset 0)
(left-channel left-boundary-channel)
(right-channel right-boundary-channel)
(vertical-channel-number 0)
(vertical-channel-position vertical-rail-spacing)
(if (integer? right-boundary-channel)
#f
(set! right-boundary-channel (ceiling right-boundary-channel)))
(let instantiate-horizontal-rails ((horizontal-rail-index
horizontal-rail-index))
(cond
((eqv? substrate-contact-type 'ndc)
(set! left-channel (- left-boundary-channel 1))
(set! right-channel (+ right-boundary-channel (* 2 (+ horizontalchannel-span 1)))))
((eqv? substrate-contact-type 'pdc)
(set! left-channel (- left-boundary-channel (* 2 (+ horizontalchannel-span 1))))
(set! right-channel (+ right-boundary-channel 1))))
(if (> horizontal-rail-index (- bottom-boundary-channel
(+ 2 (* 3 horizontal-channel-span))))
(begin
(instantiate-horizontal-strap mf 'metall (+ (* 10 horizontalchannel-span) 8) left-channel right-channel horizontal-rail-index railyoffset)
(let instantiate-substrate-contacts ((xposition xposition))
(let ((channel-box (horizontal-channel-box horizontal-railindex)))
(if (< xposition (* (+ right-boundary-channel 1) 8))
(begin
(cond ((eqv? vertical-channel-number vertical-railspacing)
(if (eqv? substrate-contact-type 'ndc)
(set! contact-type substrate-contact-type)
(set! contact-type 'm2contact))
(set! vertical-channel-number (+ verticalchannel-number 1)))
((eqv? vertical-channel-number (+ vertical-railspacing 1))
(if (eqv? substrate-contact-type 'ndc)
(set! contact-type 'm2contact)
(set! contact-type substrate-contact-type))
(set! vertical-channel-number 0))
(else
(set! contact-type substrate-contact-type)
(set! vertical-channel-number (+ verticalchannel-number 1))))
(append-box (get-layer mf contact-type)
(make-magic-box
xposition
(- (+ rail-yoffset (vertical-center channelbox))
2)
(+ xposition 4)
(+ rail-yoffset
box)
2)))
(vertical-center channel-
(instantiate-substrate-contacts (+ xposition 4
contact-spacing))))))
(if (eqv? substrate-contact-type 'ndc)
(set! substrate-contact-type 'pdc)
(set! substrate-contact-type 'ndc))
(set! vertical-channel-number 0)
(instantiate-horizontal-rails (- horizontal-rail-index (+ 6
horizontal-channel-span))))
#f))
(let instantiate-vertical-rails ((vertical-channel-position
vertical-channel-position))
(if (< vertical-channel-position right-boundary-channel)
(begin
(instantiate-vertical-strap mf 'metal2 vertical-rail-width
vertical-channel-position 6 (- top-boundary-channel 6) 0 (- (* 5
horizontal-channel-span)) 0)
(instantiate-vertical-strap mf 'metal2 vertical-rail-width (+
vertical-channel-position 1) 0 top-boundary-channel 0 (* 5 horizontalchannel-span) 0)
(instantiate-vertical-rails (+ vertical-channel-position 2
vertical-rail-spacing)))
#f))
(let instantiate-vertical-boundary ((horizontal-rail-index
horizontal-rail-index))
(if (> horizontal-rail-index 18)
(begin
(instantiate-vertical-strap mf 'metal2 (+ 8 (* 10
horizontal-channel-span)) -1 (+ horizontal-rail-index 1) (- horizontal1 (* 2 (+ 6 horizontal-channel-span))) (- (+ 2 (/ (* 10
rail-index
horizontal-channel-span) 2)))(* 5 horizontal-channel-span) 0)
(instantiate-vertical-strap mf 'metal2 (+ 8 (* 10
(+ horizontalhorizontal-channel-span)) (+ 2 right-boundary-channel)
rail-index 1) (- horizontal-rail-index 1 (* 2 (+ 6 horizontal-channelspan))) (+ 6 (* 15 horizontal-channel-span)) (* 5 horizontal-channelspan) 0)
(if (> horizontal-rail-index 11)
(begin
(instantiate-vertical-strap mf 'metal2 (+ 8 (* 10
horizontal-channel-span)) -2 (- horizontal-rail-index 6 horizontalchannel-span) (- horizontal-rail-index (* 3 (+ 6 horizontal-channelspan))) (- (+ 6 (* 15 horizontal-channel-span)))(- (* 5 horizontalchannel-span)) 0)
(instantiate-vertical-strap mf 'metal2 (+ 8 (* 10
horizontal-channel-span)) (+ 1 right-boundary-channel) (- horizontal(* 3 (+
rail-index 6 horizontal-channel-span) (- horizontal-rail-index
6 horizontal-channel-span)))(+ 2 (/ (* 10 horizontal-channel-span) 2))
(- (* 5 horizontal-channel-span)) 0))
#f)
(instantiate-vertical-boundary (- horizontal-rail-index (* 2
(+ 6 horizontal-channel-span)))))
#f))
(instantiate-vertical-strap mf 'metal2 (+ 8 (* 10 horizontalchannel-span)) -2 6 (- top-boundary-channel 6) (- (+ 6 (* 15
horizontal-channel-span)))(- (* 5 horizontal-channel-span)) 0)
(instantiate-vertical-strap mf 'metal2 (+ 8 (* 10 horizontalchannel-span)) -1 0 top-boundary-channel (- (+ 2 (/ (* 10 horizontalchannel-span) 2)))(* 5 horizontal-channel-span) 0)
(instantiate-vertical-strap mf 'metal2 (+ 8 (* 10 horizontalchannel-span)) (+ 1 right-boundary-channel) 6 (- top-boundary-channel
6) (+ 2 (/ (* 10 horizontal-channel-span) 2)) (- (* 5 horizontalchannel-span)) 0)
(instantiate-vertical-strap mf 'metal2 (+ 8 (* 10 horizontalchannel-span)) (+ 2 right-boundary-channel) 0 top-boundary-channel
6 (* 15 horizontal-channel-span)) (* 5 horizontal-channel-span) 0)
))
(+
A.2 counter.scm
; 32-bit counter example to test out magic.scm
(declare (usual-integrations))
(define row-spacing 1)
(define empty-space (* 10 row-spacing))
; mux
(define (tgmux_gnd)
(let ((new-file (make-magic-file
'filename "tgmux_gnd"
'tech "scmos"))
(instantiate-and-tile
new-file
'("tgmux")
'("tgmux-O")
'horizontal
(list identity)
0
0
'(0)
'(0))
(instantiate-vertical-strap new-file
'metal2
4
1
0
2
0
-2
-3)
(write-magic-file new-file)))
(define (mux_32)
(let ((new-file (make-magic-file
'filename "mux_32"
'tech "scmos"))
(instantiate-and-tile-vertical-array
new-file
"tgmux_gnd"
32
0
0
0
empty-space)
(instantiate-wire new-file
'("tgmux gnd-O")
"S"
'("tgmux_gnd-31")
"S "
3)
(instantiate-wire new-file
'("tgmuxgnd-O")
"-S"
'("tgmux_gnd-31")
"- S"I
3)
(write-magic-file new-file)))
register
(define (reg_bit)
(let ((new-file (make-magic-file
'filename "reg bit"
'tech "scmos"))
(instantiate-and-tile
new-file
'("tsinv"
"inv_l"
"inv_weak" "tg"
"inv_l"
"inv_weakbig_contacts"
"inv_2")
"inv_1-0" "invweak-0" "tg-O" "invl-1" "inv_weak-l"
'("tsinv-0"
"inv_2-0")
'horizontal
(list identity
identity
identity
identity
identity
sideways
identity)
0
0
'(0 0 0 0 0 -8 0)
'(0 0 0 0 0 0 0)
(instantiate-wire new-file
'("tsinv-0")
"Z
"
'("inv_l-0")
"A"
1)
(instantiate-wire new-file
'("inv_l-0")
"Z"
"D1 "
3)
(instantiate-single-layer-wire new-file
'("inv_l1-0")
S1Z"
'("invweak- 0")
"A"
'metall
4
2)
(instantiate-wire new-file
'("inv_weak-O")
" Z"
'("inv_l-0")
"A"
1)
(instantiate-wire new-file
'("tsinv-0")
" EN"
' ("tg-0")
"SO"
0)
(instantiate-wire new-file
'("tsinv-0")
" -EN"
' ("tg-0")
"S1"
4)
(instantiate-wire new-file
' ("tg-0")
'("inv_l-1")
"A"
1)
(instantiate-wire new-file
' ("tg-0")
'("inv_weak-1")
" Z
"
1)
(instantiate-wire new-file
'("inv_-1")
'("inv_weak-l")
"A"
0)
(write-magic-file new-file)))
(define (basic_reg)
(let ((new-file (make-magic-file
'filename "basic_reg"
'tech "scmos"))
(instantiate-and-tile-vertical-array
new-file
"regbit"
32
0
0
0
(* 10 row-spacing))
(write-magic-file new-file)))
;inverter array
(define (inv_1_array)
(let ((new-file (make-magic-file
'filename "inv 1 array"
'tech "scmos"))
(instantiate-and-tile-vertical-array
new-file
"inv_1"
32
0
0
0
(* 10 row-spacing))
(write-magic-file new-file)))
; counter logic
(define (nor_nand_tree_triple)
(let ((new-file (make-magic-file
'filename "nor_nandtree_triple"
'tech "scmos"))
(instantiate-and-tile
new-file
'("nor2" "nand2" "nor2")
'("nor2-0" "nand2-0" "nor2-1")
'vertical
(list identity
upsidedown
identity)
0
0
'(0 0 0)
(list empty-space empty-space empty-space))
(instantiate-wire new-file
'("nor2-0")
" Z" I
'("nand2-0")
"A"
3)
(instantiate-wire new-file
'("nor2-1")
" Z"
("nand2-0")
"B"
12)
(write-magic-file new-file)))
(define (nor_nand_nor_tree)
(let ((new-file (make-magic-file
'filename "nornandnortree"
'tech "scmos"))
(instantiate-and-tile
new-file
'("nor_nand_treetriple" "nor2" "nor_nand_treetriple")
'("nor_nand_treetriple-0" "nor2-0" "nor_nand_tree_triple-l")
'vertical
(list identity
upsidedown
identity)
0
0
,(0 0 0)
(list empty-space empty-space empty-space))
(instantiate-five-segment-wire new-file
'("nor_nand_tree_triple-0"
"nand2-0")
" Z 11
'("nor2-0")
"A"
11
22
3)
(instantiate-five-segment-wire new-file
'("nornand_tree_triple-l"
"nand2-0")
'("nor2-0")
"B"
36
25
3)
(write-magic-file new-file)))
(define (nor_nand_nor_nandtree)
(let ((new-file (make-magic-file
'filename "nor nand nor nand tree"
'tech "scmos"))
(instantiate-and-tile
new-file
'("nor_nand_nor_tree" "nand2" "nor_nand_nor_tree")
'("nornand_nor_tree-0" "nand2-0" "nor_nand_nor_tree-l")
'vertical
(list identity
upsidedown
identity)
0
0
'(0 0 0)
(list empty-space empty-space empty-space))
(instantiate-five-segment-wire new-file
'("nor_nand_nor_tree-0" "nor2-0")
"Z"
'("nand2-0")
"A"
23
51
4)
(instantiate-five-segment-wire new-file
'("nor_nand_nor_tree-i" "nor2-0")
" Z"
'("nand2-0")
"B"
79
53
4)
(write-magic-file new-file)))
(define (inv2and4)
(let ((new-file (make-magic-file
'filename "inv_2and4"
'tech "scmos"))
(instantiate-and-tile-horizontally
new-file
'("inv_2" "inv_4")
'("inv_2-0" "inv4-0")
(list identity
identity)
0
0
0
(instantiate-single-layer-wire new-file
'("inv_2-0")
"! Z"
'("inv_4-0")
"A"
'metall
4
2)
(write-magic-file new-file)))
(define (counter_logic)
(let ((new-file (make-magic-file
'filename "counter_logic"
'tech "scmos"))
(instantiate-and-tile
new-file
'("nor_nand_nor_nand_tree" "nor2" "inv_2and4"
"nornand nor nand tree")
'("nor_nand_nor nand_tree-0" "nor2-0" "inv 2and4-0"
"nor_nand_nor_nand_tree-l")
'vertical
(list identity
upsidedown
identity
upsidedown)
0
0
,(0 0 0 0)
(list empty-space empty-space empty-space empty-space))
(instantiate-five-segment-wire new-file
'("nor nand_nor_nand_tree-0"
"nand2-0")
" Z 11
'("nor2-0")
"A"
54
107
5)
(instantiate-five-segment-wire new-file
'("nor_nand_nor_nand_tree-l"
"nand2-0")
" Z 11
'("nor2-0")
"B"
168
109
5)
(instantiate-wire new-file
'("nor2-0")
"'Z"
'("inv_2and4-0" "inv_2-0")
"A"
112)
(write-magic-file new-file)))
(define (counter)
(let ((new-file (make-magic-file
'filename "counter"
'tech "scmos"))
(instantiate-and-tile
new-file
'("mux_32" "addthirtytwo" "basic_reg" "invl_array"
"counter_logic")
'("mux_32-0" "addthirtytwo-O" "basic_reg-0" "inv 1_array-O"
"counter_logic-O")
'horizontal
(list identity
identity
identity
identity
identity)
0
0
'(0 16 0 0 0)
(0 0 0 0 0)
;adder inputs (1)
;bitO
(instantiate-vertical-strap new-file
'metal2
4
10
2
5
0
-5
-1)
;bit2
(instantiate-vertical-strap new-file
'metal2
;bit4
(instantiate-vertical-strap new-file
'metal2
1)
;bit6
(instantiate-vertical-strap new-file
'metal2
4
10
42
44
0
-6
1)
;bit8
(instantiate-vertical-strap
'metal2
4
10
56
58
0
-6
1)
;bitlO
(instantiate-vertical-strap
'metal2
4
10
70
72
0
-6
1)
;bitl2
(instantiate-vertical-strap
'metal2
4
10
84
86
0
-6
1)
;bitl4
(instantiate-vertical-strap
'metal2
4
10
98
100
0
-6
new-file
new-file
new-file
new-file
1)
;bitl6
(instantiate-vertical-strap new-file
'metal2
4
10
112
114
0
-6
1)
;bitl8
(instantiate-vertical-strap
'metal2
4
10
126
128
0
-6
1)
;bit20
(instantiate-vertical-strap
'metal2
4
10
140
142
0
-6
1)
;bit22
(instantiate-vertical-strap
'metal2
4
10
154
156
0
-6
1)
;bit24
(instantiate-vertical-strap
'metal2
4
10
168
170
new-file
new-file
new-file
new-file
;bit26
(instantiate-vertical-strap new-file
'metal2
4
10
182
184
0
-6
1)
;bit28
(instantiate-vertical-strap new-file
'metal2
4
10
196
198
;bit30
(instantiate-vertical-strap new-file
'metal2
4
10
210
212
0
-6
1)
;bitl
(instantiate-vertical-strap new-file
'metal2
4
12
10
12
0
-5
-1)
;bit3
(instantiate-vertical-strap new-file
'metal2
4
12
24
26
0
-5
-1
;bit 5
(instantiate-vertical-strap new-file
'metal2
4
12
38
40
0
-5
-1)
;bit 7
(instantiate-vertical-strap new-file
'metal2
4
12
52
54
0
-5
-1)
;bit9
(instantiate-vertical-strap new-file
'metal2
4
12
66
68
0
-5
-1)
;bitll
(instantiate-vertical-strap
'metal2
4
12
80
82
0
-5
-1)
;bitl3
(instantiate-vertical-strap
'metal2
4
12
94
96
0
-5
-1)
;bitl5
(instantiate-vertical-strap
'metal2
4
12
108
110
0
-5
-1)
;bitl7
(instantiate-vertical-strap
'metal2
4
12
122
124
0
-5
-1)
;bitl9
(instantiate-vertical-strap
'metal2
4
12
136
138
0
-5
-1)
new-file
new-file
new-file
new-file
new-file
;bit21
(instantiate-vertical-strap new-file
'metal2
4
12
150
152
0
-5
-1)
;bit23
(instantiate-vertical-strap new-file
'metal2
12
164
166
0
-5
-1)
;bit 25
(instantiate-vertical-strap
'metal2
4
12
178
180
0
-5
-1)
;bit 27
(instantiate-vertical-strap
'metal2
4
12
192
194
0
-5
-1)
;bit29
(instantiate-vertical-strap
'metal2
4
12
206
208
0
-5
-1)
;bit31
(instantiate-vertical-strap
'metal2
4
12
220
222
new-file
new-file
new-file
new-file
0
-5
-1)
; output of mux to adder
(instantiate-wire new-file
'("mux_32-0"
"tgmuxgnd-0")
'("addthirtytwo-O" "carrythirtytwo-0" "carrysixteen0" "carryeight-0" "carryfour-0" "carrytwo-O" "gp-0" "and2-0" "nand2-0")
"A"
3)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-l")
ny"
'("addthirtytwo-O" "carrythirtytwo-0" "carrysixteen0" "carryeight-0" "carryfour-0" "carrytwo-0" "carryone-0" "gp-0" "and20" "nand2-0")
"A"
9)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-2")
'("addthirtytwo-0" "carrythirtytwo-0" "carrysixteen0" "carryeight-0" "carryfour-O" "carrytwobb-0" "carrytwo-0" "gp-0"
"and2-0" "nand2-0")
" A"
17)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-3")
'("addthirtytwo-0" "carrythirtytwo-0" "carrysixteen0" "carryeight-0" "carryfour-0" "carrytwobb-0" "carrytwo-0" "carryone0" "gp-0" "and2-0" "nand2-0")
"A"
23)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-4")
'("addthirtytwo-0" "carrythirtytwo-0" "carrysixteen0" "carryeight-0" "carryeight_tophalf-0" "carryfour-0" "carrytwo-0"
"gp-0" "and2-0" "nand2-0")
"A"
31)
(instantiate-wire new-file
'("mux_32-0"
"tgmuxgnd-5")
'("addthirtytwo-0" "carrythirtytwo-0" "carrysixteen0" "carryeight-0" "carryeight_tophalf-0" "carryfour-0" "carrytwo-0"
"carryone-0" "gp-0" "and2-0" "nand2-0")
"A"
37)
(instantiate-wire new-file
'("mux_32-0"
"tgmux gnd-6")
'("addthirtytwo-O" "carrythirtytwo-O" "carrysixteen0" "carryeight-0" "carryeight_tophalf-0" "carryfour-0" "carrytwobb-0"
"carrytwo-O" "gp-0" "and2-0" "nand2-0")
"A"
45)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-7")
Ily II
'("addthirtytwo-0" "carrythirtytwo-O" "carrysixteen0" "carryeight-0" "carryeighttophalf-0" "carryfour-0" "carrytwobb-0"
"carrytwo-0" "carryone-0" "gp-0" "and2-0" "nand2-0")
"A"
51)
(instantiate-wire new-file
'("mux_32-0"
"tgmuxgnd-8")
'("addthirtytwo-O" "carrythirtytwo-0" "carrysixteen0" "carrysixteen_tophalf-0" "carryeight- 0" "carryfour-0" "carrytwo-0"
"gp-O" "and2-0" "nand2-0")
"A"
59)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-9")
'("addthirtytwo-0" "carrythirtytwo-0" "carrysixteen0" "carrysixteen_tophalf-0" "carryeight-0" "carryfour-0" "carrytwo-0"
"carryone-0" "gp-0" "and2-0" "nand2-0")
"A"
65)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-10")
'("addthirtytwo-0" "carrythirtytwo-0" "carrysixteen0" "carrysixteen_tophalf-0" "carryeight-0" "carryfour-0" "carrytwobb-0"
"carrytwo-0" "gp-0" "and2-0" "nand2-0")
"A"
73)
(instantiate-wire new-file
'("mux_32-0"
"tgmuxgnd-ll")
'("addthirtytwo-0" "carrythirtytwo-0" "carrysixteen0" "carrysixteen_tophalf-0" "carryeight-0" "carryfour-0" "carrytwobb-0"
"carrytwo-0" "carryone-0" "gp-0" "and2-0" "nand2-0")
"A"
79)
100
(instantiate-wire new-file
'("mux_32-0"
,Y,,
"tgmux_gnd-12")
'("addthirtytwo-O" "carrythirtytwo-0" "carrysixteen0" "carrysixteen_tophalf-0" "carryeight- 0" "carryeight_tophalf-0"
"carryfour-0" "carrytwo-0" "gp-0" "and2-0" "nand2-0")
"A"
87)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-13")
'("addthirtytwo-O" "carrythirtytwo-0" "carrysixteen0" "carrysixteen_tophalf-0" "carryeight-0" "carryeight_tophalf-0"
"carryfour-0" "carrytwo-0" "carryone-0" "gp-0" "and2-0" "nand2-0")
"A"
93)
(instantiate-wire new-file
'("mux32-0" "tgmux_gnd-14")
'("addthirtytwo-0" "carrythirtytwo-O" "carrysixteen0" "carrysixteen_tophalf-0" "carryeight-0" "carryeight_tophalf-0"
"carryfour-0" "carrytwobb-0" "carrytwo-0" "gp-0" "and2-0" "nand2-0")
"A"
101)
(instantiate-wire new-file
'("mux_32-0"
"tgmuxgnd-15")
'("addthirtytwo-0" "carrythirtytwo-0" "carrysixteen0" "carrysixteen_tophalf-0" "carryeight-0" "carryeight_tophalf-0"
"carryfour-0" "carrytwobb-0" "carrytwo-0" "carryone-0" "gp-0" "and2-0"
"nand2-0")
"A"
107)
(instantiate-wire new-file
'("mux_32-0"
"tgmuxgnd-16")
'("addthirtytwo-0" "carrythirtytwo-0"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carryeight-0" "carryfour0" "carrytwo-0" "gp-O" "and2-0" "nand2-0")
"A"
115)
(instantiate-wire new-file
'("mux_32-0"
"tgmuxgnd-17")
'("addthirtytwo-0" "carrythirtytwo-0"
"carrythirtytwotophalf-0" "carrysixteen-0" "carryeight-0" "carryfour0" "carrytwo-0" "carryone-0" "gp-0" "and2-0" "nand2-0")
"A"
121)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-18")
'("addthirtytwo-O" "carrythirtytwo-O"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carryeight-0" "carryfour0" "carrytwobb-0" "carrytwo-0" "gp-0" "and2-0" "nand2-0")
"A"
129)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-19")
'("addthirtytwo-0" "carrythirtytwo-0"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carryeight-0" "carryfour0" "carrytwobb-0" "carrytwo-0" "carryone-O" "gp-0" "and2-0" "nand2-0")
"A"
135)
(instantiate-wire new-file
'("mux_32-0"
"tgmuxgnd-20")
'("addthirtytwo-0" "carrythirtytwo-0"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carryeight-O"
"carryeight_tophalf-0" "carryfour-0" "carrytwo-O" "gp-0" "and2-0"
"nand2 - 0")
"A"
143)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-21")
'("addthirtytwo-0" "carrythirtytwo-0"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carryeight-0"
"carryeight_tophalf-0" "carryfour-0" "carrytwo-0" "carryone-0" "gp-0"
"and2-0" "nand2-0")
"A"
149)
(instantiate-wire new-file
'("mux_32-0"
"tgmuxgnd-22")
'("addthirtytwo-O" "carrythirtytwo-O"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carryeight-0"
"carryeight_tophalf-0" "carryfour-0" "carrytwobb-0" "carrytwo-0" "gp-0"
"and2-0" "nand2 - 0")
"A"
157)
(instantiate-wire new-file
'("mux32-0" "tgmuxgnd-23")
'("addthirtytwo-0" "carrythirtytwo-0"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carryeight-0"
"carryeight_tophalf-0" "carryfour-0" "carrytwobb-0" "carrytwo-0"
"carryone-0" "gp-0" "and2-0" "nand2-0")
"A"
163)
102
(instantiate-wire new-file
'("mux_32-0"
"tgmuxgnd-24")
'("addthirtytwo-O" "carrythirtytwo-O"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carrysixteen_tophalf-O"
"carryeight-O" "carryfour-O" "carrytwo-O" "gp-O" "and2-0" "nand2-0")
"A"
171)
(instantiate-wire new-file
'("mux_32-0" "tgmux_gnd-25")
Ilyll
'("addthirtytwo-O" "carrythirtytwo-O"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carrysixteen_tophalf-O"
"carryeight-0" "carryfour-O" "carrytwo-O" "carryone-0" "gp-O" "and2-0"
"nand2-0")
"A"
177)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-26")
'("addthirtytwo-O" "carrythirtytwo-O"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carrysixteen_tophalf-O"
"carryeight-0" "carryfour-O" "carrytwobb-0" "carrytwo-O" "gp-0" "and20" "nand2-0")
"A"
185)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-27")
'("addthirtytwo-0" "carrythirtytwo-O"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carrysixteen_tophalf-0"
"carryeight-0" "carryfour-0" "carrytwobb-0" "carrytwo-0" "carryone-0"
"gp-0" "and2-0" "nand2-0")
"A"
191)
(instantiate-wire new-file
'("mux_32-0"
"tgmuxgnd-28")
'("addthirtytwo-0" "carrythirtytwo-0"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carrysixteen_tophalf-0"
"carryeight-0" "carryeight_tophalf-0" "carryfour-0" "carrytwo-0" "gp-0"
"and2-0" "nand2-0")
"A"
199)
(instantiate-wire new-file
'("mux32-0" "tgmuxgnd-29")
'("addthirtytwo-O" "carrythirtytwo-0"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carrysixteen_tophalf-0"
103
"carryeight-0" "carryeight_tophalf-0" "carryfour-0
"carryone-0" "gp-O" "and2-0" "nand2-0")
"A"
205)
(instantiate-wire new-file
'("mux_32-0"
"carrytwo-0"
"tgmux_gnd-30")
'("addthirtytwo-0" "carrythirtytwo-0"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carrysixteen_tophalf-0"
"carryeight-0" "carryeight_tophalf-0" "carryfour-0" "carrytwobb-0"
"carrytwo-O" "gp-0" "and2-0" "nand2-0")
"A"
213)
(instantiate-wire new-file
'("mux_32-0"
"tgmux_gnd-31")
'("addthirtytwo-0" "carrythirtytwo-0"
"carrythirtytwo_tophalf-0" "carrysixteen-0" "carrysixteen_tophalf-0"
"carryeight-0" "carryeight_tophalf-0" "carryfour-0" "carrytwobb-0"
"carrytwo-0" "carryone-0" "gp-0" "and2-0" "nand2-0")
"A"
219)
; adder outputs to register
(instantiate-wire new-file
'("addthirtytwo-0" "carrythirtytwo-0" "carrysixteen0" "carryeight-0" "carryfour-0" "carrytwo-0" "gp-0" "and2-0" "inv_l-0")
" Z"
'("basic_reg-0"
"A"
4)
"reg_bit-0" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-0"
"xnorquad-0" "xnor-0")
"xnor_array_with_inv-0"
" Z 11
'("basic_reg-0"
"A"
8)
"regbit-l" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-0"
"xnor_quad-0" "xnor-l")
"xnor_array_with_inv-0"
"! Z"
'("basic_reg-0" "reg_bit-2" "tsinv-0")
"A"
15)
(instantiate-wire new-file
'("addthirtytwo-0" "xnor_array_with_inv-0"
"xnorquad-0" "xnor-2")
'("basic_reg-0"
"A"
22)
"regbit-3" "tsinv-0")
104
(instantiate-wire new-file
'("addthirtytwo-O" "xnor_array_with_inv-0"
"xnorquad-O" "xnor-3")
ofZ"
'("basic_reg-0" "regbit-4" "tsinv-0")
"A"
29)
(instantiate-wire new-file
'("addthirtytwo-O" "xnor_arraywith_inv-0"
"xnorquad-1" "xnor-3")
l Z"
'("basic_reg-0" "regbit-5" "tsinv-0")
"A"
36)
(instantiate-wire new-file
'("addthirtytwo-O"
"xnorquad-l" "xnor-2")
"xnor_array_with_inv-0"
"1Z"
'("basic_reg-0"
"A"
43)
"reg_bit-6" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-O"
"xnorquad-l" "xnor-l")
"xnor_array_with_inv-0"
"1Z"
'("basic_reg-0"
"A"
50)
"reg_bit-7" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-0"
"xnorquad-l" "xnor-0")
'("basic_reg-0"
"A"
57)
"xnor_arraywith_inv-0"
"regbit-8" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-O"
"xnorquad-2" "xnor-O")
"xnor_array with_inv-0"
"| Z"
'("basic_reg-0"
"A"
64)
"regbit-9" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-O"
"xnorquad-2" "xnor-l")
'("basic_reg-0"
"A"
71)
"xnor_array_with_inv-0"
"reg_bit-10" "tsinv-0")
105
(instantiate-wire new-file
'("addthirtytwo-O"
"xnor_quad-2" "xnor-2")
" Z
"
'("basic_reg-0"
"A"
78)
"reg_bit-ll"
(instantiate-wire new-file
'("addthirtytwo-0"
"xnor_quad-2" "xnor-3")
" Z
"xnor_array with_inv-0"
"
'("basic_reg-0"
"A"
92)
"regbit-13" "tsinv-O")
(instantiate-wire new-file
'("addthirtytwo-O"
"xnor_quad-3" "xnor-2")
"xnor_array_with_inv-0"
"
'("basic_reg-0"
"A"
99)
"regbit-14" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-O"
"xnor_quad-3" "xnor-l")
" Z
"xnor_array_with_inv-0"
"reg_bit-12" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-O"
"xnor_quad-3" "xnor-3")
" Z
"tsinv-O")
"
'("basic_reg-0"
"A"
85)
" Z
"xnorarraywith_inv-0"
"xnor_array_with_inv-0"
"
'("basic_reg-0"
"A"
106)
"reg_bit-15" "tsinv-O")
(instantiate-wire new-file
'("addthirtytwo-0"
"xnor_quad-3" "xnor-O")
"xnor_array with_inv-0"
" Z"
'("basic_reg-0"
"A"
113)
"reg_bit-16" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-0"
"xnorquad-4" "xnor-0")
"xnor_array_with_inv-0"
" Z"
'("basic_reg-0"
"A"
120)
"regbit-17" "tsinv-0")
106
(instantiate-wire new-file
'("addthirtytwo-O"
"xnorquad-4" "xnor-l")
"xnor_array_with_inv-0"
"Z "
'("basic_reg-0"
"A"
127)
"reg_bit-18" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-O"
"xnorquad-4" "xnor-2")
"xnor_array_with_inv-0"
" Z"
'("basic_reg-0"
"A"
134)
"reg_bit-19" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-O"
"xnor_quad-4" "xnor-3")
"xnor_array_with_inv-0"
" Z"
'("basic_reg-0" "reg_bit-20" "tsinv-0")
"A"
141)
(instantiate-wire new-file
'("addthirtytwo-O"
"xnor_quad-5" "xnor-3")
"xnor_array_with_inv-0"
'("basic_reg-0" "reg_bit-21" "tsinv-0")
"A"
148)
(instantiate-wire new-file
'("addthirtytwo-O"
"xnor_quad-5" "xnor-2")
"xnor_array_with_inv-0"
"
" Z
'("basic_reg-0"
"A"
155)
"reg_bit-22" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-O"
"xnor_quad-5" "xnor-l")
"xnorarraywith_inv-0"
"
" Z
'("basic_reg-0"
"A"
162)
"regbit-23" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-O"
"xnor_quad-5" "xnor-O")
"xnorarraywith_inv-0"
"
" Z
'("basic_reg-0"
"A"
169)
"reg bit-24" "tsinv-0")
107
(instantiate-wire new-file
'("addthirtytwo-O"
"xnorquad-6" "xnor-0")
"xnor_array_with_inv-0"
" Z"
'("basic_reg-0"
"A"
176)
"reg_bit-25" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-0"
"xnor_quad-6" "xnor-l")
"xnor_arraywith_inv-0"
It Z"
'("basic_reg-0" "reg_bit-26" "tsinv-0")
"A"
183)
(instantiate-wire new-file
'("addthirtytwo-O"
"xnor quad-6" "xnor-2")
"xnor_array_with_inv-0"
ITZ"
'("basic_reg-0" "reg_bit-27" "tsinv-0")
"A"
190)
(instantiate-wire new-file
'("addthirtytwo-0"
"xnor_quad-6" "xnor-3")
"xnor_array_with_inv-0"
", Z"
'("basic_reg-0"
"A"
197)
"reg_bit-28" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-O"
"xnor_arraywith_inv-0" "xnor-0")
"1Z"
'("basic_reg-0"
"A"
204)
"regbit-29" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-0"
"xnor_array_with_inv-0" "xnor-l")
" Z"
'("basic_reg-0"
"A"
211)
"reg_bit-30" "tsinv-0")
(instantiate-wire new-file
'("addthirtytwo-0"
"xnor_array_with_inv-0" "xnor-2")
"! Z"
'("basic reg-0" "reg_bit-31" "tsinv-0")
"A"
218)
outputs of register to inverters
(instantiate-single-layer-wire new-file
108
'("basic_reg-0"
"reg_bit-O"
"inv_2-0")
f Z i"
'("inv_1larray-O"
"A"
'metall
4
2)
"inv_1-0")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "regbit-l" "inv2-0")
"iZ"
'("inv_1larray-0" "inv_l-l")
"A"
'metall
4
10)
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-2" "inv_2-0")
'("inv_1_array-0"
"A"
'metall
4
16)
"inv_1-2")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-3" "inv_2-0")
11Z 11
'("inv_1 array-O"
"A"
'metall
4
24)
"inv_1-3")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-4" "inv_2-0")
'("inv_1_array-0"
"A"
'metall
4
30)
"inv_-4")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-5" "inv_2-0")
", Z"
'("inv_1_array-0"
"A"
'metall
4
38)
"inv_-5")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "regbit-6" "inv2-0")
Z"1
"i
'("inv_1_array-0" "inv_1-6")
109
"A"
'metall
4
44)
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-7" "inv_2-0")
"1Z"
'("inv_1_array-0"
"A"
'metall
4
52)
"inv_1-7")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-8" "inv_2-0")
"lZ"
'("inv_1_array-0"
"A"
'metall
4
58)
"inv_l-8")
(instantiate-single-layer-wire new-file
'("basic reg-0" "regbit-9" "inv_2-0")
If Z"
'("inv_1_array-O"
"A"
'metall
4
66)
"inv_-9")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "regbit-10" "inv_2-0")
" Z"
'("inv_1_array-0"
"A"
'metall
4
72)
"inv_1-10")
(instantiate-single-layer-wire new-file
"reg_bit-ll"
'("basic_reg-0"
"inv_2-0")
"! Z"
"inv_1-11")
'("inv_1_array-0"
"A"
'metall
4
80)
(instantiate-single-layer-wire new-file
'("basicreg-0" "reg_bit-12" "inv2-0")
"! Z"
'("inv_1_array-0"
"A"
'metall
4
86)
"inv_1-12")
110
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-13" "inv_2-0")
"!Z"
'("inv_1_array-O"
"A"
'metall
4
94)
"inv_1-13")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg bit-14"
"inv_2-0")
"|Z"
'("inv_1_array-0"
"A"
'metall
4
100)
"inv_1-14")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-15" "inv_2-0")
" Z"
'("inv_1larray-0"
"A"
'metall
4
108)
"inv_1-15")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "regbit-16" "inv_2-0")
"!Z"
'("inv_1_array-0"
"A"
'metall
4
114)
"inv_1-16")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-17" "inv_2-0")
'("inv_1_array-0"
"inv_l-17")
"A"
'metall
4
122)
(instantiate-single-layer-wire new-file
'("basicreg-0" "regbit-18" "inv2-0")
f Z 11
'("inv_1_array-0"
"A"
'metall
4
128)
"inv_1-18")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-19" "inv_2-0")
"! Z"
'("inv 1_array-O"
"A"
'metall
4
136)
"inv_1-19")
(instantiate-single-layer-wire new-file
'("basicreg-0" "regbit-20" "inv 2-0")
" Z"
'("invl _array-O"
"A"
'metall
4
142)
"inv_1-20")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "regbit-21" "inv2-0")
" Z 11
'("inv_1_array-0"
"A"
'metall
4
150)
"inv_1-21")
(instantiate-single-layer-wire new-file
'("basicreg-0" "reg_bit-22" "inv_2-0")
11Z"
'("inv_1_array-0"
"A"
'metall
4
156)
"inv_1-22")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "regbit-23" "inv_2-0")
" Z"
'("inv 1_array-0" "inv_1-23")
"A"
'metall
4
164)
(instantiate-single-layer-wire new-file
'("basic_reg-0" "regbit-24" "inv2-0")
"! Z"
'("inv_1_array-0"
"A"
'metall
4
170)
"inv_1-24")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "regbit-25" "inv2-0")
" Z"
'("inv_1_array-0"
"A"
"inv_1-25")
112
'metall
4
178)
(instantiate-single-layer-wire new-file
'("basic_reg-0" "regbit-26" "inv_2-0")
" Z"
'("inv_1 array-0" "inv_1-26")
"A"
'metall
4
184)
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-27" "inv2-0")
I Z"
'("inv_1larray-0"
"A"
'metall
4
192)
"inv_1-27")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-28" "inv_2-0")
"!Z"
'("inv_1_array-0"
"inv_1-28")
"A"
'metall
4
198)
(instantiate-single-layer-wire new-file
'("basic_reg-0" "reg_bit-29" "inv_2-0")
'("inv_1_array-O"
"A"
"inv_1-29")
'metall
4
206)
(instantiate-single-layer-wire new-file
'("basicreg-0" "regbit-30" "inv_2-0")
'("inv_1_array-O"
"A"
'metall
4
212)
"inv_1-30")
(instantiate-single-layer-wire new-file
'("basic_reg-0" "regbit-31" "inv_2-0")
"!Z"
'("inv_1_array-0"
"A"
'metall
4
220)
"inv_1-31")
113
; output of inverters to logic
(instantiate-single-layer-wire new-file
'("inv_1_array-0"
"inv_1-0")
f Z"
'("counter_logic-0" "nor_nand_nor_nand_tree0" "nornand_nor_tree-0" "nor_nandtreetriple-0" "nor2-0")
"A"
'metall
4
2)
(instantiate-wire new-file
'("inv_1_array-0"
"inv_1-1")
"1Z"
'("counter_logic-0" "nor_nand_nor_nand_tree-0"
"nor_nand_nortree-0" "nor_nand_treetriple-0" "nor2-0")
"B"
4)
(instantiate-single-layer-wire new-file
'("inv_1_array-0"
"inv_l-2")
11Z 11
'("counter_logic-0" "nor_nandnor_nand_tree0" "nor_nand_nor_tree-0" "nor_nand_tree_triple-0" "nor2-1")
"A"
'metall
4
16)
(instantiate-wire new-file
'("inv_1_array-0"
"inv_1-3")
"1Z"
'("counter_logic-0" "nor_nand_nornand_tree-0"
"nor_nand_nor_tree-0" "nor_nand_tree_triple-0" "nor2-1")
"B"
18)
(instantiate-single-layer-wire new-file
'("inv_1larray-0"
"inv_1-4")
" Z"
'("counter_logic-0" "nor_nand_nor_nandtree0" "nor_nand_nor_tree-0" "nor_nand_tree_triple-l" "nor2-0")
"A"
'metall
4
30)
(instantiate-wire new-file
'("basic_reg-0"
"regbit-5" "inv_2-0")
'("counterlogic-0" "nornandnor nand_tree-0"
"nor nand_nor tree-0" "nornandtree triple-l" "nor2-0")
"B"
32)
#1
(instantiate-wire new-file
'("inv_1_array-0"
"inv_1-5")
'("counter_logic-0" "nor_nand_nor_nand_tree-0"
"nor_nand_nortree-0" "nor_nand_treetriple-l" "nor2-0")
"B"
32)
1#
(instantiate-single-layer-wire new-file
'("inv 1 array-0"
"inv_l1-6")
"| Z"
'("counter_logic-0" "nor_nand_nor_nand_tree0" "nor_nand_nor_tree-0" "nor_nand_tree_triple-l" "nor2-1")
"A"
'metall
4
44)
(instantiate-wire new-file
'("inv_1_array-O"
"inv_1-7")
"1Z"
'("counter_logic-0" "nornandnornandtree-0"
"nor_nand_nortree-0" "nornand_treetriple-l" "nor2-1")
"B"
46)
(instantiate-single-layer-wire new-file
'("inv_1_array-0"
"inv1-8")
"! Z"
'("counter_logic-0" "nor_nand_nor_nand_tree0" "nor_nand_nor_tree-l" "nor_nand_tree_triple-0" "nor2-0")
"A"
'metall
4
58)
(instantiate-wire new-file
'("inv 1_array-0"
"inv_1-9")
if Z"
'("counter_logic-0" "nor_nand_nor_nand_tree-0"
"nor_nand_nor_tree-l" "nor_nand_tree_triple-0" "nor2-0")
"B"
60)
(instantiate-single-layer-wire new-file
'("inv_1_array-0" "inv_1-10")
'("counterlogic-0" "nor_nand_nor_nand_tree-0"
"nor nand_nor_tree-l" "nornand_tree triple-0" "nor2-1")
"A"
'metall
4
72)
(instantiate-wire new-file
'("inv_1_array-0"
"inv_1-11")
" Z"
115
'("counter_logic-0" "nor_nand_nor_nand_tree-0"
"nor_nand_nor_tree-1" "nor_nand_tree_triple-0" "nor2-1")
"B"
74)
(instantiate-single-layer-wire new-file
'("inv 1_array-0" "inv_1-12")
'("counter_logic-0" "nornand_nor_nand_tree-0"
"nor_nand_nor_tree-1" "nor_nand_treetriple-l" "nor2-0")
"A"
'metall
4
86)
(instantiate-wire new-file
'("inv 1_array-0" "inv_1-13")
'("counter_logic-0" "nor_nand_nor_nand_tree-0"
"nor_nand_nor_tree-1" "nor_nand_treetriple-1" "nor2-0")
" B"
88)
(instantiate-single-layer-wire new-file
"inv_1-14")
'("inv_1larray-0"
"1Z"
'("counter_logic-0" "nornand_nornand_tree-0"
"nor_nand_nor_tree-1" "nor_nand_treetriple-l" "nor2-1")
"A"
'metall
4
100)
(instantiate-wire new-file
'("inv_1_array-0"
"inv_1-15")
", Z"
'("counter_logic-0" "nornandnornandtree-0"
"nor_nand_nor_tree-i" "nor_nand_treetriple-l" "nor2-1")
iB"
102)
(instantiate-wire new-file
'("inv 1 array-0"
"inv_1-16")
I"Z"
'("counter_logic-0" "nor_nand_nor_nand_tree-1"
"nornand_nor_tree-1" "nor_nand_treetriple-l" "nor2-1")
"B"
116)
(instantiate-single-layer-wire new-file
"inv_1-17")
'("inv_1_array-0"
'("counter_logic-0" "nornandnornand_tree-l"
"nornand_nor_tree-1" "nor_nand_treetriple-l" "nor2-1")
"A"
'metall
4
122)
116
(instantiate-wire new-file
'("inv 1_array-0" "inv_1-18")
"
" Z
'("counter_logic-0" "nornandnor_nand_tree-1"
"nor_nand_nor_tree-1" "nor_nand_treetriple-l" "nor2-0")
"B"
134)
(instantiate-single-layer-wire new-file
'("inv_1_array-0" "inv_1-19")
11Z"
'("counter_logic-0" "nor_nand_nor_nand_tree-1"
"nor_nand_nortree-1" "nor_nand_treetriple-l" "nor2-0")
"A"
'metall
4
136)
(instantiate-wire new-file
'("inv_1_array-O"
"inv_1-20")
'("counterlogic-0" "nornand_nor_nandtree-l"
"nor_nand_nortree-1" "nor nand_treetriple-0" "nor2-1")
"B"
148)
(instantiate-single-layer-wire new-file
'("inv_1_array-0" "inv_1-21")
"
" Z
'("counter_logic-0" "nor_nand_nor_nand_tree-1"
"nor_nand_nor_tree-1" "nor_nand_tree_triple-0" "nor2-1")
"A"
'metall
4
150)
(instantiate-wire new-file
'("inv_1larray-0" "inv_1-22")
"1Z"
'("counter_logic-0" "nor_nand_nor_nand_tree-1"
"nor_nand_nor_tree-1" "nor_nand_treetriple-0" "nor2-0")
"B"
162)
(instantiate-single-layer-wire new-file
'("inv 1 array-0" "inv_1-23")
"
" Z
'("counter_logic-0" "nor_nand_nor_nand_tree-1"
"nor_nand_nor_tree-1" "nor_nand_treetriple-0" "nor2-0")
"A"
'metall
4
164)
(instantiate-wire new-file
1array-O"
'("inv_
"inv_l-24")
117
I Z"
'("counter logic-0" "nor_nandnor_nandtree-l"
"nor_nand_nortree-0" "nor_nand_treetriple-1" "nor2-1")
",
B
176)
(instantiate-single-layer-wire new-file
'("inv_1_array-0" "inv_1-25")
"
" Z
'("counter logic-0" "nor_nand_nor_nandtree-l"
"nor_nand_nortree-0" "nor_nand_treetriple-l" "nor2-1")
"A"
'metall
4
178)
(instantiate-wire new-file
'("inv 1 array-0" "inv_1-26")
11Z
"
'("counter_logic-0" "nornandnor nandtree-1"
"nor_nand_nor_tree-0" "nor_nand_treetriple-1" "nor2-0")
"B"
190)
(instantiate-single-layer-wire new-file
'("inv_1larray-0" "inv_l-27")
" Z" 11
'("counter_logic-0" "nor_nand_nor_nand_tree-1"
"nor_nand_nor_tree-0" "nor_nand_treetriple-1" "nor2-0")
"A"
'metall
4
192)
(instantiate-wire new-file
'("inv_1larray-0"
"inv 1-28")
'("counterlogic-0" "nornand_nor_nand_tree-1"
"nor_nand_nortree-0" "nor_nand_treetriple-0" "nor2-1")
"B"
204)
(instantiate-single-layer-wire new-file
'("inv_1_array-0" "inv_1-29")
" Z"
'("counter_logic-0" "nornand_nornand_tree-i"
"nor_nand_nortree-0" "nor_nand_treetriple-0" "nor2-1")
"A"
'metall
4
206)
(instantiate-wire new-file
'("inv_
1array-0" "inv_1-30")
11Z 11
'("counter logic-0" "nornandnornand_tree-l"
"nor_nand_nortree-0" "nor nand_treetriple-0" "nor2-0")
118
" B"
218)
(instantiate-single-layer-wire new-file
'("inv_1_array-0"
"inv_l-31")
" Z"
'("counter_logic-0" "nor_nand_nor_nand_tree1" "nor_nand_nor_tree-0" "nor_nand tree_triple-0" "nor2-0")
"A"
'metall
4
220)
output of register to mux input
(instantiate-wire new-file
'("basic_reg-0"
"reg_bit-0" "inv_2-0")
ifZ"
'("mux_32-0"
"DO "
6)
"tgmux_gnd-0")
(instantiate-wire new-file
'("basic_reg-0"
" Z
'("mux_32-0"
"DO "
7)
"inv2-0")
"tgmux_gnd-l")
(instantiate-wire new-file
'("basic_reg-0"
" Z
"reg_bit-l"
"
"regbit-2" "inv_2-0")
"
'("mux_32-0"
"DO "
13)
"tgmuxgnd-2")
(instantiate-wire new-file
'("basic_reg-0"
"reg_bit-3" "inv_2-0")
"Z"
'("mux_32-0"
"DO "
20)
"tgmuxgnd-3")
(instantiate-wire new-file
'("basic_reg-0"
"reg_bit-4" "inv_2-0")
11Z"
'("mux_32-0"
"DO "
27)
"tgmuxgnd-4")
(instantiate-wire new-file
'("basic_reg-0"
" Z
"reg_bit-5" "inv_2-0")
"
'("mux_32-0"
"DO "
34)
"tgmuxgnd-5")
(instantiate-wire new-file
119
'("basic_reg-0"
"reg_bit-6" "inv_2-0")
"1Z"
'("mux_32-O"
"DO"
41)
"tgmux_gnd-6")
(instantiate-wire new-file
'("basic_reg-0"
"regbit-7" "inv_2-0")
" Z"
'("mux_32-0"
"DO"
48)
"tgmux_gnd-7")
(instantiate-wire new-file
'("basic_reg-0"
"reg_bit-8" "inv_2-0")
i Z"
'("mux_32-0"
"DO"
55)
"tgmuxgnd-8")
(instantiate-wire new-file
'("basic_reg-O"
"regbit-9" "inv_2-0")
11Z"
'("mux_32-0"
"DO"
62)
"tgmuxgnd-9")
(instantiate-wire new-file
'("basic_reg-0"
"reg_bit-10" "inv_2-0")
"1Z"
'("mux_32-O"
"DO"
69)
"tgmux_gnd-10")
(instantiate-wire new-file
'("basic_reg-O"
"reg_bit-ll"
"inv_2-0")
"1Z"
'("mux_32-0"
"DO"
76)
"tgmux_gnd-11")
(instantiate-wire new-file
'("basic_reg-O"
"reg_bit-12" "inv_2-0")
"! Z"
'("mux_32-0"
"DO"
83)
"tgmux_gnd-12")
(instantiate-wire new-file
'("basic_reg-O"
"regbit-13"
"inv_2-0")
" Z 11
'("mux_32-0"
"DO"
90)
"tgmuxgnd-13")
(instantiate-wire new-file
'("basic_reg-O"
"regbit-14" "inv_2-0")
120
'("mux_32-0"
"DO"
97)
"tgmux_gnd-14")
(instantiate-wire new-file
'("basicreg-O"
" Z
"regbit-15" "inv2-0")
"
'("mux_32-0"
"DO"
104)
"tgmux_gnd-15")
(instantiate-wire new-file
'("basic_reg-O"
f Z"
"reg_bit-16" "inv_2-0")
1
'("mux_32-0"
"DO"
111)
"tgmux_gnd-16")
(instantiate-wire new-file
'("basic_reg-O"
"reg_bit-17" "inv_2-0")
"1Z"
'("mux_32-0"
"DO"
118)
"tgmux_gnd-17")
(instantiate-wire new-file
'("basic_reg-O"
'("mux_32-0"
"DO"
125)
"reg_bit-18" "inv_2-0")
"tgmux_gnd-18")
(instantiate-wire new-file
'("basic_reg-0"
"reg_bit-19" "inv_2-0")
"0Z"
'("mux_32-0"
"DO"
132)
"tgmux_gnd-19")
(instantiate-wire new-file
'("basic_reg-O"
'("mux_32-0"
"DO"
139)
"reg_bit-20" "inv_2-0")
"tgmux_gnd-20")
(instantiate-wire new-file
'("basic_reg-O"
"reg_bit-21" "inv_2-0")
" Z"
'("mux_32-0"
"DO"
146)
"tgmux_gnd-21")
(instantiate-wire new-file
'("basic_reg-O"
" Z"
"reg_bit-22" "inv_2-0")
'("mux_32-0"
"DO "
153)
"tgmux_gnd-22")
(instantiate-wire new-file
'("basic_reg-O" "regbit-23" "inv_2-0")
"iZ"
'("mux_32-0" "tgmuxgnd-23")
"DO"
160)
(instantiate-wire new-file
'("basic reg-0" "reg_bit-24" "inv2-0")
"1Z"
'("mux_32-0"
"DO"
167)
"tgmux_gnd-24")
(instantiate-wire new-file
'("basic reg-0" "reg_bit-25" "inv_2-0")
1
f Z"
'("mux_32-0"
"DO"
174)
"tgmux_gnd-25")
(instantiate-wire new-file
'("basic_reg-O"
"reg_bit-26" "inv_2-0")
"1Z"
'("mux_32-0"
"DO"
181)
"tgmux_gnd-26")
(instantiate-wire new-file
'("basic_reg-0"
"reg_bit-27" "inv_2-0")
If Z"
'("mux_32-0"
"DO "
188)
"tgmux_gnd-27")
(instantiate-wire new-file
'("basic_reg-O"
"reg_bit-28" "inv_2-0")
"! Z"
'("mux_32-0"
"DO"
195)
"tgmux_gnd-28")
(instantiate-wire new-file
'("basicreg-0" "reg_bit-29" "inv_2-0")
"! Z"
'("mux_32-0"
"DO"
202)
"tgmux_gnd-29")
(instantiate-wire new-file
'("basic_reg-O"
Z"tg
("
'("mux_32-0"
"reg_bit-30" "inv_2-0")
"tgmux_gnd-30")
122
"DO "
209)
(instantiate-wire new-file
'("basic_reg-O"
"reg_bit-31" "inv_2-0")
i Z"
'("mux_32-0"
"DO"
216)
"tgmuxgnd-31")
; selector bits from logic to mux
(instantiate-five-segment-wire new-file
'("counter_logic-0" "inv2and4-O" "inv2-0")
I Z" I
'("mux_32-0"
"tgmux_gnd-O")
"i
Si
113
-1
95)
(instantiate-power-grid new-file row-spacing 4 65 4)
(instantiate-five-segment-wire new-file
'("counter_logic-0" "inv_2and4-0" "inv4-0")
"! Z"
'("mux_32-0"
"tgmux_gnd-31")
115
223
95)
(write-magic-file new-file)))
(define (make-basicreg)
(reg_bit)
(basic_reg))
(define (make-counterlogic)
(nor_nand_tree_triple)
(nor_nand_nor_tree)
(nor_nand_nor_nand_tree)
(inv_2and4)
(counter_logic))
(define (make-counter)
(make-basicreg)
(mux_32)
(make-counterlogic)
(inv_1_array)
(counter))
123
References
1.
Ulrich Lauther, "A Min-Cut Placement Algorithm for General Cell Assemblies
Based on a Graph Representation," Proceedings of the 16th Design Automation
Conference, 1979, pp. 1-10.
2.
Mark Hortoog, "Analysis of Placement Procedures for VLSI Standard Cell
Layout," Proceedings of the 23rd Design Automation Conference, 1986, pp. 314319.
3.
Ronald Rivest and Charles Fidducia, "A 'Greedy' Channel Router," Proceedings
of the 1 9 th Design Automation Conference, 1982, pp. 418-424.
4.
J. Soukup, "Global Router," Proceedingsof the 16 th Design Automation
Conference, 1978, pp. 481-484.
5.
C. Sechen and A. Sangiovanni-Vincentelli, "Timberwolf3.2: A New Standard
Cell Placement and Global Routing Package," Proceedings of the International
Conference on Computer-AidedDesign, 1984, pp. 72-75.
6.
http://www.swiss.ai.mit.edu/-switz/amorphous/index.html
7.
Magic, Version 6. DECWRL/Livermore, 1990.
8.
Weste and Eshragian, Principlesof CMOS VLSI Design, Reading, Mass.:
Addison-Wesley, 1993, pp. 326-327
9.
Hennessy and Patterson, Computer Architecture: A QuantitativeApproach, San
Francisco, CA: Morgan Kaufmann Publishers, 1996, pp. A43-A44
10.
Weste and Eshragian, Principles of CMOS VLSI Design, Reading, Mass.:
Addison-Wesley, 1993, pp. 528-530
11.
Weste and Eshragian, Principles of CMOS VLSI Design, Reading, Mass.:
Addison-Wesley, 1990, pp. 326-331
124
Download