Version abc70930

This commit is contained in:
Alan Mishchenko
2007-09-30 08:01:00 -07:00
parent 7d7e60f2dc
commit e54d969161
811 changed files with 248706 additions and 18038 deletions
-30
View File
@@ -1,30 +0,0 @@
TARGETS = place_test BookshelfView.class
CFLAGS = -g -pedantic -Wall
STATIC_LIBS = libhmetis.a
DYNAMIC_LIBS = -lm
OBJECTS = place_test.o place_qpsolver.o place_base.o place_pads.o place_genqp.o place_gordian.o \
place_partition.o place_legalize.o place_bin.o
# For hMetis free code, uncomment the following lines
#
# CFLAGS = -g -pedantic -Wall -DNO_HMETIS
# STATIC_LIBS =
all: $(TARGETS)
%.o: %.c *.h
gcc $(CFLAGS) -c -o $@ $<
place_test: $(OBJECTS)
gcc *.o $(STATIC_LIBS) $(DYNAMIC_LIBS) -o place_test
BookshelfView.class: BookshelfView.java
javac BookshelfView.java
clean:
rm -rf *.o place_test *.class *~
-50
View File
@@ -1,50 +0,0 @@
/*===================================================================*/
//
// GORDIAN-like placement package
//
// Aaron P. Hurst ([email protected])
// Addl code from Philip Chong ([email protected])
// hMetis partitioner (www.cs.umn.edu/~metis)
//
/*===================================================================*/
1. Requirements
An i386 Linux system (though others will certainly work with some tweaks).
A standard ANSI C development platform.
The following are optional, but useful:
- hMetis partitioner. This can be obtained from (www.cs.umn.edu/~metis)
Place (links to) the files "libhmetis.a" and "libhtmetis.h" in this directory.
Otherwise, #define NO_HMETIS in the file "place_gordian.h"
- Java SDK, if compiling BookshelfView is desired.
- Perl, if additional script utilities are desired.
2. Descriptions of contents:
place_base.h contains the basic data structures and "external" API.
place_gordian.h contains the "internal" API and configuration options.
There are also several utilities:
i) place_test
Reads a netlist description in GSRC Bookshelf format, performs global placement,
and rewrites the placement file. An example usage:
./place_test ac97_emap.nodes ac97_emap.nets ac97_emap.pl
ii) BookshelfView
A simple Java GUI to view the resulting placements. It has been tested with
Java 5 and 6. Usage:
java BookshelfView ac97_emap.nodes ac97_emap.pl
iii) hpwl
A perl script to print the half-perimeter wirelength of a placement. Usage:
./hpwl ac97_emap.nets ac97_emal.pl
-57
View File
@@ -1,57 +0,0 @@
#! /usr/bin/perl
$netsfile = shift;
$plfile = shift;
# ------------------------------ read placement
open FILE, $plfile;
while (<FILE>) {
chop;
if (/(\w+)\s+([\-\d\.]+)\s+([\-\d\.]+)\s+\:/) {
$loc{$1} = "$2 $3";
}
}
close FILE;
open FILE, $netsfile;
while (<FILE>) {
chop;
$net = $2 if /NetDegree\s+\:\s+(\d+)\s+(\w+)/;
if (/(\w+)\s+(\w+)\s+\:/) {
$netconn{$net} .= "$1 ";
$cellconn{$1} .= "$net ";
}
}
close FILE;
# ----------------------------- compute HPWL
$hpwl = 0;
foreach $net (keys %netconn) {
@conns = split ' ',$netconn{$net};
$min_x = $min_y = 1e12;
$max_x = $max_y = -1e12;
foreach $cell (@conns) {
if (!exists $loc{$cell}) {
print "WARNING: Unknown cell location: $cell\n";
} else {
($x, $y) = split ' ',$loc{$cell};
$min_x = $x if $x < $min_x;
$min_y = $y if $y < $min_y;
$max_x = $x if $x > $max_x;
$max_y = $y if $y > $max_y;
}
}
if ($min_x eq 1e12 or $min_y eq 1e12 or
$max_x eq -1e12 or $max_y eq -1e12) {
print "WARNING: Unbounded box\n";
} else {
$hpwl = $hpwl + $max_x - $min_x + $max_y - $min_y;
}
}
print "HPWL = ";
printf "%e",$hpwl;
print "\n";
-31
View File
@@ -1,31 +0,0 @@
// A. Hurst [email protected]
#ifndef LIBHMETIS_H_
#define LIBHMETIS_H_
static void HMETIS_PartRecursive(int nvtxs,
int nhedges,
int *vwgts,
int *eptr,
int *eind,
int *hewgts,
int nparts,
int nbfactor,
int *options,
int *part,
int *edgecnt ) {} //;
static void HMETIS_PartKway(int nvtxs,
int nhedges,
int *vwgts,
int *eptr,
int *eind,
int *hewgts,
int nparts,
int nbfactor,
int *options,
int *part,
int *edgecnt ) {} //;
#endif
-10
View File
@@ -1,10 +0,0 @@
SRC += src/phys/place/place_base.c \
src/phys/place/place_bin.c \
src/phys/place/place_genqp.c \
src/phys/place/place_gordian.c \
src/phys/place/place_legalize.c \
src/phys/place/place_pads.c \
src/phys/place/place_partition.c \
src/phys/place/place_qpsolver.c \
src/phys/place/place_io.c \
src/phys/place/place_inc.c
-345
View File
@@ -1,345 +0,0 @@
/*===================================================================*/
//
// place_base.c
//
// Aaron P. Hurst, 2003-2007
// [email protected]
//
/*===================================================================*/
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
#include <string.h>
#include "place_base.h"
#include "place_gordian.h"
// --------------------------------------------------------------------
// Global variables
//
// --------------------------------------------------------------------
int g_place_numCells = 0;
int g_place_numNets = 0;
float g_place_rowHeight = 1.0;
Rect g_place_coreBounds;
Rect g_place_padBounds;
ConcreteCell **g_place_concreteCells = NULL;
int g_place_concreteCellsSize = 0;
ConcreteNet **g_place_concreteNets = NULL;
int g_place_concreteNetsSize = 0;
// --------------------------------------------------------------------
// getNetBBox()
//
/// \brief Returns the bounding box of a net.
//
// --------------------------------------------------------------------
Rect getNetBBox(const ConcreteNet *net) {
int t;
Rect r;
assert(net);
r.x = r.y = INT_MAX;
r.w = r.h = -INT_MAX;
for(t=0; t<net->m_numTerms; t++) {
r.x = net->m_terms[t]->m_x < r.x ? net->m_terms[t]->m_x : r.x;
r.y = net->m_terms[t]->m_y < r.y ? net->m_terms[t]->m_y : r.y;
r.w = net->m_terms[t]->m_x > r.w ? net->m_terms[t]->m_x : r.w;
r.h = net->m_terms[t]->m_y > r.h ? net->m_terms[t]->m_y : r.h;
}
r.w -= r.x; r.h -= r.y;
return r;
}
// --------------------------------------------------------------------
// getNetWirelength()
//
/// \brief Returns the half-perimeter wirelength of a net.
//
// --------------------------------------------------------------------
float getNetWirelength(const ConcreteNet *net) {
Rect r;
assert(net);
r = getNetBBox(net);
return r.w+r.h;
}
// --------------------------------------------------------------------
// getTotalWirelength()
//
/// \brief Returns the total HPWL of all nets.
//
// --------------------------------------------------------------------
float getTotalWirelength() {
float r = 0;
int n;
for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n])
r += getNetWirelength(g_place_concreteNets[n]);
return r;
}
// --------------------------------------------------------------------
// getCellArea()
//
// --------------------------------------------------------------------
float getCellArea(const ConcreteCell *cell) {
assert(cell);
return cell->m_parent->m_width*cell->m_parent->m_height;
}
// --------------------------------------------------------------------
// addConcreteNet()
//
/// \brief Adds a net to the placement database.
///
/// The net object must already be allocated and the ID must be set
/// appropriately.
//
// --------------------------------------------------------------------
void addConcreteNet(ConcreteNet *net) {
assert(net);
assert(net->m_id >= 0);
if (net->m_id >= g_place_concreteNetsSize) {
g_place_concreteNetsSize = (net->m_id > g_place_concreteNetsSize ?
net->m_id : g_place_concreteNetsSize);
g_place_concreteNetsSize *= 1.5;
g_place_concreteNetsSize += 20;
g_place_concreteNets = (ConcreteNet**)realloc(g_place_concreteNets,
sizeof(ConcreteNet*)*g_place_concreteNetsSize);
assert(g_place_concreteNets);
}
if (net->m_id >= g_place_numNets) {
memset(&(g_place_concreteNets[g_place_numNets]), 0,
sizeof(ConcreteNet*)*(net->m_id+1-g_place_numNets));
g_place_numNets = net->m_id+1;
assert(g_place_numNets <= g_place_concreteNetsSize);
}
g_place_concreteNets[net->m_id] = net;
}
// --------------------------------------------------------------------
// delConcreteNet()
//
/// Does not deallocate memory.
// --------------------------------------------------------------------
void delConcreteNet(ConcreteNet *net) {
assert(net);
g_place_concreteNets[net->m_id] = 0;
while(!g_place_concreteNets[g_place_numNets-1]) g_place_numNets--;
}
// --------------------------------------------------------------------
// addConcreteCell()
//
/// The cell object must already be allocated and the ID must be set
/// appropriately.
//
// --------------------------------------------------------------------
void addConcreteCell(ConcreteCell *cell) {
assert(cell);
assert(cell->m_id >= 0);
if (cell->m_id >= g_place_concreteCellsSize) {
g_place_concreteCellsSize = (cell->m_id > g_place_concreteCellsSize ?
cell->m_id : g_place_concreteCellsSize);
g_place_concreteCellsSize *= 1.5;
g_place_concreteCellsSize += 20;
g_place_concreteCells = (ConcreteCell**)realloc(g_place_concreteCells,
sizeof(ConcreteCell*)*g_place_concreteCellsSize);
assert(g_place_concreteCells);
}
if (cell->m_id >= g_place_numCells) {
memset(&(g_place_concreteCells[g_place_numCells]), 0,
sizeof(ConcreteCell*)*(cell->m_id+1-g_place_numCells));
g_place_numCells = cell->m_id+1;
}
g_place_concreteCells[cell->m_id] = cell;
}
// --------------------------------------------------------------------
// delCellFromPartition()
//
// --------------------------------------------------------------------
void delCellFromPartition(ConcreteCell *cell, Partition *p) {
int c;
bool found = false;
assert(cell);
assert(p);
for(c=0; c<p->m_numMembers; c++)
if (p->m_members[c] == cell) {
p->m_members[c] = 0;
p->m_area -= getCellArea(cell);
found = true;
break;
}
if (!found) return;
if (!p->m_leaf) {
delCellFromPartition(cell, p->m_sub1);
delCellFromPartition(cell, p->m_sub2);
}
}
// --------------------------------------------------------------------
// delConcreteCell()
//
/// \brief Removes a cell from the placement database.
///
/// Does not deallocate memory.
///
/// Important: does not modify nets that may point to this
/// cell. If these are connections are not removed, segmentation faults
/// and other nasty errors will occur.
//
// --------------------------------------------------------------------
void delConcreteCell(ConcreteCell *cell) {
assert(cell);
g_place_concreteCells[cell->m_id] = 0;
while(!g_place_concreteCells[g_place_numCells-1]) g_place_numCells--;
if (g_place_rootPartition) delCellFromPartition(cell, g_place_rootPartition);
}
// --------------------------------------------------------------------
// netSortByX...
//
/// \brief Sorts nets by position of one of its corners.
//
/// These are for use with qsort().
///
/// Can tolerate pointers to NULL objects.
///
// --------------------------------------------------------------------
int netSortByL(const void *a, const void *b) {
const ConcreteNet *pa = *(const ConcreteNet **)a;
const ConcreteNet *pb = *(const ConcreteNet **)b;
Rect ba, bb;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
ba = getNetBBox(pa), bb = getNetBBox(pb);
if (ba.x < bb.x) return -1;
if (ba.x > bb.x) return 1;
return 0;
}
int netSortByR(const void *a, const void *b) {
const ConcreteNet *pa = *(const ConcreteNet **)a;
const ConcreteNet *pb = *(const ConcreteNet **)b;
Rect ba, bb;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
ba = getNetBBox(pa), bb = getNetBBox(pb);
if (ba.x + ba.w < bb.x + bb.w) return -1;
if (ba.x + ba.w > bb.x + bb.w) return 1;
return 0;
}
int netSortByB(const void *a, const void *b) {
const ConcreteNet *pa = *(const ConcreteNet **)a;
const ConcreteNet *pb = *(const ConcreteNet **)b;
Rect ba, bb;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
ba = getNetBBox(pa), bb = getNetBBox(pb);
if (ba.y + ba.h < bb.y + bb.h) return -1;
if (ba.y + ba.h > bb.y + bb.h) return 1;
return 0;
}
int netSortByT(const void *a, const void *b) {
const ConcreteNet *pa = *(const ConcreteNet **)a;
const ConcreteNet *pb = *(const ConcreteNet **)b;
Rect ba, bb;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
ba = getNetBBox(pa), bb = getNetBBox(pb);
if (ba.y < bb.y) return -1;
if (ba.y > bb.y) return 1;
return 0;
}
int netSortByID(const void *a, const void *b) {
const ConcreteNet *pa = *(const ConcreteNet **)a;
const ConcreteNet *pb = *(const ConcreteNet **)b;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
if (pa->m_id < pb->m_id) return -1;
if (pa->m_id > pb->m_id) return 1;
return 0;
}
// --------------------------------------------------------------------
// cellSortByX...
//
/// \brief Sorts cells by either position coordinate.
//
/// These are for use with qsort().
///
/// Can tolerate pointers to NULL objects.
//
// --------------------------------------------------------------------
int cellSortByX(const void *a, const void *b) {
const ConcreteCell *pa = *(const ConcreteCell **)a;
const ConcreteCell *pb = *(const ConcreteCell **)b;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
if (pa->m_x < pb->m_x) return -1;
if (pa->m_x > pb->m_x) return 1;
return 0;
}
int cellSortByY(const void *a, const void *b) {
const ConcreteCell *pa = *(const ConcreteCell **)a;
const ConcreteCell *pb = *(const ConcreteCell **)b;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
if (pa->m_y < pb->m_y) return -1;
if (pa->m_y > pb->m_y) return 1;
return 0;
}
int cellSortByID(const void *a, const void *b) {
const ConcreteCell *pa = *(const ConcreteCell **)a;
const ConcreteCell *pb = *(const ConcreteCell **)b;
if (!pa && !pb) return 0;
else if (!pa) return -1;
else if (!pb) return 1;
if (pa->m_id < pb->m_id) return -1;
if (pa->m_id > pb->m_id) return 1;
return 0;
}
-137
View File
@@ -1,137 +0,0 @@
/*===================================================================*/
//
// place_base.h
//
// Aaron P. Hurst, 2003-2007
// [email protected]
//
/*===================================================================*/
#if !defined(PLACE_BASE_H_)
#define PLACE_BASE_H_
// --------------------------------------------------------------------
// Data structures
//
// --------------------------------------------------------------------
// --- a C++ bool-like type
//typedef char bool;
#ifndef bool
#define bool int
#endif
#define true 1
#define false 0
// --- Rect - rectangle
typedef struct Rect {
float x, y;
float w, h;
} Rect;
// --- AbstractCell - a definition of a cell type
typedef struct AbstractCell {
char *m_label; // string description
float m_width, m_height; // dimensions
bool m_pad; // a pad (external I/O) cell?
} AbstractCell;
// --- ConcreteCell - a design object
typedef struct ConcreteCell {
int m_id; // a unique ID (see below)
char *m_label; // string description
AbstractCell *m_parent; // cell type
bool m_fixed; // position is fixed?
float m_x, m_y; // center of cell
int m_data;
} ConcreteCell;
// --- ConcreteNet - a design net
typedef struct ConcreteNet {
int m_id; // a unique ID (see below)
int m_numTerms; // num. of connected cells
ConcreteCell **m_terms; // connected cells
float m_weight; // relative weight
int m_data;
} ConcreteNet;
// A note about IDs - the IDs are non-nonegative integers. They need not
// be contiguous, but this is certainly a good idea, as they are stored
// in a non-sparse array.
// Cells and nets have separate ID spaces.
// --------------------------------------------------------------------
// Global variable prototypes
//
// --------------------------------------------------------------------
// NOTE: None of these need to be managed externally.
extern int g_place_numCells; // number of cells
extern int g_place_numNets; // number of nets
extern float g_place_rowHeight; // height of placement row
extern Rect g_place_coreBounds; // border of placeable area
// (x,y) = corner
extern Rect g_place_padBounds; // border of total die area
// (x,y) = corner
extern ConcreteCell **g_place_concreteCells; // all concrete cells
extern ConcreteNet **g_place_concreteNets; // all concrete nets
// --------------------------------------------------------------------
// Function prototypes
//
// --------------------------------------------------------------------
void addConcreteNet(ConcreteNet *net);
void addConcreteCell(ConcreteCell *cell);
void delConcreteNet(ConcreteNet *net);
void delConcreteCell(ConcreteCell *cell);
void globalPreplace(float utilization);
void globalPlace();
void globalIncremental();
void globalFixDensity(int numBins, float maxMovement);
float fastEstimate(ConcreteCell *cell,
int numNets, ConcreteNet *nets[]);
float fastTopoPlace(int numCells, ConcreteCell *cells[],
int numNets, ConcreteNet *nets[]);
Rect getNetBBox(const ConcreteNet *net);
float getNetWirelength(const ConcreteNet *net);
float getTotalWirelength();
float getCellArea(const ConcreteCell *cell);
void writeBookshelf(const char *filename);
// comparative qsort-style functions
int netSortByL(const void *a, const void *b);
int netSortByR(const void *a, const void *b);
int netSortByB(const void *a, const void *b);
int netSortByT(const void *a, const void *b);
int netSortByID(const void *a, const void *b);
int cellSortByX(const void *a, const void *b);
int cellSortByY(const void *a, const void *b);
int cellSortByID(const void *a, const void *b);
#endif
-277
View File
@@ -1,277 +0,0 @@
/*===================================================================*/
//
// place_bin.c
//
// Aaron P. Hurst, 2007
// [email protected]
//
/*===================================================================*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
//#define DEBUG
#include "place_base.h"
// --------------------------------------------------------------------
// Global variables
//
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// Function prototypes and local data structures
//
// --------------------------------------------------------------------
void spreadDensityX(int numBins, float maxMovement);
void spreadDensityY(int numBins, float maxMovement);
// --------------------------------------------------------------------
// globalFixDensity()
//
/// Doesn't deal well with fixed cells in the core area.
// --------------------------------------------------------------------
void globalFixDensity(int numBins, float maxMovement) {
printf("QCLN-10 : \tbin-based density correction\n");
spreadDensityX(numBins, maxMovement);
// spreadDensityY(numBins, maxMovement);
}
// --------------------------------------------------------------------
// spreadDensityX()
//
// --------------------------------------------------------------------
void spreadDensityX(int numBins, float maxMovement) {
int c, c2, c3, x, y;
float totalArea = 0;
int moveableCells = 0;
float yBinArea = 0, yCumArea = 0;
int yBinStart = 0, yBinCount = 0;
int xBinCount, xBinStart;
float xBinArea, xCumArea;
float lastOldEdge;
float lastNewEdge;
float curOldEdge, curNewEdge;
float stretch, w;
ConcreteCell *xCell, *yCell;
ConcreteCell **binCells;
ConcreteCell **allCells;
binCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
ConcreteCell *cell = g_place_concreteCells[c];
if (!cell->m_fixed && !cell->m_parent->m_pad) {
allCells[moveableCells++] = cell;
totalArea += getCellArea(cell);
}
}
// spread X
qsort(allCells, moveableCells, sizeof(ConcreteCell*), cellSortByY);
y = 0;
// for each y-bin...
for(c=0; c<moveableCells; c++) {
yCell = allCells[c];
yBinArea += getCellArea(yCell);
yCumArea += getCellArea(yCell);
yBinCount++;
// have we filled up a y-bin?
if (yCumArea >= totalArea*(y+1)/numBins && yBinArea > 0) {
memcpy(binCells, &(allCells[yBinStart]), sizeof(ConcreteCell*)*yBinCount);
qsort(binCells, yBinCount, sizeof(ConcreteCell*), cellSortByX);
#if defined(DEBUG)
printf("y-bin %d count=%d area=%f\n",y,yBinCount, yBinArea);
#endif
x = 0;
xBinCount = 0, xBinStart = 0;
xBinArea = 0, xCumArea = 0;
lastOldEdge = g_place_coreBounds.x;
lastNewEdge = g_place_coreBounds.x;
// for each x-bin...
for(c2=0; c2<yBinCount; c2++) {
xCell = binCells[c2];
xBinArea += getCellArea(xCell);
xCumArea += getCellArea(xCell);
xBinCount++;
curOldEdge = xCell->m_x;
printf("%.3f ", xCell->m_x);
// have we filled up an x-bin?
if (xCumArea >= yBinArea*(x+1)/numBins && xBinArea > 0) {
curNewEdge = lastNewEdge + g_place_coreBounds.w*xBinArea/yBinArea;
if (curNewEdge > g_place_coreBounds.x+g_place_coreBounds.w)
curNewEdge = g_place_coreBounds.x+g_place_coreBounds.w;
if ((curNewEdge-curOldEdge)>maxMovement) curNewEdge = curOldEdge + maxMovement;
if ((curOldEdge-curNewEdge)>maxMovement) curNewEdge = curOldEdge - maxMovement;
#if defined(DEBUG)
printf("->\tx-bin %d count=%d area=%f (%f,%f)->(%f,%f)\n",x, xBinCount, xBinArea,
curOldEdge, lastOldEdge, curNewEdge, lastNewEdge);
#endif
stretch = (curNewEdge-lastNewEdge)/(curOldEdge-lastOldEdge);
// stretch!
for(c3=xBinStart; c3<xBinStart+xBinCount; c3++) {
if (curOldEdge == lastOldEdge)
binCells[c3]->m_x = lastNewEdge+(c3-xBinStart)*(curNewEdge-lastNewEdge);
else
binCells[c3]->m_x = lastNewEdge+(binCells[c3]->m_x-lastOldEdge)*stretch;
// force within core
w = binCells[c3]->m_parent->m_width*0.5;
if (binCells[c3]->m_x-w < g_place_coreBounds.x)
binCells[c3]->m_x = g_place_coreBounds.x+w;
if (binCells[c3]->m_x+w > g_place_coreBounds.x+g_place_coreBounds.w)
binCells[c3]->m_x = g_place_coreBounds.x+g_place_coreBounds.w-w;
}
lastOldEdge = curOldEdge;
lastNewEdge = curNewEdge;
x++;
xBinCount = 0;
xBinArea = 0;
xBinStart = c2+1;
}
}
y++;
yBinCount = 0;
yBinArea = 0;
yBinStart = c+1;
}
}
free(binCells);
free(allCells);
}
// --------------------------------------------------------------------
// spreadDensityY()
//
// --------------------------------------------------------------------
void spreadDensityY(int numBins, float maxMovement) {
int c, c2, c3, x, y;
float totalArea = 0;
int moveableCells = 0;
float xBinArea = 0, xCumArea = 0;
int xBinStart = 0, xBinCount = 0;
int yBinCount, yBinStart;
float yBinArea, yCumArea;
float lastOldEdge;
float lastNewEdge;
float curOldEdge, curNewEdge;
float stretch, h;
ConcreteCell *xCell, *yCell;
ConcreteCell **binCells;
ConcreteCell **allCells;
binCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
ConcreteCell *cell = g_place_concreteCells[c];
if (!cell->m_fixed && !cell->m_parent->m_pad) {
allCells[moveableCells++] = cell;
totalArea += getCellArea(cell);
}
}
// spread Y
qsort(allCells, moveableCells, sizeof(ConcreteCell*), cellSortByX);
x = 0;
// for each x-bin...
for(c=0; c<moveableCells; c++) {
xCell = allCells[c];
xBinArea += getCellArea(xCell);
xCumArea += getCellArea(xCell);
xBinCount++;
// have we filled up an x-bin?
if (xCumArea >= totalArea*(x+1)/numBins && xBinArea > 0) {
memcpy(binCells, &(allCells[xBinStart]), sizeof(ConcreteCell*)*xBinCount);
qsort(binCells, xBinCount, sizeof(ConcreteCell*), cellSortByY);
// printf("x-bin %d count=%d area=%f\n",y,yBinCount, yBinArea);
y = 0;
yBinCount = 0, yBinStart = 0;
yBinArea = 0, yCumArea = 0;
lastOldEdge = g_place_coreBounds.y;
lastNewEdge = g_place_coreBounds.y;
// for each y-bin...
for(c2=0; c2<xBinCount; c2++) {
yCell = binCells[c2];
yBinArea += getCellArea(yCell);
yCumArea += getCellArea(yCell);
yBinCount++;
curOldEdge = yCell->m_y;
// have we filled up an x-bin?
if (yCumArea >= xBinArea*(y+1)/numBins && yBinArea > 0) {
curNewEdge = lastNewEdge + g_place_coreBounds.h*yBinArea/xBinArea;
if (curNewEdge > g_place_coreBounds.y+g_place_coreBounds.h)
curNewEdge = g_place_coreBounds.y+g_place_coreBounds.h;
if ((curNewEdge-curOldEdge)>maxMovement) curNewEdge = curOldEdge + maxMovement;
if ((curOldEdge-curNewEdge)>maxMovement) curNewEdge = curOldEdge - maxMovement;
if (curOldEdge == lastOldEdge) continue; // hmmm
stretch = (curNewEdge-lastNewEdge)/(curOldEdge-lastOldEdge);
// stretch!
for(c3=yBinStart; c3<yBinStart+yBinCount; c3++) {
binCells[c3]->m_y = lastNewEdge+(binCells[c3]->m_y-lastOldEdge)*stretch;
// force within core
h = binCells[c3]->m_parent->m_height;
if (binCells[c3]->m_y-h < g_place_coreBounds.y)
binCells[c3]->m_y = g_place_coreBounds.y+h;
if (binCells[c3]->m_y+h > g_place_coreBounds.y+g_place_coreBounds.h)
binCells[c3]->m_y = g_place_coreBounds.y+g_place_coreBounds.h-h;
}
lastOldEdge = curOldEdge;
lastNewEdge = curNewEdge;
y++;
yBinCount = 0;
yBinArea = 0;
yBinStart = c2+1;
}
}
x++;
xBinCount = 0;
xBinArea = 0;
xBinStart = c+1;
}
}
free(binCells);
free(allCells);
}
-309
View File
@@ -1,309 +0,0 @@
/*===================================================================*/
//
// place_genqp.c
//
// Aaron P. Hurst, 2003-2007
// [email protected]
//
/*===================================================================*/
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "place_base.h"
#include "place_qpsolver.h"
#include "place_gordian.h"
// --------------------------------------------------------------------
// Global variables
//
// --------------------------------------------------------------------
qps_problem_t *g_place_qpProb = NULL;
// --------------------------------------------------------------------
// splitPenalty()
//
/// \brief Returns a weight for all of the edges in the clique for a multipin net.
//
// --------------------------------------------------------------------
float splitPenalty(int pins) {
if (pins > 1) {
return 1.0 + CLIQUE_PENALTY/(pins - 1);
// return pow(pins - 1, CLIQUE_PENALTY);
}
return 1.0 + CLIQUE_PENALTY;
}
// --------------------------------------------------------------------
// constructQuadraticProblem()
//
/// \brief Constructs the matrices necessary to do analytical placement.
//
// --------------------------------------------------------------------
void constructQuadraticProblem() {
int maxConnections = 1;
int ignoreNum = 0;
int n,t,c,c2,p;
ConcreteCell *cell;
ConcreteNet *net;
int *cell_numTerms = calloc(g_place_numCells, sizeof(int));
ConcreteNet ***cell_terms = calloc(g_place_numCells, sizeof(ConcreteNet**));
bool incremental = false;
int nextIndex = 1;
int *seen = calloc(g_place_numCells, sizeof(int));
float weight;
int last_index;
// create problem object
if (!g_place_qpProb) {
g_place_qpProb = malloc(sizeof(qps_problem_t));
g_place_qpProb->area = NULL;
g_place_qpProb->x = NULL;
g_place_qpProb->y = NULL;
g_place_qpProb->fixed = NULL;
g_place_qpProb->connect = NULL;
g_place_qpProb->edge_weight = NULL;
}
// count the maximum possible number of non-sparse entries
for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
ConcreteNet *net = g_place_concreteNets[n];
if (net->m_numTerms > IGNORE_NETSIZE) {
ignoreNum++;
}
else {
maxConnections += net->m_numTerms*(net->m_numTerms-1);
for(t=0; t<net->m_numTerms; t++) {
c = net->m_terms[t]->m_id;
p = ++cell_numTerms[c];
cell_terms[c] = (ConcreteNet**)realloc(cell_terms[c], p*sizeof(ConcreteNet*));
cell_terms[c][p-1] = net;
}
}
}
if(ignoreNum) {
printf("QMAN-10 : \t\t%d large nets ignored\n", ignoreNum);
}
// initialize the data structures
g_place_qpProb->num_cells = g_place_numCells;
maxConnections += g_place_numCells + 1;
g_place_qpProb->area = realloc(g_place_qpProb->area,
sizeof(float)*g_place_numCells);// "area" matrix
g_place_qpProb->edge_weight = realloc(g_place_qpProb->edge_weight,
sizeof(float)*maxConnections); // "weight" matrix
g_place_qpProb->connect = realloc(g_place_qpProb->connect,
sizeof(int)*maxConnections); // "connectivity" matrix
g_place_qpProb->fixed = realloc(g_place_qpProb->fixed,
sizeof(int)*g_place_numCells); // "fixed" matrix
// initialize or keep preexisting locations
if (g_place_qpProb->x != NULL && g_place_qpProb->y != NULL) {
printf("QMAN-10 :\tperforming incremental placement\n");
incremental = true;
}
g_place_qpProb->x = (float*)realloc(g_place_qpProb->x, sizeof(float)*g_place_numCells);
g_place_qpProb->y = (float*)realloc(g_place_qpProb->y, sizeof(float)*g_place_numCells);
// form a row for each cell
// build data
for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) {
cell = g_place_concreteCells[c];
// fill in the characteristics for this cell
g_place_qpProb->area[c] = getCellArea(cell);
if (cell->m_fixed || cell->m_parent->m_pad) {
g_place_qpProb->x[c] = cell->m_x;
g_place_qpProb->y[c] = cell->m_y;
g_place_qpProb->fixed[c] = 1;
} else {
if (!incremental) {
g_place_qpProb->x[c] = g_place_coreBounds.x+g_place_coreBounds.w*0.5;
g_place_qpProb->y[c] = g_place_coreBounds.y+g_place_coreBounds.h*0.5;
}
g_place_qpProb->fixed[c] = 0;
}
// update connectivity matrices
last_index = nextIndex;
for(n=0; n<cell_numTerms[c]; n++) {
net = cell_terms[c][n];
weight = net->m_weight / splitPenalty(net->m_numTerms);
for(t=0; t<net->m_numTerms; t++) {
c2 = net->m_terms[t]->m_id;
if (c2 == c) continue;
if (seen[c2] < last_index) {
// not seen
g_place_qpProb->connect[nextIndex-1] = c2;
g_place_qpProb->edge_weight[nextIndex-1] = weight;
seen[c2] = nextIndex;
nextIndex++;
} else {
// seen
g_place_qpProb->edge_weight[seen[c2]-1] += weight;
}
}
}
g_place_qpProb->connect[nextIndex-1] = -1;
g_place_qpProb->edge_weight[nextIndex-1] = -1.0;
nextIndex++;
} else {
// fill in dummy values for connectivity matrices
g_place_qpProb->connect[nextIndex-1] = -1;
g_place_qpProb->edge_weight[nextIndex-1] = -1.0;
nextIndex++;
}
free(cell_numTerms);
free(cell_terms);
free(seen);
}
typedef struct reverseCOG {
float x,y;
Partition *part;
float delta;
} reverseCOG;
// --------------------------------------------------------------------
// generateCoGConstraints()
//
/// \brief Generates center of gravity constraints.
//
// --------------------------------------------------------------------
int generateCoGConstraints(reverseCOG COG_rev[]) {
int numConstraints = 0; // actual num contraints
int cogRevNum = 0;
Partition **stack = malloc(sizeof(Partition*)*g_place_numPartitions*2);
int stackPtr = 0;
Partition *p;
float cgx, cgy;
int next_index = 0, last_constraint = 0;
bool isTrueConstraint = false;
int i, m;
float totarea;
ConcreteCell *cell;
// each partition may give rise to a center-of-gravity constraint
stack[stackPtr] = g_place_rootPartition;
while(stackPtr >= 0) {
p = stack[stackPtr--];
assert(p);
// traverse down the partition tree to leaf nodes-only
if (!p->m_leaf) {
stack[++stackPtr] = p->m_sub1;
stack[++stackPtr] = p->m_sub2;
} else {
/*
cout << "adding a COG constraint for box "
<< p->bounds.x << ","
<< p->bounds.y << " of size"
<< p->bounds.w << "x"
<< p->bounds.h
<< endl;
*/
cgx = p->m_bounds.x + p->m_bounds.w*0.5;
cgy = p->m_bounds.y + p->m_bounds.h*0.5;
COG_rev[cogRevNum].x = cgx;
COG_rev[cogRevNum].y = cgy;
COG_rev[cogRevNum].part = p;
COG_rev[cogRevNum].delta = 0;
cogRevNum++;
}
}
assert(cogRevNum == g_place_numPartitions);
for (i = 0; i < g_place_numPartitions; i++) {
p = COG_rev[i].part;
assert(p);
g_place_qpProb->cog_x[numConstraints] = COG_rev[i].x;
g_place_qpProb->cog_y[numConstraints] = COG_rev[i].y;
totarea = 0.0;
for(m=0; m<p->m_numMembers; m++) if (p->m_members[m]) {
cell = p->m_members[m];
assert(cell);
if (!cell->m_fixed && !cell->m_parent->m_pad) {
isTrueConstraint = true;
}
else {
continue;
}
g_place_qpProb->cog_list[next_index++] = cell->m_id;
totarea += getCellArea(cell);
}
if (totarea == 0.0) {
isTrueConstraint = false;
}
if (isTrueConstraint) {
numConstraints++;
g_place_qpProb->cog_list[next_index++] = -1;
last_constraint = next_index;
}
else {
next_index = last_constraint;
}
}
free(stack);
return --numConstraints;
}
// --------------------------------------------------------------------
// solveQuadraticProblem()
//
/// \brief Calls quadratic solver.
//
// --------------------------------------------------------------------
void solveQuadraticProblem(bool useCOG) {
int c;
reverseCOG *COG_rev = malloc(sizeof(reverseCOG)*g_place_numPartitions);
g_place_qpProb->cog_list = malloc(sizeof(int)*(g_place_numPartitions+g_place_numCells));
g_place_qpProb->cog_x = malloc(sizeof(float)*g_place_numPartitions);
g_place_qpProb->cog_y = malloc(sizeof(float)*g_place_numPartitions);
// memset(g_place_qpProb->x, 0, sizeof(float)*g_place_numCells);
// memset(g_place_qpProb->y, 0, sizeof(float)*g_place_numCells);
qps_init(g_place_qpProb);
if (useCOG)
g_place_qpProb->cog_num = generateCoGConstraints(COG_rev);
else
g_place_qpProb->cog_num = 0;
g_place_qpProb->loop_num = 0;
qps_solve(g_place_qpProb);
qps_clean(g_place_qpProb);
// set the positions
for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) {
g_place_concreteCells[c]->m_x = g_place_qpProb->x[c];
g_place_concreteCells[c]->m_y = g_place_qpProb->y[c];
}
// clean up
free(g_place_qpProb->cog_list);
free(g_place_qpProb->cog_x);
free(g_place_qpProb->cog_y);
free(COG_rev);
}
-160
View File
@@ -1,160 +0,0 @@
/*===================================================================*/
//
// place_gordian.c
//
// Aaron P. Hurst, 2003-2007
// [email protected]
//
/*===================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <limits.h>
#include "place_gordian.h"
#include "place_base.h"
// --------------------------------------------------------------------
// Global variables
//
// --------------------------------------------------------------------
int g_place_numPartitions;
// --------------------------------------------------------------------
// globalPlace()
//
/// \brief Performs analytic placement using a GORDIAN-like algorithm.
//
/// Updates the positions of all non-fixed non-pad cells.
///
// --------------------------------------------------------------------
void globalPlace() {
bool completionFlag = false;
int iteration = 0;
printf("PLAC-10 : Global placement (wirelength-driven Gordian)\n");
initPartitioning();
// build matrices representing interconnections
printf("QMAN-00 : \tconstructing initial quadratic problem...\n");
constructQuadraticProblem();
// iterate placement until termination condition is met
while(!completionFlag) {
printf("QMAN-01 : \titeration %d numPartitions = %d\n",iteration,g_place_numPartitions);
// do the global optimization in each direction
printf("QMAN-01 : \t\tglobal optimization\n");
solveQuadraticProblem(!IGNORE_COG);
// -------- PARTITIONING BASED CELL SPREADING ------
// bisection
printf("QMAN-01 : \t\tpartition refinement\n");
if (REALLOCATE_PARTITIONS) reallocPartitions();
completionFlag |= refinePartitions();
printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
iteration++;
}
// final global optimization
printf("QMAN-02 : \t\tfinal pass\n");
if (FINAL_REALLOCATE_PARTITIONS) reallocPartitions();
solveQuadraticProblem(!IGNORE_COG);
printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
// clean up
sanitizePlacement();
printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
globalFixDensity(25, g_place_rowHeight*5);
printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
}
// --------------------------------------------------------------------
// globalIncremental()
//
/// \brief Performs analytic placement using a GORDIAN-like algorithm.
//
/// Requires a valid set of partitions.
///
// --------------------------------------------------------------------
void globalIncremental() {
if (!g_place_rootPartition) {
printf("WARNING: Can not perform incremental placement\n");
globalPlace();
return;
}
printf("PLAC-10 : Incremental global placement\n");
incrementalPartition();
printf("QMAN-00 : \tconstructing initial quadratic problem...\n");
constructQuadraticProblem();
solveQuadraticProblem(!IGNORE_COG);
printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
// clean up
sanitizePlacement();
printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
globalFixDensity(25, g_place_rowHeight*5);
printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
}
// --------------------------------------------------------------------
// sanitizePlacement()
//
/// \brief Moves any cells that are outside of the core bounds to the nearest location within.
//
// --------------------------------------------------------------------
void sanitizePlacement() {
int c;
float order_width = g_place_rowHeight;
float x, y, edge, w, h;
printf("QCLN-10 : \tsanitizing placement\n");
for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
ConcreteCell *cell = g_place_concreteCells[c];
if (cell->m_fixed || cell->m_parent->m_pad) {
continue;
}
// the new locations of the cells will be distributed within
// a small margin inside the border so that ordering is preserved
order_width = g_place_rowHeight;
x = cell->m_x, y = cell->m_y,
w = cell->m_parent->m_width, h = cell->m_parent->m_height;
if ((edge=x-w*0.5) < g_place_coreBounds.x) {
x = g_place_coreBounds.x+w*0.5 +
order_width/(1.0+g_place_coreBounds.x-edge);
}
else if ((edge=x+w*0.5) > g_place_coreBounds.x+g_place_coreBounds.w) {
x = g_place_coreBounds.x+g_place_coreBounds.w-w*0.5 -
order_width/(1.0+edge-g_place_coreBounds.x-g_place_coreBounds.w);
}
if ((edge=y-h*0.5) < g_place_coreBounds.y) {
y = g_place_coreBounds.y+h*0.5 +
order_width/(1.0+g_place_coreBounds.y-edge);
}
else if ((edge=y+h*0.5) > g_place_coreBounds.y+g_place_coreBounds.h) {
y = g_place_coreBounds.y+g_place_coreBounds.h-h*0.5 -
order_width/(1.0+edge-g_place_coreBounds.x-g_place_coreBounds.w);
}
cell->m_x = x;
cell->m_y = y;
}
}
-78
View File
@@ -1,78 +0,0 @@
/*===================================================================*/
//
// place_gordian.h
//
// Aaron P. Hurst, 2003-2007
// [email protected]
//
/*===================================================================*/
#if !defined(PLACE_GORDIAN_H_)
#define PLACE_GORDIAN_H_
#include "place_base.h"
#include "place_qpsolver.h"
// Parameters for analytic placement
#define CLIQUE_PENALTY 1.0
#define IGNORE_NETSIZE 20
// Parameters for partitioning
#define LARGEST_FINAL_SIZE 20
#define PARTITION_AREA_ONLY true
#define REALLOCATE_PARTITIONS false
#define FINAL_REALLOCATE_PARTITIONS false
#define IGNORE_COG false
#define MAX_PARTITION_NONSYMMETRY 0.30
// Parameters for re-partitioning
#define REPARTITION_LEVEL_DEPTH 4
#define REPARTITION_TARGET_FRACTION 0.15
#define REPARTITION_FM false
#define REPARTITION_HMETIS true
// Parameters for F-M re-partitioning
#define FM_MAX_BIN 10
#define FM_MAX_PASSES 10
extern int g_place_numPartitions;
extern qps_problem_t *g_place_qpProb;
typedef struct Partition {
int m_numMembers;
ConcreteCell **m_members;
Rect m_bounds;
bool m_done,
m_leaf,
m_vertical;
float m_area;
int m_level;
struct Partition *m_sub1, *m_sub2;
} Partition;
extern Partition *g_place_rootPartition;
void initPartitioning();
void incrementalPartition();
bool refinePartitions();
void reallocPartitions();
bool refinePartition(Partition *p);
void resizePartition(Partition *p);
void reallocPartition(Partition *p);
void repartitionHMetis(Partition *parent);
void repartitionFM(Partition *parent);
void partitionScanlineMincut(Partition *parent);
void partitionEqualArea(Partition *parent);
void sanitizePlacement();
void constructQuadraticProblem();
void solveQuadraticProblem(bool useCOG);
#endif
-106
View File
@@ -1,106 +0,0 @@
/*===================================================================*/
//
// place_inc.c
//
// Aaron P. Hurst, 2003-2007
// [email protected]
//
/*===================================================================*/
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
#include <string.h>
#include "place_base.h"
#include "place_gordian.h"
inline int sqHashId(int id, int max) {
return ((id * (id+17)) % max);
}
#if 0
// --------------------------------------------------------------------
// fastPlace()
//
/// The first cell is assumed to be the "output".
// --------------------------------------------------------------------
float fastPlace(int numCells, ConcreteCell *cells[],
int numNets, ConcreteNet *nets[]) {
int n, t, c, i, local_id = 0, pass;
const int NUM_PASSES = 4;
int *cell_numTerms = calloc(numCells, sizeof(int));
ConcreteNet **cell_terms;
ConcreteNet *net;
Rect outputBox;
outputBox = getNetBBox(nets[0]);
// assign local ids
// put cells in reasonable initial location
for(n=0; n<numNets; n++)
for(t=0; nets[n]->m_numTerms; t++)
nets[n]->m_terms[t]->m_data = -1;
for(c=0; c<numCells; c++) {
cells[c]->m_data = local_id;
cells[c]->m_x = outputBox.x + 0.5*outputBox.w;
cells[c]->m_y = outputBox.y + 0.5*outputBox.h;
}
// build reverse map of cells to nets
for(n=0; n<numNets; n++)
for(t=0; nets[n]->m_numTerms; t++) {
local_id = nets[n]->m_terms[t]->m_data;
if (local_id >= 0)
cell_numTerms[local_id]++;
}
for(c=0; c<numCells; c++) {
cell_terms[c] = malloc(sizeof(ConcreteNet*)*cell_numTerms[c]);
cell_numTerms[c] = 0;
}
for(n=0; n<numNets; n++)
for(t=0; nets[n]->m_numTerms; t++) {
local_id = nets[n]->m_terms[t]->m_data;
if (local_id >= 0)
cell_terms[cell_numTerms[local_id]++] = nets[n];
}
// topological order?
// iterative linear
for(pass=0; pass<NUM_PASSES; pass++)
for(c=0; c<numCells; c++) {
for(n=0; n<cell_numTerms[c]; n++) {
net = cell_terms[c];
for(t=0; t<net->m_numTerms; t++);
}
}
}
#endif
// --------------------------------------------------------------------
// fastEstimate()
//
// --------------------------------------------------------------------
float fastEstimate(ConcreteCell *cell,
int numNets, ConcreteNet *nets[]) {
float len = 0;
int n;
Rect box;
assert(cell);
for(n=0; n<numNets; n++) {
box = getNetBBox(nets[n]);
if (cell->m_x < box.x) len += (box.x - cell->m_x);
if (cell->m_x > box.x+box.w) len += (cell->m_x-box.x-box.w);
if (cell->m_y < box.y) len += (box.x - cell->m_y);
if (cell->m_y > box.y+box.h) len += (cell->m_y-box.y-box.h);
}
return len;
}
-94
View File
@@ -1,94 +0,0 @@
/*===================================================================*/
//
// place_io.c
//
// Aaron P. Hurst, 2003-2007
// [email protected]
//
/*===================================================================*/
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include "place_base.h"
// --------------------------------------------------------------------
// writeBookshelfNodes()
//
// --------------------------------------------------------------------
void writeBookshelfNodes(const char *filename) {
int c = 0;
int numNodes, numTerms;
FILE *nodesFile = fopen(filename, "w");
if (!nodesFile) {
printf("ERROR: Could not open .nodes file\n");
exit(1);
}
numNodes = numTerms = 0;
for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
numNodes++;
if (g_place_concreteCells[c]->m_parent->m_pad)
numTerms++;
}
fprintf(nodesFile, "UCLA nodes 1.0\n");
fprintf(nodesFile, "NumNodes : %d\n", numNodes);
fprintf(nodesFile, "NumTerminals : %d\n", numTerms);
for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
fprintf(nodesFile, "CELL%d %f %f %s\n",
g_place_concreteCells[c]->m_id,
g_place_concreteCells[c]->m_parent->m_width,
g_place_concreteCells[c]->m_parent->m_height,
(g_place_concreteCells[c]->m_parent->m_pad ? " terminal" : ""));
}
fclose(nodesFile);
}
// --------------------------------------------------------------------
// writeBookshelfPl()
//
// --------------------------------------------------------------------
void writeBookshelfPl(const char *filename) {
int c = 0;
FILE *plFile = fopen(filename, "w");
if (!plFile) {
printf("ERROR: Could not open .pl file\n");
exit(1);
}
fprintf(plFile, "UCLA pl 1.0\n");
for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
fprintf(plFile, "CELL%d %f %f : N %s\n",
g_place_concreteCells[c]->m_id,
g_place_concreteCells[c]->m_x,
g_place_concreteCells[c]->m_y,
(g_place_concreteCells[c]->m_fixed ? "\\FIXED" : ""));
}
fclose(plFile);
}
// --------------------------------------------------------------------
// writeBookshelf()
//
// --------------------------------------------------------------------
void writeBookshelf(const char *filename) {
writeBookshelfNodes("out.nodes");
writeBookshelfPl("out.pl");
}
-23
View File
@@ -1,23 +0,0 @@
/*===================================================================*/
//
// place_legalize.c
//
// Aaron P. Hurst, 2007
// [email protected]
//
/*===================================================================*/
#include <limits.h>
#include <assert.h>
#include "place_base.h"
// --------------------------------------------------------------------
// legalize()
//
// --------------------------------------------------------------------
void legalize() {
// UNIMPLEMENTED
}
-141
View File
@@ -1,141 +0,0 @@
/*===================================================================*/
//
// place_pads.c
//
// Aaron P. Hurst, 2003-2007
// [email protected]
//
/*===================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include "place_base.h"
// --------------------------------------------------------------------
// globalPreplace()
//
/// \brief Place pad ring, leaving a core area to meet a desired utilization.
//
/// Sets the position of pads that aren't already fixed.
///
/// Computes g_place_coreBounds and g_place_padBounds. Determines
/// g_place_rowHeight.
//
// --------------------------------------------------------------------
void globalPreplace(float utilization) {
int i, c, h, numRows;
float coreArea = 0, totalArea = 0;
int padCount = 0;
float area;
ConcreteCell **padCells = NULL;
AbstractCell *padType = NULL;
ConcreteCell *cell;
float nextPos;
int remainingPads, northPads, southPads, eastPads, westPads;
printf("PLAC-00 : Placing IO pads\n");;
// identify the pads and compute the total core area
g_place_coreBounds.x = g_place_coreBounds.y = 0;
g_place_coreBounds.w = g_place_coreBounds.h = -INT_MAX;
for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
cell = g_place_concreteCells[c];
area = getCellArea(cell);
if (cell->m_parent->m_pad) {
padType = cell->m_parent;
} else {
coreArea += area;
g_place_rowHeight = cell->m_parent->m_height;
}
if (cell->m_fixed) {
g_place_coreBounds.x = g_place_coreBounds.x < cell->m_x ? g_place_coreBounds.x : cell->m_x;
g_place_coreBounds.y = g_place_coreBounds.y < cell->m_y ? g_place_coreBounds.y : cell->m_y;
g_place_coreBounds.w = g_place_coreBounds.w > cell->m_x ? g_place_coreBounds.w : cell->m_x;
g_place_coreBounds.h = g_place_coreBounds.h > cell->m_y ? g_place_coreBounds.h : cell->m_y;
} else if (cell->m_parent->m_pad) {
padCells = realloc(padCells, sizeof(ConcreteCell **)*(padCount+1));
padCells[padCount++] = cell;
}
totalArea += area;
}
if (!padType) {
printf("ERROR: No pad cells\n");
exit(1);
}
g_place_padBounds.w -= g_place_padBounds.x;
g_place_padBounds.h -= g_place_padBounds.y;
coreArea /= utilization;
// create the design boundaries
numRows = sqrt(coreArea)/g_place_rowHeight+1;
h = numRows * g_place_rowHeight;
g_place_coreBounds.h = g_place_coreBounds.h > h ? g_place_coreBounds.h : h;
g_place_coreBounds.w = g_place_coreBounds.w > coreArea/g_place_coreBounds.h ?
g_place_coreBounds.w : coreArea/g_place_coreBounds.h;
// increase the dimensions by the width of the padring
g_place_padBounds = g_place_coreBounds;
if (padCount) {
printf("PLAC-05 : \tpreplacing %d pad cells\n", padCount);
g_place_padBounds.x -= padType->m_width;
g_place_padBounds.y -= padType->m_height;
g_place_padBounds.w = g_place_coreBounds.w+2*padType->m_width;
g_place_padBounds.h = g_place_coreBounds.h+2*padType->m_height;
}
printf("PLAC-05 : \tplaceable rows : %d\n", numRows);
printf("PLAC-05 : \tcore dimensions : %.0fx%.0f\n",
g_place_coreBounds.w, g_place_coreBounds.h);
printf("PLAC-05 : \tchip dimensions : %.0fx%.0f\n",
g_place_padBounds.w, g_place_padBounds.h);
remainingPads = padCount;
c = 0;
// north pads
northPads = remainingPads/4; remainingPads -= northPads;
nextPos = 0;
for(i=0; i<northPads; i++) {
cell = padCells[c++];
cell->m_x = g_place_padBounds.x+cell->m_parent->m_width*0.5 + nextPos;
cell->m_y = g_place_padBounds.y+cell->m_parent->m_height*0.5;
nextPos += (g_place_padBounds.w-padType->m_width) / northPads;
}
// south pads
southPads = remainingPads/3; remainingPads -= southPads;
nextPos = 0;
for(i=0; i<southPads; i++) {
cell = padCells[c++];
cell->m_x = g_place_padBounds.w+g_place_padBounds.x-cell->m_parent->m_width*0.5 - nextPos;
cell->m_y = g_place_padBounds.h+g_place_padBounds.y-cell->m_parent->m_height*0.5;
nextPos += (g_place_padBounds.w-2*padType->m_width) / southPads;
}
// east pads
eastPads = remainingPads/2; remainingPads -= eastPads;
nextPos = 0;
for(i=0; i<eastPads; i++) {
cell = padCells[c++];
cell->m_x = g_place_padBounds.w+g_place_padBounds.x-cell->m_parent->m_width*0.5;
cell->m_y = g_place_padBounds.y+cell->m_parent->m_height*0.5 + nextPos;
nextPos += (g_place_padBounds.h-padType->m_height) / eastPads;
}
// west pads
westPads = remainingPads;
nextPos = 0;
for(i=0; i<westPads; i++) {
cell = padCells[c++];
cell->m_x = g_place_padBounds.x+cell->m_parent->m_width*0.5;
cell->m_y = g_place_padBounds.h+g_place_padBounds.y-cell->m_parent->m_height*0.5 - nextPos;
nextPos += (g_place_padBounds.h-padType->m_height) / westPads;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-140
View File
@@ -1,140 +0,0 @@
/*===================================================================*/
//
// place_qpsolver.h
//
// Philip Chong
// [email protected]
//
/*===================================================================*/
#if !defined(_QPS_H)
#define _QPS_H
#include <stdio.h>
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
typedef float qps_float_t;
typedef struct qps_problem {
/* Basic stuff */
int num_cells; /* Total number of cells (both fixed and
floating) to be placed. */
int *connect; /* Connectivity array. Must contain at least
num_cells elements with value -1. The
entries which precede the first element
with value -1 are the indices of the cells
which connect to cell 0; the entries
which lie between the first and second
elements with value -1 are the indices of
the cells which connect to cell 1; etc.
Example: cells 0 and 1 are connected
together, and 1 and 2 are connected as
well. *connect = { 1, -1, 0, 2, -1, 1, -1
}. */
qps_float_t *edge_weight; /* Same structure as connectivity array, but
giving the weights assigned to each edge
instead. */
qps_float_t *x; /* num_cells element array which contains the
x-coordinates of the cells. This is used
for the initial values in the iterative
solution of floating cells, and for the
fixed location of fixed cells. */
qps_float_t *y; /* num_cells element array of
y-coordinates. */
int *fixed; /* num_cells element array with value 1 if
corresponding cell is fixed, 0 if
floating. */
qps_float_t f; /* return value for sum-of-square
wirelengths. */
/* COG stuff */
int cog_num; /* Number of COG constraints. */
int *cog_list; /* Array indicating for each COG constraint
which cells belong to that constraint.
Format is similar to c array: there must
be at least cog_num elements with value
-1. The entries of cog_list preceding the
first -1 element are the indices of the
cells which belong to the first COG
constraint; etc. Example: cells 0 and 1
belong to one COG constraint, cells 4 and
5 belong to another. *cog_list= { 0, 1,
-1, 4, 5, -1 }. */
qps_float_t *cog_x; /* cog_num element array whose values are the
x-coordinates for the corresponding COG
constraints. */
qps_float_t *cog_y; /* cog_num element array whose values are the
y-coordinates for the corresponding COG
constraints. */
qps_float_t *area; /* num_cells element array whose values are
the areas for the corresponding cells;
only useful with COG constraints. */
/* Loop constraint stuff */
int loop_num; /* Number of loop constraints. */
int *loop_list; /* Array with list of cells for each loop
constraint. Format is similar to cog_list.
*/
qps_float_t *loop_max; /* loop_num element array indicating maximum
distance for each loop. */
qps_float_t *loop_penalty; /* loop_num element array indicating penalty
for each loop. */
int loop_k; /* Current iteration for loop optimization. */
int loop_done; /* Done flag for loop optimization. */
int loop_fail;
/* max_x/max_y stuff */
qps_float_t max_x; /* max x location; only used in
constrained optimization. */
qps_float_t max_y; /* max y location; only used in
constrained optimization. */
int max_enable; /* Set to 1 after qps_init() to enable
max_x/max_y. */
int max_done; /* Done flag for max optimization. */
/* Private stuff */
int *priv_ii;
int *priv_cc, *priv_cr;
qps_float_t *priv_cw, *priv_ct;
int priv_cm;
int *priv_gt;
int *priv_la;
int priv_lm;
qps_float_t *priv_gm, *priv_gw;
qps_float_t *priv_g, *priv_h, *priv_xi;
qps_float_t *priv_tp, *priv_tp2;
int priv_n;
qps_float_t *priv_cp;
qps_float_t priv_f;
qps_float_t *priv_lt;
qps_float_t *priv_pcg, *priv_pcgt;
qps_float_t priv_fmax;
qps_float_t priv_fprev;
qps_float_t priv_fopt;
qps_float_t priv_eps;
int priv_pn;
qps_float_t *priv_mxl, *priv_mxh, *priv_myl, *priv_myh;
int priv_ik;
FILE *priv_fp;
} qps_problem_t;
/* call qps_init() as soon as the qps_problem_t has been set up */
/* this initializes some private data structures */
extern void qps_init(qps_problem_t *);
/* call qps_solve() to solve the given qp problem */
extern void qps_solve(qps_problem_t *);
/* call qps_clean() when finished with the qps_problem_t */
/* this discards the private data structures assigned by qps_init() */
extern void qps_clean(qps_problem_t *);
#if defined(__cplusplus)
}
#endif /* __cplusplus */
#endif /* _QPS_H */
-360
View File
@@ -1,360 +0,0 @@
/*===================================================================*/
//
// place_test.c
//
// Aaron P. Hurst, 2003-2007
// [email protected]
//
/*===================================================================*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "place_base.h"
// --------------------------------------------------------------------
// Hash type/functions
//
// --------------------------------------------------------------------
struct hash_element {
ConcreteCell *obj;
struct hash_element *next;
} hash_element;
int hash_string(int hash_max, const char *str) {
unsigned int hash = 0;
int p;
for(p = 0; p<strlen(str); p++)
hash += str[p]*p;
return hash % hash_max;
}
void hash_add(struct hash_element **hash, int hash_max,
ConcreteCell *cell) {
int key = hash_string(hash_max, cell->m_label);
// printf("adding %s key = %d\n", cell->m_label, key);
struct hash_element *element = malloc(sizeof(struct hash_element));
assert(element);
element->obj = cell;
element->next = hash[key];
hash[key] = element;
}
ConcreteCell *hash_find(struct hash_element **hash, int hash_max, const char *str) {
int key = hash_string(hash_max, str);
// printf("looking for %s key = %d\n", str, key);
struct hash_element *next = hash[key];
while(next) {
if (!strcmp(str, next->obj->m_label))
return next->obj;
next = next->next;
}
return 0;
}
// --------------------------------------------------------------------
// Global variables
//
// --------------------------------------------------------------------
struct hash_element **hash_cellname;
int numCells = 0, numNets = 0;
AbstractCell *abstractCells;
ConcreteCell *concreteCells;
ConcreteNet *concreteNets;
// --------------------------------------------------------------------
// Function implementations
//
// --------------------------------------------------------------------
void readBookshelfNets(char *filename) {
char *tok;
char buf[1024];
const char *DELIMITERS = " \n\t:";
int id = 0;
int t;
ConcreteCell *cell;
FILE *netsFile = fopen(filename, "r");
if (!netsFile) {
printf("ERROR: Could not open .nets file\n");
exit(1);
}
// line 1 : version
while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#'));
// line 2 : number of nets
while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#'));
tok = strtok(buf, DELIMITERS);
tok = strtok(NULL, DELIMITERS);
numNets = atoi(tok);
printf("READ-20 : number of nets = %d\n", numNets);
concreteNets = malloc(sizeof(ConcreteNet)*numNets);
// line 3 : number of pins
while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#'));
// line XXX : net definitions
while(fgets(buf, 1024, netsFile)) {
if (buf[0] == '\n' || buf[0] == '#') continue;
concreteNets[id].m_id = id;
concreteNets[id].m_weight = 1.0;
tok = strtok(buf, DELIMITERS);
if (!!strcmp(tok, "NetDegree")) {
printf("%s\n",buf);
printf("ERROR: Incorrect format in .nets file\n");
exit(1);
}
tok = strtok(NULL, DELIMITERS);
concreteNets[id].m_numTerms = atoi(tok);
if (concreteNets[id].m_numTerms < 0 ||
concreteNets[id].m_numTerms > 100000) {
printf("ERROR: Bad net degree\n");
exit(1);
}
concreteNets[id].m_terms = malloc(sizeof(ConcreteCell*)*
concreteNets[id].m_numTerms);
// read terms
t = 0;
while(t < concreteNets[id].m_numTerms &&
fgets(buf, 1024, netsFile)) {
if (buf[0] == '\n' || buf[0] == '#') continue;
// cell name
tok = strtok(buf, DELIMITERS);
cell = hash_find(hash_cellname, numCells, tok);
if (!cell) {
printf("ERROR: Could not find cell %s in .nodes file\n", tok);
exit(1);
}
concreteNets[id].m_terms[t] = cell;
t++;
}
// add!
addConcreteNet(&(concreteNets[id]));
id++;
}
fclose(netsFile);
}
void readBookshelfNodes(char *filename) {
char *tok;
char buf[1024];
const char *DELIMITERS = " \n\t:";
int id = 0;
FILE *nodesFile = fopen(filename, "r");
if (!nodesFile) {
printf("ERROR: Could not open .nodes file\n");
exit(1);
}
// line 1 : version
while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#'));
// line 2 : num nodes
while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#'));
tok = strtok(buf, DELIMITERS);
tok = strtok(NULL, DELIMITERS);
numCells = atoi(tok);
printf("READ-10 : number of cells = %d\n", numCells);
concreteCells = malloc(sizeof(ConcreteCell)*numCells);
abstractCells = malloc(sizeof(AbstractCell)*numCells);
hash_cellname = calloc(numCells, sizeof(struct hash_element*));
// line 3 : num terminals
while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#'));
// line XXX : cell definitions
while(fgets(buf, 1024, nodesFile)) {
if (buf[0] == '\n' || buf[0] == '#') continue;
tok = strtok(buf, DELIMITERS);
concreteCells[id].m_id = id;;
// label
concreteCells[id].m_parent = &(abstractCells[id]);
concreteCells[id].m_label = malloc(sizeof(char)*strlen(tok)+1);
strcpy(concreteCells[id].m_label, tok);
abstractCells[id].m_label = concreteCells[id].m_label;
hash_add(hash_cellname, numCells,
&(concreteCells[id]));
// dimensions
tok = strtok(NULL, DELIMITERS);
abstractCells[id].m_width = atof(tok);
tok = strtok(NULL, DELIMITERS);
abstractCells[id].m_height = atof(tok);
tok = strtok(NULL, DELIMITERS);
// terminal
abstractCells[id].m_pad = tok && !strcmp(tok, "terminal");
// add!
addConcreteCell(&(concreteCells[id]));
// DEBUG
/*
printf("\"%s\" : %f x %f\n", concreteCells[id].m_label,
abstractCells[id].m_width,
abstractCells[id].m_height);
*/
id++;
}
fclose(nodesFile);
}
void readBookshelfPlacement(char *filename) {
char *tok;
char buf[1024];
const char *DELIMITERS = " \n\t:";
ConcreteCell *cell;
FILE *plFile = fopen(filename, "r");
FILE *netsFile = fopen(filename, "r");
if (!plFile) {
printf("ERROR: Could not open .pl file\n");
exit(1);
}
if (!netsFile) {
printf("ERROR: Could not open .nets file\n");
exit(1);
}
// line 1 : version
while (fgets(buf, 1024, plFile) && (buf[0] == '\n' || buf[0] == '#'));
// line XXX : placement definitions
while(fgets(buf, 1024, plFile)) {
if (buf[0] == '\n' || buf[0] == '#') continue;
tok = strtok(buf, DELIMITERS);
// cell name
cell = hash_find(hash_cellname, numCells, tok);
if (!cell) {
printf("ERROR: Could not find cell %s in .nodes file\n",tok);
exit(1);
}
// position
tok = strtok(NULL, DELIMITERS);
cell->m_x = atof(tok);
tok = strtok(NULL, DELIMITERS);
cell->m_y = atof(tok);
// hfixed
cell->m_fixed = strtok(NULL, DELIMITERS) &&
(tok = strtok(NULL, DELIMITERS)) &&
!strcmp(tok, "\\FIXED");
}
fclose(plFile);
}
void writeBookshelfPlacement(char *filename) {
int c = 0;
FILE *plFile = fopen(filename, "w");
if (!plFile) {
printf("ERROR: Could not open .pl file\n");
exit(1);
}
fprintf(plFile, "UCLA pl 1.0\n");
for(c=0; c<numCells; c++) {
fprintf(plFile, "%s %f %f : N %s\n",
concreteCells[c].m_label,
concreteCells[c].m_x,
concreteCells[c].m_y,
(concreteCells[c].m_fixed ? "\\FIXED" : ""));
}
fclose(plFile);
}
// deletes all connections to a cell
void delNetConnections(ConcreteCell *cell) {
int n, t, t2, count = 0;
ConcreteCell **old = malloc(sizeof(ConcreteCell*)*g_place_numCells);
for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
ConcreteNet *net = g_place_concreteNets[n];
count = 0;
for(t=0; t<net->m_numTerms; t++)
if (net->m_terms[t] == cell) count++;
if (count) {
memcpy(old, net->m_terms, sizeof(ConcreteCell*)*net->m_numTerms);
net->m_terms = realloc(net->m_terms,
sizeof(ConcreteCell*)*(net->m_numTerms-count));
t2 = 0;
for(t=0; t<net->m_numTerms; t++)
if (old[t] != cell) net->m_terms[t2++] = old[t];
net->m_numTerms -= count;
}
}
free(old);
}
int main(int argc, char **argv) {
if (argc != 4) {
printf("Usage: %s [nodes] [nets] [pl]\n", argv[0]);
exit(1);
}
readBookshelfNodes(argv[1]);
readBookshelfNets(argv[2]);
readBookshelfPlacement(argv[3]);
globalPreplace(0.8);
globalPlace();
// DEBUG net/cell removal/addition
/*
int i;
for(i=1000; i<2000; i++) {
delConcreteNet(g_place_concreteNets[i]);
delNetConnections(g_place_concreteCells[i]);
delConcreteCell(g_place_concreteCells[i]);
}
ConcreteCell newCell[2];
newCell[0].m_id = g_place_numCells+1;
newCell[0].m_x = 1000;
newCell[0].m_y = 1000;
newCell[0].m_fixed = false;
newCell[0].m_parent = &(abstractCells[1000]);
newCell[0].m_label = " ";
addConcreteCell(&newCell[0]);
newCell[1].m_id = g_place_numCells+3;
newCell[1].m_x = 1000;
newCell[1].m_y = 1000;
newCell[1].m_fixed = false;
newCell[1].m_parent = &(abstractCells[1000]);
newCell[1].m_label = " ";
addConcreteCell(&newCell[1]);
*/
globalIncremental();
writeBookshelfPlacement(argv[3]);
free(hash_cellname);
return 0;
}