mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-22 14:17:43 +02:00
Initial commit at Tue Apr 25 08:41:48 EDT 2017 by tim on stravinsky
This commit is contained in:
+27
@@ -0,0 +1,27 @@
|
||||
lefCmd.o: lefCmd.c ../tcltk/tclmagic.h ../utils/magic.h \
|
||||
../utils/geometry.h ../tiles/tile.h ../utils/hash.h \
|
||||
../database/database.h ../windows/windows.h ../dbwind/dbwind.h \
|
||||
../utils/main.h ../textio/txcommands.h ../commands/commands.h
|
||||
lefTech.o: lefTech.c ../tcltk/tclmagic.h ../utils/magic.h \
|
||||
../utils/geometry.h ../tiles/tile.h ../utils/hash.h \
|
||||
../database/database.h ../utils/malloc.h ../lef/lefInt.h ../drc/drc.h
|
||||
lefWrite.o: lefWrite.c ../tcltk/tclmagic.h ../utils/magic.h \
|
||||
../utils/geometry.h ../tiles/tile.h ../utils/hash.h \
|
||||
../database/database.h ../utils/tech.h ../utils/utils.h \
|
||||
../utils/malloc.h ../utils/stack.h ../utils/signals.h \
|
||||
../windows/windows.h ../dbwind/dbwind.h ../graphics/graphics.h \
|
||||
../utils/main.h ../utils/undo.h ../cif/cif.h ../lef/lefInt.h
|
||||
defWrite.o: defWrite.c ../tcltk/tclmagic.h ../utils/magic.h \
|
||||
../utils/geometry.h ../tiles/tile.h ../utils/hash.h \
|
||||
../database/database.h ../utils/tech.h ../utils/malloc.h ../utils/undo.h \
|
||||
../cif/cif.h ../extflat/extflat.h ../lef/lefInt.h ../drc/drc.h
|
||||
lefRead.o: lefRead.c ../tcltk/tclmagic.h ../utils/magic.h \
|
||||
../utils/geometry.h ../tiles/tile.h ../utils/hash.h ../utils/undo.h \
|
||||
../database/database.h ../windows/windows.h ../graphics/graphics.h \
|
||||
../dbwind/dbwind.h ../utils/malloc.h ../textio/textio.h ../cif/cif.h \
|
||||
../cif/CIFint.h ../lef/lefInt.h
|
||||
defRead.o: defRead.c ../tcltk/tclmagic.h ../utils/magic.h \
|
||||
../utils/geometry.h ../tiles/tile.h ../utils/hash.h ../utils/undo.h \
|
||||
../database/database.h ../windows/windows.h ../dbwind/dbwind.h \
|
||||
../utils/malloc.h ../graphics/graphics.h ../utils/main.h ../cif/cif.h \
|
||||
../lef/lefInt.h
|
||||
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# LEF module Makefile
|
||||
#
|
||||
|
||||
MODULE = lef
|
||||
MAGICDIR = ..
|
||||
SRCS = lefCmd.c lefTech.c lefWrite.c defWrite.c lefRead.c defRead.c
|
||||
|
||||
include ${MAGICDIR}/defs.mak
|
||||
|
||||
LIBS += ${LD_EXTRA_LIBS} ${SUB_EXTRA_LIBS}
|
||||
CLEANS += magiclef${SHDLIB_EXT} tcllef.o
|
||||
|
||||
tcl-main: tcllef.o magiclef${SHDLIB_EXT}
|
||||
|
||||
tcllef.o: tcllef.c
|
||||
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} tcllef.c -c -o tcllef.o
|
||||
|
||||
magiclef${SHDLIB_EXT}: tcllef.o ${OBJS}
|
||||
@echo --- making Tcl auto-load module \(magiclef${SHDLIB_EXT}\)
|
||||
${RM} magiclef${SHDLIB_EXT}
|
||||
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} tcllef.o ${OBJS} \
|
||||
${EXTRA_LIBS} -lc ${LIBS}
|
||||
|
||||
install-tcl: $(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT}
|
||||
|
||||
$(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT}: magiclef${SHDLIB_EXT}
|
||||
${RM} $(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT}
|
||||
${CP} magiclef${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT}
|
||||
|
||||
include ${MAGICDIR}/rules.mak
|
||||
+1439
File diff suppressed because it is too large
Load Diff
+1956
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* lef.h --
|
||||
*
|
||||
* Contains definitions for things that are exported by the
|
||||
* lef module.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LEF_H
|
||||
#define _LEF_H
|
||||
|
||||
#include "utils/magic.h"
|
||||
|
||||
/* Procedures for reading the technology file: */
|
||||
|
||||
extern void LefTechInit();
|
||||
extern bool LefTechLine();
|
||||
extern void LefTechScale();
|
||||
|
||||
/* Initialization: */
|
||||
|
||||
extern void LefInit();
|
||||
|
||||
#endif /* _LEF_H */
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* lefCmd.c --
|
||||
*
|
||||
* Commands for the LEF module only.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/lef/lefCmd.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tcltk/tclmagic.h"
|
||||
#include "utils/magic.h"
|
||||
#include "utils/geometry.h"
|
||||
#include "tiles/tile.h"
|
||||
#include "utils/hash.h"
|
||||
#include "database/database.h"
|
||||
#include "windows/windows.h"
|
||||
#include "dbwind/dbwind.h"
|
||||
#include "utils/main.h"
|
||||
#include "textio/txcommands.h"
|
||||
#include "commands/commands.h"
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* CmdLef --
|
||||
*
|
||||
* Implement the "lef" and "def" commands: generate LEF-format output
|
||||
* for a layout, or read LEF- or DEF-format files.
|
||||
*
|
||||
* Usage:
|
||||
* lef [options]
|
||||
* def [options]
|
||||
*
|
||||
* Results:
|
||||
* Always return 0.
|
||||
*
|
||||
* Side effects:
|
||||
* Generates LEF-format output on disk somewhere, or reads
|
||||
* LEF- or DEF-format files, generating cell definitions and
|
||||
* uses in the process.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* These definitions must correspond to the ordering in cmdLefOption[] below */
|
||||
|
||||
#define LEF_READ 0
|
||||
#define LEF_WRITE 1
|
||||
#define LEF_WRITEALL 2
|
||||
#define LEF_HELP 3
|
||||
|
||||
void
|
||||
CmdLef(w, cmd)
|
||||
MagWindow *w;
|
||||
TxCommand *cmd;
|
||||
{
|
||||
int option;
|
||||
char **msg, *namep;
|
||||
CellUse *selectedUse;
|
||||
CellDef *selectedDef;
|
||||
bool is_lef;
|
||||
bool lefImport = FALSE; /* Indicates whether or not we
|
||||
* read cells from .mag files
|
||||
* when the FOREIGN statement
|
||||
* is encountered in a macro.
|
||||
*/
|
||||
bool lefTopCell = TRUE; /* Indicates whether or not we
|
||||
* write the top-level cell to
|
||||
* LEF, or just the subcells.
|
||||
*/
|
||||
bool allSpecial = FALSE; /* Indicates whether we should
|
||||
* treat all geometry as "special"
|
||||
* nets in DEF format output.
|
||||
*/
|
||||
|
||||
static char *cmdLefOption[] =
|
||||
{
|
||||
"read [filename] read a LEF file filename[.lef]\n"
|
||||
" read [filename] -import read a LEF file; import cells from .mag files",
|
||||
"write [cell] write LEF for current or indicated cell",
|
||||
"writeall write all cells including the top-level cell\n"
|
||||
" writeall -notop write all subcells of the top-level cell",
|
||||
"help print this help information",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *cmdDefOption[] =
|
||||
{
|
||||
"read [filename] read a DEF file filename[.def]",
|
||||
"write [cell] [-allspecial] write DEF for current or indicated cell",
|
||||
"writeall (use \"flatten -nosubckt\" + \"def"
|
||||
" write\" instead)",
|
||||
"help print this help information",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Determine whether this function has been called via the "lef" or
|
||||
* the "def" command.
|
||||
*/
|
||||
is_lef = (cmd->tx_argv[0][0] == 'd') ? FALSE : TRUE;
|
||||
|
||||
if (cmd->tx_argc < 2)
|
||||
option = LEF_HELP;
|
||||
else
|
||||
{
|
||||
option = Lookup(cmd->tx_argv[1], cmdLefOption);
|
||||
if (option < 0)
|
||||
{
|
||||
TxError("\"%s\" isn't a valid %s option.\n", cmd->tx_argv[1],
|
||||
cmd->tx_argv[0]);
|
||||
option = LEF_HELP;
|
||||
}
|
||||
}
|
||||
|
||||
if (option != LEF_HELP)
|
||||
{
|
||||
selectedUse = CmdGetSelectedCell((Transform *)NULL);
|
||||
if (selectedUse == NULL)
|
||||
{
|
||||
windCheckOnlyWindow(&w, DBWclientID);
|
||||
if (w == (MagWindow *) NULL)
|
||||
{
|
||||
if (ToolGetBox(&selectedDef,NULL) == FALSE)
|
||||
{
|
||||
TxError("Point to a window first\n");
|
||||
return;
|
||||
}
|
||||
selectedUse = selectedDef->cd_parents;
|
||||
}
|
||||
else
|
||||
selectedUse = (CellUse *)w->w_surfaceID;
|
||||
}
|
||||
}
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case LEF_READ:
|
||||
if (cmd->tx_argc != 3)
|
||||
{
|
||||
if (cmd->tx_argc == 4)
|
||||
{
|
||||
if (*(cmd->tx_argv[3]) == '-')
|
||||
if (!strncmp(cmd->tx_argv[3], "-import", 7))
|
||||
lefImport = TRUE;
|
||||
}
|
||||
else
|
||||
goto wrongNumArgs;
|
||||
}
|
||||
namep = cmd->tx_argv[2];
|
||||
if (is_lef)
|
||||
LefRead(namep, lefImport);
|
||||
else
|
||||
DefRead(namep);
|
||||
break;
|
||||
case LEF_WRITEALL:
|
||||
if (!is_lef)
|
||||
{
|
||||
TxError("Sorry, can't write hierarchical DEF at this time.\n");
|
||||
TxError("Try \"def write\"\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cmd->tx_argc == 3)
|
||||
if (*(cmd->tx_argv[2]) == '-')
|
||||
if (!strncmp(cmd->tx_argv[2], "-notop", 6))
|
||||
lefTopCell = FALSE;
|
||||
|
||||
LefWriteAll(selectedUse, lefTopCell);
|
||||
}
|
||||
break;
|
||||
case LEF_WRITE:
|
||||
if (!is_lef)
|
||||
{
|
||||
allSpecial = FALSE;
|
||||
if (cmd->tx_argc == 4)
|
||||
{
|
||||
if (*(cmd->tx_argv[3]) == '-')
|
||||
{
|
||||
if (!strncmp(cmd->tx_argv[3], "-allspec", 8))
|
||||
allSpecial = TRUE;
|
||||
else goto wrongNumArgs;
|
||||
}
|
||||
else goto wrongNumArgs;
|
||||
}
|
||||
else if (cmd->tx_argc != 3) goto wrongNumArgs;
|
||||
}
|
||||
else if (cmd->tx_argc != 2) goto wrongNumArgs;
|
||||
if (selectedUse == NULL)
|
||||
{
|
||||
TxError("No cell selected\n");
|
||||
return;
|
||||
}
|
||||
if (cmd->tx_argc == 2)
|
||||
namep = selectedUse->cu_def->cd_name;
|
||||
else
|
||||
namep = cmd->tx_argv[2];
|
||||
if (!is_lef)
|
||||
DefWriteCell(selectedUse->cu_def, namep, allSpecial);
|
||||
else
|
||||
LefWriteCell(selectedUse->cu_def, namep, selectedUse->cu_def
|
||||
== EditRootDef);
|
||||
break;
|
||||
case LEF_HELP:
|
||||
wrongNumArgs:
|
||||
TxPrintf("The \"%s\" options are:\n", cmd->tx_argv[0]);
|
||||
msg = (is_lef) ? &(cmdLefOption[0]) : &(cmdDefOption[0]);
|
||||
for (; *msg != NULL; msg++)
|
||||
{
|
||||
TxPrintf(" %s %s\n", cmd->tx_argv[0], *msg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* lefInt.h --
|
||||
*
|
||||
* This file defines things that are used by internal LEF routines in
|
||||
* various files.
|
||||
*
|
||||
* rcsid $Header: /usr/cvsroot/magic-8.0/lef/lefInt.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $
|
||||
*/
|
||||
|
||||
#ifndef _LEFINT_H
|
||||
#define _LEFINT_H
|
||||
|
||||
#include "utils/magic.h"
|
||||
|
||||
/* Some constants for LEF and DEF files */
|
||||
|
||||
#define LEF_LINE_MAX 2048 /* Maximum length fixed by LEF/DEF specifications */
|
||||
#define LEF_MAX_ERRORS 100 /* Max # errors to report; limits output if */
|
||||
/* something is really wrong about the file */
|
||||
|
||||
#define DEFAULT_WIDTH 3 /* Default metal width for routes if undefined */
|
||||
#define DEFAULT_SPACING 4 /* Default spacing between metal if undefined */
|
||||
|
||||
/* Structure holding the counts of regular and special nets */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int regular;
|
||||
int special;
|
||||
bool has_nets;
|
||||
} NetCount;
|
||||
|
||||
/* Various modes for writing nets. */
|
||||
#define DO_REGULAR 0
|
||||
#define DO_SPECIAL 1
|
||||
#define ALL_SPECIAL 2 /* treat all nets as SPECIALNETS */
|
||||
|
||||
/* For a linked list of rectangular areas, use the LinkedRect structure */
|
||||
/* defined in utils/geometry.h. */
|
||||
|
||||
/* Structure used for returning information about polygon geometry */
|
||||
|
||||
typedef struct _linkedPoint {
|
||||
Point pos;
|
||||
TileType type;
|
||||
struct _linkedPoint *point_next;
|
||||
} linkedPoint;
|
||||
|
||||
/* Structure used to maintain default routing information for each */
|
||||
/* routable layer type. */
|
||||
|
||||
typedef struct {
|
||||
int width; /* width, in lambda */
|
||||
int spacing; /* minimum spacing rule, in lambda */
|
||||
int pitch; /* route pitch, in lambda */
|
||||
bool hdirection; /* horizontal direction preferred */
|
||||
} lefRoute;
|
||||
|
||||
/* Structure used to maintain default generation information for each */
|
||||
/* via or viarule (contact) type. If "cell" is non-NULL, then the via */
|
||||
/* is saved in a cell (pointed to by "cell"), and "area" describes the */
|
||||
/* bounding box. Otherwise, the via is formed by magic type "type" */
|
||||
/* with a minimum area "area" for a single contact. */
|
||||
|
||||
typedef struct {
|
||||
Rect area; /* Area of single contact, or cell bbox */
|
||||
/* in units of 1/2 lambda */
|
||||
CellDef *cell; /* Cell for fixed via def, or NULL */
|
||||
LinkedRect *lr; /* Extra information for vias with */
|
||||
/* more complicated geometry. */
|
||||
TileType obsType; /* Secondary obstruction type */
|
||||
} lefVia;
|
||||
|
||||
/* Defined types for "lefClass" in the lefLayer structure */
|
||||
|
||||
#define CLASS_ROUTE 0 /* routing layer */
|
||||
#define CLASS_VIA 1 /* via or cut layer */
|
||||
#define CLASS_MASTER 2 /* masterslice layer */
|
||||
#define CLASS_OVERLAP 3 /* overlap layer */
|
||||
#define CLASS_BOUND 4 /* boundary-defining layer */
|
||||
#define CLASS_IGNORE 5 /* inactive layer */
|
||||
|
||||
/* Structure defining a route or via layer and matching it to a magic */
|
||||
/* layer type. This structure is saved in the LefInfo hash table. */
|
||||
/* To allow multiple names to refer to the same structure, we keep a */
|
||||
/* reference count of the number of times a hash table value points to */
|
||||
/* this structure. */
|
||||
|
||||
typedef struct {
|
||||
TileType type; /* magic tile type, or -1 for none */
|
||||
TileType obsType; /* magic type to use if this is an obstruction */
|
||||
short refCnt; /* reference count for memory deallocation */
|
||||
char * canonName; /* name to use when writing LEF output */
|
||||
unsigned char lefClass; /* is this a via, route, or masterslice layer */
|
||||
union {
|
||||
lefRoute route; /* for route layers */
|
||||
lefVia via; /* for contacts */
|
||||
} info;
|
||||
} lefLayer;
|
||||
|
||||
/* Inverse mapping structure for returning the primary LEF */
|
||||
/* layer corresponding to a magic tile type. */
|
||||
|
||||
typedef struct {
|
||||
char *lefName; /* Primary name of LEF layer */
|
||||
lefLayer *lefInfo; /* Pointer to information about the layer */
|
||||
} LefMapping;
|
||||
|
||||
/* External declaration of global variables */
|
||||
extern int lefCurrentLine;
|
||||
extern HashTable LefInfo;
|
||||
|
||||
/* Forward declarations */
|
||||
|
||||
int lefDefInitFunc(), lefDefPushFunc();
|
||||
FILE *lefFileOpen();
|
||||
|
||||
char *LefGetInput();
|
||||
int LefParseEndStatement();
|
||||
void LefSkipSection();
|
||||
void LefEndStatement();
|
||||
CellDef *lefFindCell();
|
||||
char *LefNextToken();
|
||||
char *LefLower();
|
||||
LinkedRect *LefReadGeometry();
|
||||
void LefEstimate();
|
||||
lefLayer *LefRedefined();
|
||||
void LefAddViaGeometry();
|
||||
Rect *LefReadRect();
|
||||
TileType LefReadLayer();
|
||||
|
||||
LefMapping *defMakeInverseLayerMap();
|
||||
|
||||
void LefError(char *, ...); /* Variable argument procedure requires */
|
||||
/* parameter list. */
|
||||
|
||||
#endif /* _LEFINT_H */
|
||||
+2067
File diff suppressed because it is too large
Load Diff
+448
@@ -0,0 +1,448 @@
|
||||
/*
|
||||
* lefTech.c --
|
||||
*
|
||||
* This module incorporates the LEF/DEF format for standard-cell place and
|
||||
* route. Defines technology file layer mapping between LEF and magic layer
|
||||
* types.
|
||||
*
|
||||
* Version 0.1 (December 5, 2003): LEF section of the technology file.
|
||||
* Lets the technology file state how layers declared in the LEF and DEF
|
||||
* files should correspond to magic layout units. If these are not
|
||||
* declared, magic will attempt to relate layer names in the LEF file to
|
||||
* magic layer names and their aliases. The LEF section allows the declaration
|
||||
* of obstruction layer names, which may be the same as actual layer names in
|
||||
* the LEF or DEF file, but which should declare a type that takes up space
|
||||
* on the routing plane but does not connect to any other material. Otherwise,
|
||||
* some LEF/DEF files will end up merging ports together with the obstruction
|
||||
* layer.
|
||||
*
|
||||
* Layer name case sensitivity should depend on the
|
||||
* NAMESCASESENSITIVE [ON|OFF] LEF instruction!
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/lef/lefTech.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tcltk/tclmagic.h"
|
||||
#include "utils/magic.h"
|
||||
#include "utils/geometry.h"
|
||||
#include "tiles/tile.h"
|
||||
#include "utils/hash.h"
|
||||
#include "database/database.h"
|
||||
#include "utils/malloc.h"
|
||||
#include "lef/lefInt.h"
|
||||
#include "drc/drc.h"
|
||||
|
||||
/* ---------------------------------------------------------------------*/
|
||||
|
||||
/* Layer and Via routing information table. */
|
||||
|
||||
HashTable LefInfo;
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
* LefInit --
|
||||
*
|
||||
* Things that need to be initialized on startup, before the technology
|
||||
* file is read in.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Hash Table initialization.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
LefInit()
|
||||
{
|
||||
/* Ensure that the table has a null entry so we don't run HashKill */
|
||||
/* on it when we to the tech initialization. */
|
||||
|
||||
LefInfo.ht_table = (HashEntry **) NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
* LefTechInit --
|
||||
*
|
||||
* Called once at beginning of technology file read-in to initialize
|
||||
* data structures.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Clears out the LEF layer info table. Because multiple LEF names
|
||||
* can point to the same record, this is handled by reference count.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
LefTechInit()
|
||||
{
|
||||
HashSearch hs;
|
||||
HashEntry *he;
|
||||
lefLayer *lefl;
|
||||
|
||||
if (LefInfo.ht_table != (HashEntry **) NULL)
|
||||
{
|
||||
HashStartSearch(&hs);
|
||||
while (he = HashNext(&LefInfo, &hs))
|
||||
{
|
||||
lefl = (lefLayer *)HashGetValue(he);
|
||||
if (!lefl) continue;
|
||||
lefl->refCnt--;
|
||||
if (lefl->refCnt <= 0)
|
||||
{
|
||||
/* Via detailed information, if it exists, */
|
||||
/* needs to have its allocated memory free'd. */
|
||||
|
||||
if (lefl->lefClass == CLASS_VIA)
|
||||
if (lefl->info.via.lr != NULL)
|
||||
freeMagic(lefl->info.via.lr);
|
||||
|
||||
freeMagic(lefl);
|
||||
}
|
||||
}
|
||||
HashKill(&LefInfo);
|
||||
}
|
||||
HashInit(&LefInfo, 32, HT_STRINGKEYS);
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
* lefRemoveGeneratedVias --
|
||||
*
|
||||
* Remove the Generated Vias created during a DEF file write
|
||||
* from the LEF layer hash table. By design, each of these
|
||||
* generated layers gets a refCnt of zero, so they are easy
|
||||
* to find.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Memory freed in the hash table.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
lefRemoveGeneratedVias()
|
||||
{
|
||||
HashSearch hs;
|
||||
HashEntry *he;
|
||||
lefLayer *lefl;
|
||||
|
||||
if (LefInfo.ht_table != (HashEntry **) NULL)
|
||||
{
|
||||
HashStartSearch(&hs);
|
||||
while (he = HashNext(&LefInfo, &hs))
|
||||
{
|
||||
lefl = (lefLayer *)HashGetValue(he);
|
||||
if (!lefl) continue;
|
||||
if (lefl->refCnt == 0)
|
||||
{
|
||||
if (lefl->lefClass == CLASS_VIA)
|
||||
if (lefl->info.via.lr != NULL)
|
||||
freeMagic(lefl->info.via.lr);
|
||||
|
||||
freeMagic(lefl);
|
||||
HashSetValue(he, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
* LefTechLine --
|
||||
*
|
||||
* This procedure is invoked by the technology module once for
|
||||
* each line in the "lef" 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 LEF layer table, prints error messages if necessary.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define LEFTECH_OBS 0
|
||||
#define LEFTECH_LAYER 1
|
||||
#define LEFTECH_ROUTE 2
|
||||
#define LEFTECH_ROUTING 3
|
||||
#define LEFTECH_MASTER 4
|
||||
#define LEFTECH_CUT 5
|
||||
#define LEFTECH_CONTACT 6
|
||||
#define LEFTECH_OVERLAP 7
|
||||
#define LEFTECH_BOUND 8
|
||||
#define LEFTECH_IGNORE 9
|
||||
|
||||
bool
|
||||
LefTechLine(sectionName, argc, argv)
|
||||
char *sectionName; /* Name of this section (unused). */
|
||||
int argc; /* Number of arguments on line. */
|
||||
char *argv[]; /* Pointers to fields of line. */
|
||||
{
|
||||
bool isObstruction, isContact, isInactive;
|
||||
HashEntry *he;
|
||||
TileType mtype, mtype2 = -1;
|
||||
TileTypeBitMask mmask;
|
||||
lefLayer *lefl, *newlefl;
|
||||
int i, option;
|
||||
static char *keywords[] = {
|
||||
"obstruction", "layer", "route", "routing", "masterslice",
|
||||
"cut", "contact", "overlap", "bound", "ignore", NULL
|
||||
};
|
||||
|
||||
option = Lookup(argv[0], keywords);
|
||||
if (option < 0)
|
||||
{
|
||||
TechError("Unknown LEF section keyword: %s. Line ignored.\n", argv[0]);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((option != LEFTECH_IGNORE) && (argc < 3))
|
||||
{
|
||||
TechError("No LEF layer names present!\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
isInactive = FALSE;
|
||||
switch (option)
|
||||
{
|
||||
case LEFTECH_IGNORE:
|
||||
isInactive = TRUE;
|
||||
break;
|
||||
case LEFTECH_OBS:
|
||||
isObstruction = TRUE;
|
||||
break;
|
||||
default:
|
||||
isObstruction = FALSE;
|
||||
}
|
||||
|
||||
TTMaskZero(&mmask);
|
||||
i = 0;
|
||||
|
||||
if (!isInactive)
|
||||
{
|
||||
DBTechNoisyNameMask(argv[1], &mmask);
|
||||
for (mtype2 = TT_TECHDEPBASE; mtype2 < DBNumUserLayers; mtype2++)
|
||||
{
|
||||
if (TTMaskHasType(&mmask, mtype2))
|
||||
{
|
||||
if (++i == 1)
|
||||
mtype = mtype2;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mtype2 == DBNumUserLayers) mtype2 = -1;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
LefError("Bad magic layer type \"%s\" in LEF layer definition.\n", argv[1]);
|
||||
return TRUE;
|
||||
}
|
||||
else if ((i == 2) && (option != LEFTECH_OBS))
|
||||
{
|
||||
LefError("Can only define multiple types for via obstruction layers.\n");
|
||||
return TRUE;
|
||||
}
|
||||
else if (i > 2)
|
||||
{
|
||||
LefError("Too many types in LEF layer definition.\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
isContact = DBIsContact(mtype);
|
||||
if (option == LEFTECH_LAYER)
|
||||
option = (isContact) ? LEFTECH_CUT : LEFTECH_ROUTE;
|
||||
else if (isContact && (option != LEFTECH_CUT && option != LEFTECH_CONTACT))
|
||||
TechError("Attempt to define cut type %s as %s.\n",
|
||||
DBTypeLongNameTbl[mtype], keywords[option]);
|
||||
else if (!isContact && (option == LEFTECH_CUT || option == LEFTECH_CONTACT))
|
||||
TechError("Attempt to define non-cut type %s as a cut.\n",
|
||||
DBTypeLongNameTbl[mtype]);
|
||||
}
|
||||
|
||||
/* All other aliases are stuffed in the hash table but point to the */
|
||||
/* same record as the first. If any name is repeated, then report */
|
||||
/* an error condition. */
|
||||
|
||||
newlefl = NULL;
|
||||
for (i = 2 - isInactive; i < argc; i++)
|
||||
{
|
||||
he = HashFind(&LefInfo, argv[i]);
|
||||
lefl = (lefLayer *)HashGetValue(he);
|
||||
if (lefl == NULL)
|
||||
{
|
||||
/* Create an entry in the hash table for this layer or obstruction */
|
||||
|
||||
if (newlefl == NULL)
|
||||
{
|
||||
float oscale = CIFGetOutputScale(1000);
|
||||
|
||||
newlefl = (lefLayer *)mallocMagic(sizeof(lefLayer));
|
||||
newlefl->refCnt = 0;
|
||||
newlefl->type = -1;
|
||||
newlefl->obsType = -1;
|
||||
if (!isInactive)
|
||||
{
|
||||
if (isObstruction)
|
||||
newlefl->obsType = mtype;
|
||||
else
|
||||
newlefl->type = mtype;
|
||||
}
|
||||
newlefl->canonName = (char *)he->h_key.h_name;
|
||||
|
||||
/* Fill in default values per type */
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case LEFTECH_CUT:
|
||||
newlefl->lefClass = CLASS_VIA;
|
||||
newlefl->info.via.area = GeoNullRect;
|
||||
newlefl->info.via.cell = (CellDef *)NULL;
|
||||
newlefl->info.via.lr = (LinkedRect *)NULL;
|
||||
newlefl->info.via.obsType = mtype2;
|
||||
break;
|
||||
case LEFTECH_CONTACT:
|
||||
newlefl->lefClass = CLASS_VIA;
|
||||
newlefl->info.via.area.r_xtop = DRCGetDefaultLayerWidth(mtype);
|
||||
newlefl->info.via.area.r_ytop = newlefl->info.via.area.r_xtop;
|
||||
newlefl->info.via.area.r_xbot = -newlefl->info.via.area.r_xtop;
|
||||
newlefl->info.via.area.r_ybot = -newlefl->info.via.area.r_ytop;
|
||||
newlefl->info.via.cell = (CellDef *)NULL;
|
||||
newlefl->info.via.lr = (LinkedRect *)NULL;
|
||||
newlefl->info.via.obsType = mtype2;
|
||||
break;
|
||||
case LEFTECH_ROUTE:
|
||||
case LEFTECH_ROUTING:
|
||||
case LEFTECH_OBS:
|
||||
newlefl->lefClass = CLASS_ROUTE;
|
||||
newlefl->info.route.width = DRCGetDefaultLayerWidth(mtype);
|
||||
if (newlefl->info.route.width == 0)
|
||||
newlefl->info.route.width = DEFAULT_WIDTH;
|
||||
newlefl->info.route.spacing =
|
||||
DRCGetDefaultLayerSpacing(mtype, mtype);
|
||||
if (newlefl->info.route.spacing == 0)
|
||||
newlefl->info.route.spacing = DEFAULT_SPACING;
|
||||
newlefl->info.route.pitch = 0;
|
||||
newlefl->info.route.hdirection = TRUE;
|
||||
break;
|
||||
case LEFTECH_BOUND:
|
||||
newlefl->lefClass = CLASS_BOUND;
|
||||
break;
|
||||
case LEFTECH_MASTER:
|
||||
newlefl->lefClass = CLASS_MASTER;
|
||||
break;
|
||||
case LEFTECH_OVERLAP:
|
||||
newlefl->lefClass = CLASS_OVERLAP;
|
||||
break;
|
||||
case LEFTECH_IGNORE:
|
||||
newlefl->lefClass = CLASS_IGNORE;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
HashSetValue(he, newlefl);
|
||||
newlefl->refCnt++;
|
||||
}
|
||||
else if (lefl->lefClass != CLASS_IGNORE)
|
||||
{
|
||||
if ((lefl->obsType == -1) && isObstruction)
|
||||
{
|
||||
// if (DBIsContact(lefl->type) != isContact)
|
||||
// TechError("Error: Cannot mix layer and via types\n");
|
||||
// else
|
||||
{
|
||||
lefl->obsType = mtype;
|
||||
if (lefl->lefClass == CLASS_VIA)
|
||||
lefl->info.via.obsType = mtype2;
|
||||
}
|
||||
}
|
||||
else if ((lefl->type == -1) && !isObstruction)
|
||||
{
|
||||
// if (DBIsContact(lefl->obsType) != isContact)
|
||||
// TechError("Error: Cannot mix layer and via types\n");
|
||||
// else
|
||||
lefl->type = mtype;
|
||||
|
||||
}
|
||||
else
|
||||
TechError("LEF name %s already used for magic type %s\n",
|
||||
argv[i], DBTypeLongNameTbl[lefl->type]);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
* LefTechScale --
|
||||
*
|
||||
* Change parameters of the LEF section as required when
|
||||
* redefining magic's internal grid relative to the technology lambda.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
LefTechScale(scalen, scaled)
|
||||
int scalen, scaled;
|
||||
{
|
||||
HashSearch hs;
|
||||
HashEntry *he;
|
||||
lefLayer *lefl;
|
||||
|
||||
if (LefInfo.ht_table != (HashEntry **) NULL)
|
||||
{
|
||||
HashStartSearch(&hs);
|
||||
while (he = HashNext(&LefInfo, &hs))
|
||||
{
|
||||
lefl = (lefLayer *)HashGetValue(he);
|
||||
if (!lefl) continue;
|
||||
if (lefl->refCnt >= 1)
|
||||
{
|
||||
/* Avoid scaling more than once. . . */
|
||||
if (lefl->refCnt > 1) lefl->refCnt = -lefl->refCnt;
|
||||
if (lefl->lefClass == CLASS_VIA)
|
||||
{
|
||||
DBScalePoint(&lefl->info.via.area.r_ll, scaled, scalen);
|
||||
DBScalePoint(&lefl->info.via.area.r_ur, scaled, scalen);
|
||||
}
|
||||
else if (lefl->lefClass == CLASS_ROUTE)
|
||||
{
|
||||
lefl->info.route.width *= scaled;
|
||||
lefl->info.route.width /= scalen;
|
||||
lefl->info.route.spacing *= scaled;
|
||||
lefl->info.route.spacing /= scalen;
|
||||
lefl->info.route.pitch *= scaled;
|
||||
lefl->info.route.pitch /= scalen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return all refCnt values to normal */
|
||||
HashStartSearch(&hs);
|
||||
while (he = HashNext(&LefInfo, &hs))
|
||||
{
|
||||
lefl = (lefLayer *)HashGetValue(he);
|
||||
if (!lefl) continue;
|
||||
if (lefl->refCnt < 0)
|
||||
lefl->refCnt = -lefl->refCnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1062
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
/*--------------------------------------------------------------*/
|
||||
/* tcllef.c */
|
||||
/* */
|
||||
/* Allows the "lef" feature to be loaded as a module */
|
||||
/* under the Tcl/Tk version of magic. Loading is */
|
||||
/* automatic upon invoking the "lef" command. */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
#ifdef LEF_AUTO
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tcltk/tclmagic.h"
|
||||
#include "utils/magic.h"
|
||||
#include "utils/geometry.h"
|
||||
#include "tiles/tile.h"
|
||||
#include "utils/hash.h"
|
||||
#include "database/database.h"
|
||||
#include "windows/windows.h"
|
||||
#include "commands/commands.h"
|
||||
#include "utils/tech.h"
|
||||
#include "dbwind/dbwind.h"
|
||||
|
||||
/* External routines */
|
||||
|
||||
extern void CmdLef();
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Tcl package initialization function
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
Magiclef_Init(interp)
|
||||
Tcl_Interp *interp;
|
||||
{
|
||||
/* Sanity checks! */
|
||||
if (interp == NULL) return TCL_ERROR;
|
||||
if (Tcl_PkgRequire(interp, "Tclmagic", MAGIC_VERSION, 0) == NULL)
|
||||
return TCL_ERROR;
|
||||
if (Tcl_InitStubs(interp, "8.1", 0) == NULL) return TCL_ERROR;
|
||||
|
||||
TxPrintf("Auto-loading LEF/DEF module\n");
|
||||
TxFlushOut();
|
||||
|
||||
/* Replace the auto-load function with the ones defined in */
|
||||
/* this package in the command functions list. */
|
||||
|
||||
if (WindReplaceCommand(DBWclientID, "lef", CmdLef) < 0)
|
||||
return TCL_ERROR;
|
||||
|
||||
if (WindReplaceCommand(DBWclientID, "def", CmdLef) < 0)
|
||||
return TCL_ERROR;
|
||||
|
||||
Tcl_PkgProvide(interp, "MagicLEF", MAGIC_VERSION);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#endif /* LEF_AUTO */
|
||||
Reference in New Issue
Block a user