2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* wireTech.c --
|
|
|
|
|
*
|
|
|
|
|
* This file contains procedures that parse the wiring sections of
|
|
|
|
|
* technology files.
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
|
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
|
|
|
* * software and its documentation for any purpose and without *
|
|
|
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
|
|
|
* * notice appear in all copies. The University of California *
|
|
|
|
|
* * makes no representations about the suitability of this *
|
|
|
|
|
* * software for any purpose. It is provided "as is" without *
|
|
|
|
|
* * express or implied warranty. Export of this software outside *
|
|
|
|
|
* * of the United States of America may require an export license. *
|
2017-04-25 14:41:48 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef lint
|
2025-01-31 20:04:54 +01:00
|
|
|
static const char rcsid[] __attribute__ ((unused)) = "$Header$";
|
2017-04-25 14:41:48 +02:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "utils/magic.h"
|
|
|
|
|
#include "utils/utils.h"
|
|
|
|
|
#include "utils/geometry.h"
|
|
|
|
|
#include "tiles/tile.h"
|
|
|
|
|
#include "utils/hash.h"
|
|
|
|
|
#include "database/database.h"
|
|
|
|
|
#include "utils/tech.h"
|
|
|
|
|
#include "wiring/wiring.h"
|
|
|
|
|
#include "utils/malloc.h"
|
|
|
|
|
|
|
|
|
|
/* Linked list to store contact information collected by this module: */
|
2022-04-01 02:02:12 +02:00
|
|
|
Contact *WireContacts = NULL;
|
2019-06-04 15:15:56 +02:00
|
|
|
int WireUnits; // Units per lambda for wiring sizes
|
2017-04-25 14:41:48 +02:00
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
* WireTechInit --
|
|
|
|
|
*
|
|
|
|
|
* Called once at beginning of technology file read-in to initialize
|
|
|
|
|
* data structures.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Clears out the contact table.
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2025-01-31 20:00:47 +01:00
|
|
|
WireTechInit(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
Contact *contact;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
while (WireContacts != NULL)
|
|
|
|
|
{
|
|
|
|
|
freeMagic((char *) WireContacts);
|
|
|
|
|
WireContacts = WireContacts->con_next;
|
|
|
|
|
}
|
2019-06-04 15:15:56 +02:00
|
|
|
WireUnits = 1;
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
* WireTechLine --
|
|
|
|
|
*
|
|
|
|
|
* This procedure is invoked by the technology module once for
|
|
|
|
|
* each line in the "wiring" section of the technology file.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Always returns TRUE (otherwise the technology module would
|
|
|
|
|
* abort Magic with a fatal error).
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Builds up the contact table, prints error messages if necessary.
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
|
|
|
|
bool
|
2025-01-31 20:00:47 +01:00
|
|
|
WireTechLine(
|
2025-01-31 20:02:19 +01:00
|
|
|
const char *sectionName, /* Name of this section (unused). */
|
2025-01-31 20:00:47 +01:00
|
|
|
int argc, /* Number of arguments on line. */
|
|
|
|
|
char *argv[]) /* Pointers to fields of line. */
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
Contact *new;
|
2019-04-24 16:48:45 +02:00
|
|
|
int hasExtend = 0;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
2019-06-04 15:15:56 +02:00
|
|
|
if (!strcmp(argv[0], "scalefactor"))
|
|
|
|
|
{
|
|
|
|
|
if (argc != 2)
|
|
|
|
|
{
|
|
|
|
|
TechError("\"scalefactor\" line must have exactly 2 arguments.\n");
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
if (!StrIsInt(argv[1]))
|
|
|
|
|
{
|
|
|
|
|
TechError("\"scalefactor\" argument must be an integer.\n");
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
WireUnits = atoi(argv[1]);
|
2019-06-05 21:03:51 +02:00
|
|
|
return TRUE;
|
2019-06-04 15:15:56 +02:00
|
|
|
}
|
|
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
if (strcmp(argv[0], "contact") != 0)
|
|
|
|
|
{
|
|
|
|
|
TechError("Unknown wiring keyword: %s. Line ignored.\n", argv[0]);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2019-04-24 16:48:45 +02:00
|
|
|
if ((argc != 7) && (argc != 9))
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2019-04-24 16:48:45 +02:00
|
|
|
TechError("\"contact\" lines must have exactly 7 or 9 arguments.\n");
|
2017-04-25 14:41:48 +02:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
2019-04-24 16:48:45 +02:00
|
|
|
if (argc == 9) hasExtend = 1;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
new = (Contact *) mallocMagic(sizeof(Contact));
|
|
|
|
|
new->con_type = DBTechNoisyNameType(argv[1]);
|
|
|
|
|
new->con_layer1 = DBTechNoisyNameType(argv[3]);
|
2019-04-24 16:48:45 +02:00
|
|
|
new->con_layer2 = DBTechNoisyNameType(argv[5 + hasExtend]);
|
|
|
|
|
new->con_extend1 = new->con_extend2 = 0;
|
2017-04-25 14:41:48 +02:00
|
|
|
if ((new->con_type < 0) || (new->con_layer1 < 0) || (new->con_layer2 < 0))
|
|
|
|
|
{
|
|
|
|
|
errorReturn:
|
|
|
|
|
freeMagic((char *) new);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!StrIsInt(argv[2]))
|
|
|
|
|
{
|
2019-04-24 16:48:45 +02:00
|
|
|
TechError("Contact size must be an integer.\n");
|
2017-04-25 14:41:48 +02:00
|
|
|
goto errorReturn;
|
|
|
|
|
}
|
|
|
|
|
else new->con_size = atoi(argv[2]);
|
|
|
|
|
if (!StrIsInt(argv[4]))
|
|
|
|
|
{
|
2019-04-24 16:48:45 +02:00
|
|
|
TechError("Contact surround distance must be an integer.\n");
|
2017-04-25 14:41:48 +02:00
|
|
|
goto errorReturn;
|
|
|
|
|
}
|
|
|
|
|
else new->con_surround1 = atoi(argv[4]);
|
2019-04-24 16:48:45 +02:00
|
|
|
if (!StrIsInt(argv[6 + hasExtend]))
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2019-04-24 16:48:45 +02:00
|
|
|
TechError("Contact surround distance must be an integer.\n");
|
2017-04-25 14:41:48 +02:00
|
|
|
goto errorReturn;
|
|
|
|
|
}
|
2019-04-24 16:48:45 +02:00
|
|
|
else new->con_surround2 = atoi(argv[6 + hasExtend]);
|
|
|
|
|
|
|
|
|
|
if (argc == 9)
|
|
|
|
|
{
|
|
|
|
|
if (!StrIsInt(argv[5]))
|
|
|
|
|
{
|
|
|
|
|
TechError("Contact extend distance must be an integer.\n");
|
|
|
|
|
goto errorReturn;
|
|
|
|
|
}
|
|
|
|
|
else new->con_extend1 = atoi(argv[5]);
|
|
|
|
|
if (!StrIsInt(argv[8]))
|
|
|
|
|
{
|
|
|
|
|
TechError("Contact extend distance must be an integer.\n");
|
|
|
|
|
goto errorReturn;
|
|
|
|
|
}
|
|
|
|
|
else new->con_extend2 = atoi(argv[8]);
|
|
|
|
|
}
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
new->con_next = WireContacts;
|
|
|
|
|
WireContacts = new;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
* WireTechFinal --
|
|
|
|
|
*
|
|
|
|
|
* This procedure is called by the technology module after all the
|
|
|
|
|
* lines of the tech file have been read. It doesn't do anything
|
|
|
|
|
* right now.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2025-01-31 20:00:47 +01:00
|
|
|
WireTechFinal(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
/* Debugging code to print info about layers: */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Contact *con;
|
|
|
|
|
|
|
|
|
|
for (con = WireContacts; con != NULL; con = con->con_next)
|
|
|
|
|
{
|
|
|
|
|
TxPrintf("Contact type \"%s\", size %d connects\n",
|
|
|
|
|
DBTypeLongName(con->con_type), con->con_size);
|
|
|
|
|
TxPrintf(" \"%s\" (overlap %d) and\n",
|
|
|
|
|
DBTypeLongName(con->con_layer1), con->con_surround1);
|
|
|
|
|
TxPrintf(" \"%s\" (overlap %d)\n",
|
|
|
|
|
DBTypeLongName(con->con_layer2), con->con_surround2);
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*----------------------------------------------------------------------------
|
|
|
|
|
* WireTechScale --
|
|
|
|
|
*
|
|
|
|
|
* Change parameters of the wiring section as required when
|
|
|
|
|
* redefining magic's internal grid relative to the technology lambda.
|
|
|
|
|
*
|
|
|
|
|
*----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2025-01-31 20:00:47 +01:00
|
|
|
WireTechScale(
|
|
|
|
|
int scalen,
|
|
|
|
|
int scaled)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
Contact *con;
|
|
|
|
|
|
|
|
|
|
for (con = WireContacts; con != NULL; con = con->con_next)
|
|
|
|
|
{
|
|
|
|
|
con->con_size *= scaled;
|
|
|
|
|
con->con_size /= scalen;
|
|
|
|
|
|
|
|
|
|
con->con_surround1 *= scaled;
|
|
|
|
|
con->con_surround1 /= scalen;
|
|
|
|
|
|
|
|
|
|
con->con_surround2 *= scaled;
|
|
|
|
|
con->con_surround2 /= scalen;
|
2019-04-24 16:48:45 +02:00
|
|
|
|
|
|
|
|
con->con_extend1 *= scaled;
|
|
|
|
|
con->con_extend1 /= scalen;
|
|
|
|
|
|
|
|
|
|
con->con_extend2 *= scaled;
|
|
|
|
|
con->con_extend2 /= scalen;
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
|
|
|
|
}
|