summaryrefslogtreecommitdiff
path: root/qconfig.c
diff options
context:
space:
mode:
authorRuben Undheim <ruben.undheim@gmail.com>2019-03-29 00:00:11 +0100
committerRuben Undheim <ruben.undheim@gmail.com>2019-03-29 00:00:11 +0100
commit6089b1f3dab7b7d60a8ea4bcec47bdec3560c5b4 (patch)
treeccf9fe6e50c78dcfd6e2b1f63b0bdfd8c7ab7d3f /qconfig.c
parent865a8002848550990b963870cca74c0a51426047 (diff)
New upstream version 1.4.49
Diffstat (limited to 'qconfig.c')
-rw-r--r--qconfig.c159
1 files changed, 88 insertions, 71 deletions
diff --git a/qconfig.c b/qconfig.c
index d71c4ff..0fc0261 100644
--- a/qconfig.c
+++ b/qconfig.c
@@ -30,19 +30,17 @@ int PinNumber = 0;
int Num_layers = MAX_LAYERS; // layers to use to route
double PathWidth[MAX_LAYERS]; // width of the paths
-int GDSLayer[MAX_LAYERS]; // GDS layer number
+int GDSLayer[MAX_TYPES]; // GDS layer number
int GDSCommentLayer = 1; // for dummy wires, etc.
-char CIFLayer[MAX_LAYERS][50]; // CIF layer name
-double PitchX[MAX_LAYERS]; // Horizontal wire pitch of layer
-double PitchY[MAX_LAYERS]; // Vertical wire pitch of layer
-int NumChannelsX[MAX_LAYERS]; // number of wire channels in X on layer
-int NumChannelsY[MAX_LAYERS]; // number of wire channels in Y on layer
+char CIFLayer[MAX_TYPES][50]; // CIF layer name
+double PitchX; // Horizontal wire pitch of layer
+double PitchY; // Vertical wire pitch of layer
+int NumChannelsX; // number of wire channels in X on layer
+int NumChannelsY; // number of wire channels in Y on layer
int Vert[MAX_LAYERS]; // 1 if vertical, 0 if horizontal
int Numpasses = 10; // number of times to iterate in route_segs
char StackedContacts = MAX_LAYERS; // Value is number of contacts that may
// be stacked on top of each other.
-char ViaPattern = VIA_PATTERN_NONE; // Patterning to be used for vias based
- // on grid position (i.e., checkerboarding)
double Xlowerbound=0.0; // Bounding Box of routes, in microns
double Xupperbound=0.0;
@@ -59,80 +57,99 @@ int OffsetCost = 50; // Cost per micron of a node offset
int ConflictCost = 50; // Cost of shorting another route
// during the rip-up and reroute stage
-char *ViaX[MAX_LAYERS];
-char *ViaY[MAX_LAYERS];
+char *ViaXX[MAX_LAYERS];
+char *ViaXY[MAX_LAYERS];
+char *ViaYX[MAX_LAYERS];
+char *ViaYY[MAX_LAYERS];
/*--------------------------------------------------------------*/
/* post_config --- */
/* */
-/* The following code ensures that the layer grids align. */
-/* For now, all PitchX[i] and PitchY[i] should be the same */
-/* for all layers. Hopefully this restriction can be lifted */
-/* sometime, but it will necessarily be a royal pain. */
+/* Resolve PitchX and PitchY, which are the minimum pitches */
+/* that determine the underlying route grid. */
+/* */
+/* If "noprint" is TRUE, then do not print diagnostic info. */
/*--------------------------------------------------------------*/
void
-post_config(void)
+post_config(u_char noprint)
{
int i, h, v;
+ double rpitchx, rpitchy;
// Make sure that Num_layers does not exceed the number of
// routing layers defined by the LEF file (or the config
// file).
- i = LefGetMaxLayer();
+ i = LefGetMaxRouteLayer();
if (i < Num_layers) Num_layers = i;
- h = v = -1;
+ // Make sure all layers have a pitch in both X and Y even if not
+ // specified separately in the configuration or def files.
for (i = 0; i < Num_layers; i++) {
- if (!Vert[i]) {
- h = i;
- PitchY[i] = PitchX[i];
- PitchX[i] = 0.0;
- }
- else
- v = i;
+ rpitchx = LefGetRoutePitchX(i);
+ rpitchy = LefGetRoutePitchY(i);
+ if ((PitchX == 0.0) || ((rpitchx != 0.0) && (rpitchx + EPS < PitchX)))
+ PitchX = rpitchx;
+ if ((PitchY == 0.0) || ((rpitchy != 0.0) && (rpitchy + EPS < PitchY)))
+ PitchY = rpitchy;
}
- // In case all layers are listed as horizontal or all
- // as vertical, we should still handle it gracefully
-
- if (h == -1) h = v;
- else if (v == -1) v = h;
+ // This is mostly arbitrary. Generally, all route layer
+ // pitches except for the smallest X and Y pitches will
+ // be ignored, and the actual route pitches will be multiples
+ // of the smallest value, and determined by width and spacing
+ // rules rather than using any value in the technology LEF.
for (i = 0; i < Num_layers; i++) {
- if (PitchX[i] != 0.0 && PitchX[i] != PitchX[v]) {
- Fprintf(stderr, "Multiple vertical route layers at different"
- " pitches. Using smaller pitch %g, will route on"
- " 1-of-N tracks if necessary.\n",
- PitchX[i]);
- PitchX[v] = PitchX[i];
- }
- if (PitchY[i] != 0.0 && PitchY[i] != PitchY[h]) {
- Fprintf(stderr, "Multiple horizontal route layers at different"
- " pitches. Using smaller pitch %g, will route on"
- " 1-of-N tracks if necessary.\n",
- PitchY[i]);
- PitchY[h] = PitchY[i];
- }
+ if (LefGetRoutePitchX(i) == 0.0) {
+ if (Vert[i])
+ LefSetRoutePitchX(i, PitchX);
+ else if (i > 0)
+ LefSetRoutePitchX(i, LefGetRoutePitchX(i - 1));
+ else
+ LefSetRoutePitchX(i, LefGetRoutePitchX(i + 1));
+ }
+ if (LefGetRoutePitchY(i) == 0.0) {
+ if (!Vert[i])
+ LefSetRoutePitchY(i, PitchY);
+ else if (i > 0)
+ LefSetRoutePitchY(i, LefGetRoutePitchY(i - 1));
+ else
+ LefSetRoutePitchY(i, LefGetRoutePitchY(i + 1));
+ }
}
- // 2nd pass: Make sure all layers have a pitch in both X and Y
- // even if not specified separately in the configuration or def files.
- for (i = 0; i < Num_layers; i++) {
- if (PitchX[i] == 0.0) PitchX[i] = PitchX[v];
- if (PitchY[i] == 0.0) PitchY[i] = PitchY[h];
+ if (noprint == FALSE) {
+ for (i = 0; i < Num_layers; i++) {
+ rpitchx = LefGetRoutePitchX(i);
+ rpitchy = LefGetRoutePitchY(i);
+ if ((PitchX != 0.0) && (PitchX + EPS < rpitchx)) {
+ Fprintf(stdout, "Vertical route layer at non-minimum pitch"
+ " %g. Using smaller pitch %g, will route on"
+ " 1-of-%d tracks for layer %s.\n",
+ rpitchx, PitchX, (int)(ceil(rpitchx / PitchX)),
+ LefGetRouteName(i));
+ }
+ if ((PitchY != 0.0) && (PitchY + EPS < rpitchy)) {
+ Fprintf(stdout, "Horizontal route layer at non-minimum pitch"
+ " %g. Using smaller pitch %g, will route on"
+ " 1-of-%d tracks for layer %s.\n",
+ rpitchy, PitchY, (int)(ceil(rpitchy / PitchY)),
+ LefGetRouteName(i));
+ }
+ }
}
-
} /* post_config() */
/*--------------------------------------------------------------*/
-/* Append to string list */
+/* Append to a string */
/*--------------------------------------------------------------*/
void string_list_append(STRING *lst, const char *s)
{
STRING n, strl;
+
n = (STRING)malloc(sizeof(struct string_));
n->name = strdup(s);
n->next = NULL;
@@ -170,8 +187,10 @@ int read_config(FILE *fconfig, int is_info)
if (Firstcall) {
for (i = 0; i < MAX_LAYERS; i++) {
sprintf(line, "via%d%d", i + 1, i + 2);
- ViaX[i] = strdup(line);
- ViaY[i] = NULL;
+ ViaXX[i] = strdup(line);
+ ViaXY[i] = NULL;
+ ViaYX[i] = NULL;
+ ViaYY[i] = NULL;
}
DontRoute = (STRING)NULL;
@@ -180,9 +199,7 @@ int read_config(FILE *fconfig, int is_info)
Nlgates = (GATE)NULL;
UserObs = (DSEG)NULL;
- for (i = 0; i < MAX_LAYERS; i++)
- PitchX[i] = PitchY[i] = 0.0;
-
+ PitchX = PitchY = 0.0;
Firstcall = 0;
}
@@ -198,11 +215,13 @@ int read_config(FILE *fconfig, int is_info)
while (isspace(*lineptr)) lineptr++;
if (!strncasecmp(lineptr, "lef", 3) || !strncmp(lineptr, "read_lef", 8)) {
+ int mscale;
if ((i = sscanf(lineptr, "%*s %s\n", sarg)) == 1) {
// Argument is a filename of a LEF file from which we
// should get the information about gate pins & obstructions
OK = 1;
- LefRead(sarg);
+ mscale = LefRead(sarg);
+ if (mscale > Scales.mscale) Scales.mscale = mscale;
}
}
@@ -220,13 +239,13 @@ int read_config(FILE *fconfig, int is_info)
}
if ((i = sscanf(lineptr, "layer_%d_name %s", &iarg2, sarg)) == 2) {
- if (iarg2 > 0 && iarg2 < 10) {
+ if (iarg2 > 0 && iarg2 <= MAX_LAYERS) {
OK = 1; strcpy(CIFLayer[iarg2 - 1], sarg);
}
}
if ((i = sscanf(lineptr, "gds_layer_%d %d", &iarg2, &iarg)) == 2) {
- if (iarg2 > 0 && iarg2 < 10) {
+ if (iarg2 > 0 && iarg2 <= MAX_TYPES) {
OK = 1; GDSLayer[iarg2 - 1] = iarg;
}
}
@@ -276,7 +295,13 @@ int read_config(FILE *fconfig, int is_info)
}
if ((i = sscanf(lineptr, "layer %d wire pitch %lf\n", &iarg, &darg)) == 2) {
- OK = 1; PitchX[iarg-1] = darg;
+ OK = 1;
+ if (Vert[iarg - 1]) {
+ if ((PitchX == 0) || (darg < PitchX)) PitchX = darg;
+ }
+ else {
+ if ((PitchY == 0) || (darg < PitchY)) PitchY = darg;
+ }
}
else if (i == 1) {
if ((i = sscanf(lineptr, "layer %*d vertical %d\n", &iarg2)) == 1) {
@@ -364,14 +389,6 @@ int read_config(FILE *fconfig, int is_info)
if (StackedContacts == 0) StackedContacts = 1;
}
- // Look for via patterning specifications
- if (strcasestr(lineptr, "via pattern") != NULL) {
- if (strcasestr(lineptr + 12, "normal") != NULL)
- ViaPattern = VIA_PATTERN_NORMAL;
- else if (strcasestr(lineptr + 12, "invert") != NULL)
- ViaPattern = VIA_PATTERN_INVERT;
- }
-
if ((i = sscanf(lineptr, "obstruction %lf %lf %lf %lf %s\n",
&darg, &darg2, &darg3, &darg4, sarg)) == 5) {
OK = 1;
@@ -457,11 +474,11 @@ int read_config(FILE *fconfig, int is_info)
// Allocate memory for 10 more pins
gateinfo->taps = (DSEG *)realloc(gateinfo->taps,
(CurrentPin + 10) * sizeof(DSEG));
- gateinfo->noderec = (NODE *)realloc(gateinfo->taps,
+ gateinfo->noderec = (NODE *)realloc(gateinfo->noderec,
(CurrentPin + 10) * sizeof(NODE));
- gateinfo->netnum = (int *)realloc(gateinfo->taps,
+ gateinfo->netnum = (int *)realloc(gateinfo->netnum,
(CurrentPin + 10) * sizeof(int));
- gateinfo->node = (char **)realloc(gateinfo->taps,
+ gateinfo->node = (char **)realloc(gateinfo->node,
(CurrentPin + 10) * sizeof(char *));
}
}
@@ -476,7 +493,7 @@ int read_config(FILE *fconfig, int is_info)
line[0] = line[1] = '\0';
}
- post_config();
+ post_config(FALSE);
return count;
} /* read_config() */