pax_global_header00006660000000000000000000000064130574655560014532gustar00rootroot0000000000000052 comment=072ba15879c1dd685bc2b0c86d599b2aeb631f8f graywolf-0.1.4+20170307gite1bf319/000077500000000000000000000000001305746555600157645ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/CMakeLists.txt000066400000000000000000000015531305746555600205300ustar00rootroot00000000000000cmake_minimum_required (VERSION 2.6) project (graywolf) find_package(PkgConfig) INCLUDE(CheckIncludeFiles) pkg_check_modules(GSL gsl) if (NOT GSL_FOUND) MESSAGE(FATAL_ERROR "The development files for the GNU Scientific Library (libgsl) are required to build graywolf.") endif() # Include RPATH in build so that ldconfig is not necessary after install SET(CMAKE_SKIP_BUILD_RPATH FALSE) SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/config-build.h) install(DIRECTORY flow DESTINATION lib/graywolf/bin) install(CODE "EXECUTE_PROCESS(COMMAND ln -sf flow.noroute flow WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/lib/graywolf/bin/flow)") add_subdirectory(src) add_subdirectory(script) graywolf-0.1.4+20170307gite1bf319/COPYING000066400000000000000000000432541305746555600170270ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. graywolf-0.1.4+20170307gite1bf319/ChangeLog000066400000000000000000000005501305746555600175360ustar00rootroot000000000000000.1.2: Changed the license of src/Ylib/radixsort.c to the 3-clause BSD license since the 4-clause license was officially rescinded 22 July 1999. 0.1.1: More copyright and license info Renamed shared library 0.1.0: Added proper documentation of license 0.0.3: Improved algorithm 0.0.2: Include RPATH in binaries 0.0.1: First version of graywolf graywolf-0.1.4+20170307gite1bf319/LICENSE000066400000000000000000000030641305746555600167740ustar00rootroot00000000000000Copyright 1987-1992 Yale University This software was originally developed at Yale University (c) and called TimberWolf. The license text is given below. The text was received 2015-06-03 from: """ Director of Technology Licensing Office of Cooperative Research Yale University School of Medicine """ This work is distributed in the hope that it will be useful; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version, on the following conditions: (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, SALE OR OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY PATENT OR OTHER RIGHTS NOT VESTED IN YALE. (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND WARRANTIES WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES WHATSOEVER TO ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN ARTICLE (a) AND (b) above. (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, EMPLOYEES AND AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING. graywolf-0.1.4+20170307gite1bf319/README.md000066400000000000000000000014401305746555600172420ustar00rootroot00000000000000This is graywolf - a fork of TimberWolf 6.3.5 TimberWolf was developed at Yale University, and was distributed as open source for a time until it was taken commercial. The last open-source version of TimberWolf does not perform detail routing, but is a professional-grade placement tool. In order to continue improving the open-source version, graywolf has been forked off from version 6.3.5 of TimberWolf. The main improvement in graywolf is that the build process is more streamlined and that it behaves as a normal linux tool - you can call it from anywhere and no environment variables must be set first. What it does ------------ graywolf is used for placement in VLSI design. It's mainly used together with qflow. Install procedure ----------------- cmake . make sudo make install graywolf-0.1.4+20170307gite1bf319/config.h.in000066400000000000000000000000721305746555600200060ustar00rootroot00000000000000 #define TWFLOWDIR "${CMAKE_INSTALL_PREFIX}/lib/graywolf" graywolf-0.1.4+20170307gite1bf319/flow/000077500000000000000000000000001305746555600167335ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/flow/flow.noroute/000077500000000000000000000000001305746555600213745ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/flow/flow.noroute/macro.fdbg000077500000000000000000000005031305746555600233220ustar00rootroot00000000000000numobjects 2 pobject edit_mcfiles 1: 0 path : drawn : 150 550 450 650 edge 0: ifiles: ofiles: $.par args : $ pobject TimberWolfMC 2: 1 path : drawn : 150 350 450 450 edge 1: ifiles: $.cel $.par $.mpar* $.mnet* $.net* ofiles: $.mdat args : -wvd $ @WINDOWID drawn : 300 450 300 550 300 450 320 470 300 450 280 470 graywolf-0.1.4+20170307gite1bf319/flow/flow.noroute/macro.flow000077500000000000000000000005011305746555600233650ustar00rootroot00000000000000numobjects 2 pobject edit_mcfiles 1: 0 path : drawn : 150 550 450 650 edge 0: ifiles: ofiles: $.par args : $ pobject TimberWolfMC 2: 1 path : drawn : 150 350 450 450 edge 1: ifiles: $.cel $.par $.mpar* $.mnet* $.net* ofiles: $.mdat args : -w $ @WINDOWID drawn : 300 450 300 550 300 450 320 470 300 450 280 470 graywolf-0.1.4+20170307gite1bf319/flow/flow.noroute/macro.fnog000077500000000000000000000004671305746555600233620ustar00rootroot00000000000000numobjects 2 pobject edit_mcfiles 1: 0 path : drawn : 150 550 450 650 edge 0: ifiles: ofiles: $.par args : $ pobject TimberWolfMC 2: 1 path : drawn : 150 350 450 450 edge 1: ifiles: $.cel $.par $.mpar* $.mnet* $.net* ofiles: $.mdat args : -n $ drawn : 300 450 300 550 300 450 320 470 300 450 280 470 graywolf-0.1.4+20170307gite1bf319/flow/flow.noroute/mixed.flow000077500000000000000000000013531305746555600234000ustar00rootroot00000000000000numobjects 4 pobject edit_twfiles 1: 0 path : drawn : 450 850 750 950 edge 0: ifiles: ofiles: $.par args : $ drawn : 600 950 600 1050 600 950 620 970 600 950 580 970 pobject Mincut 2: 1 path : drawn : 450 650 750 750 edge 1: ifiles: $.cel $.stat ofiles: $.mcel $.scel args : $ drawn : 600 750 600 850 600 750 620 770 600 750 580 770 pobject TimberWolfMC 3: 2 path : drawn : 450 450 750 550 edge 2: ifiles: $.mcel $.mpar ofiles: $.mdat $.blk args : -w $ @WINDOWID drawn : 600 550 600 650 600 550 620 570 600 550 580 570 pobject TimberWolfSC 4: 3 path : drawn : 450 250 750 350 edge 3: ifiles: $.blk $.scel $.par $.net ofiles: $.out $.pin $.pl1 args : -w $ @WINDOWID drawn : 600 350 600 450 600 350 620 370 600 350 580 370 graywolf-0.1.4+20170307gite1bf319/flow/flow.noroute/mixed.fnog000077500000000000000000000013371305746555600233640ustar00rootroot00000000000000numobjects 4 pobject edit_twfiles 1: 0 path : drawn : 450 850 750 950 edge 0: ifiles: ofiles: $.par args : $ drawn : 600 950 600 1050 600 950 620 970 600 950 580 970 pobject Mincut 2: 1 path : drawn : 450 650 750 750 edge 1: ifiles: $.cel $.stat ofiles: $.mcel $.scel args : $ drawn : 600 750 600 850 600 750 620 770 600 750 580 770 pobject TimberWolfMC 3: 2 path : drawn : 450 450 750 550 edge 2: ifiles: $.mcel $.mpar $.mnet ofiles: $.mdat $.blk args : -b $ drawn : 600 550 600 650 600 550 620 570 600 550 580 570 pobject TimberWolfSC 4: 3 path : drawn : 450 250 750 350 edge 3: ifiles: $.blk $.scel $.par $.net ofiles: $.out $.pin $.pl1 args : -n $ drawn : 600 350 600 450 600 350 620 370 600 350 580 370 graywolf-0.1.4+20170307gite1bf319/flow/flow.noroute/standard.fdbg000077500000000000000000000013561305746555600240300ustar00rootroot00000000000000numobjects 4 pobject edit_twfiles 1: 0 path : drawn : 450 850 750 950 edge 0: ifiles: ofiles: $.par args : $ drawn : 600 950 600 1050 600 950 620 970 600 950 580 970 pobject Mincut 2: 1 path : drawn : 450 650 750 750 edge 1: ifiles: $.cel $.stat ofiles: $.mcel $.scel args : $ drawn : 600 750 600 850 600 750 620 770 600 750 580 770 pobject TimberWolfMC 3: 2 path : drawn : 450 450 750 550 edge 2: ifiles: $.mcel $.mpar ofiles: $.mdat $.blk args : -wd $ @WINDOWID drawn : 600 550 600 650 600 550 620 570 600 550 580 570 pobject TimberWolfSC 4: 3 path : drawn : 450 250 750 350 edge 3: ifiles: $.blk $.scel $.par $.net ofiles: $.out $.pin $.pl1 args : -wd $ @WINDOWID drawn : 600 350 600 450 600 350 620 370 600 350 580 370 graywolf-0.1.4+20170307gite1bf319/flow/flow.noroute/standard.flow000077500000000000000000000013541305746555600240730ustar00rootroot00000000000000numobjects 4 pobject edit_twfiles 1: 0 path : drawn : 450 850 750 950 edge 0: ifiles: ofiles: $.par args : $ drawn : 600 950 600 1050 600 950 620 970 600 950 580 970 pobject Mincut 2: 1 path : drawn : 450 650 750 750 edge 1: ifiles: $.cel $.stat ofiles: $.mcel $.scel args : $ drawn : 600 750 600 850 600 750 620 770 600 750 580 770 pobject TimberWolfMC 3: 2 path : drawn : 450 450 750 550 edge 2: ifiles: $.mcel $.mpar ofiles: $.mdat $.blk args : -w $ @WINDOWID drawn : 600 550 600 650 600 550 620 570 600 550 580 570 pobject TimberWolfSC 4: 3 path : drawn : 450 250 750 350 edge 3: ifiles: $.blk $.scel $.par $.net ofiles: $.out $.pin $.pl1 args : -w $ @WINDOWID drawn : 600 350 600 450 600 350 620 370 600 350 580 370 graywolf-0.1.4+20170307gite1bf319/flow/flow.noroute/standard.fnog000077500000000000000000000013371305746555600240560ustar00rootroot00000000000000numobjects 4 pobject edit_twfiles 1: 0 path : drawn : 450 850 750 950 edge 0: ifiles: ofiles: $.par args : $ drawn : 600 950 600 1050 600 950 620 970 600 950 580 970 pobject Mincut 2: 1 path : drawn : 450 650 750 750 edge 1: ifiles: $.cel $.stat ofiles: $.mcel $.scel args : $ drawn : 600 750 600 850 600 750 620 770 600 750 580 770 pobject TimberWolfMC 3: 2 path : drawn : 450 450 750 550 edge 2: ifiles: $.mcel $.mpar $.mnet ofiles: $.mdat $.blk args : -n $ drawn : 600 550 600 650 600 550 620 570 600 550 580 570 pobject TimberWolfSC 4: 3 path : drawn : 450 250 750 350 edge 3: ifiles: $.blk $.scel $.par $.net ofiles: $.out $.pin $.pl1 args : -n $ drawn : 600 350 600 450 600 350 620 370 600 350 580 370 graywolf-0.1.4+20170307gite1bf319/include/000077500000000000000000000000001305746555600174075ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/include/yalecad/000077500000000000000000000000001305746555600210115ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/include/yalecad/assign.h000066400000000000000000000051011305746555600224430ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: assign.h DESCRIPTION:include file for the linear assignment solver. DATE: May 15, 1990 - modified mighty code. REVISIONS: Wed Apr 15 16:40:01 EDT 1992 - Replaced by new algorithms ----------------------------------------------------------------- */ #ifndef YASSIGN_H #define YASSIGN_H #ifndef lint static char YassignId[] = "@(#) assign.h (Yale) version 1.3 10/9/90" ; #endif #include #include #include /* LOW MED HIGH and INFINITY are used for the cost matrix */ #define ASSIGN_INF 1000000 #define ASSIGN_PREASSIGN 500000 /* a large number, bigger than any cost */ #define LAP_HUGE 200000000 typedef struct { INT *xmate; /* match array for x's */ INT *ymate; /* match array for y's */ INT *udual; /* dual array for u's */ INT *vdual; /* dual array for v's */ INT *pred; /* predecessor array for shortest path */ INT *unassigned; /* unassigned rows */ INT *shortlen; /* shortest path lengths */ INT *column; /* array of columns */ } LAPJV_block; /******** ASSIGNMENT FUNCTIONS *************/ extern INT **Yassign_init( P2( INT m, INT n ) ) ; /* * Arguments: * INT m, n ; * Function: * Initializes the linear assignment solver. * Bug: Internally alllcate MAX(m,n) by MAX(m,n) square matrix */ extern INT *Yassign( P3( INT **cost_matrix, INT m, INT n ) ) ; /* * Arguments: * INT **cost_matrix ; * INT m, n; * Function: * Solves the linear assignment problem. * Return: * A 0..m ans array, ans[0] contain total cost, * ans[i], 1 <= i <= m, * means row i going to map column ans[i] * Bug: * m must smaller or equal to n. * Actually, when m < n, cost_matrix will be padded to a * square matrix, the padding value is ASSIGN_INF. * Therefore, it might overflow if cost become too large. */ extern void Yassign_reset( P3(INT **cost_matrix, INT m, INT n ) ) ; /* * Arguments: * INT m, n ; * INT **cost_matrix ; * Function: * Do nothing, backward compatiblity. */ extern void Yassign_print( P3(INT **cost_matrix, INT m, INT n ) ) ; /* * Arguments: * INT m, n ; * INT **cost_matrix ; * Function: * Print the state of the linear assignment solver. */ extern void Yassign_free( P3(INT **cost_matrix, INT m, INT n ) ) ; /* * Arguments: * INT **cost_matrix ; * INT m, n ; * Function: * Free the memory associated with the solver. */ #endif graywolf-0.1.4+20170307gite1bf319/include/yalecad/base.h000066400000000000000000000154721305746555600221050ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: base.h CONTENTS: basic macro definitions. DATE: Jan 29, 1988 REVISIONS: Feb 25, 1989 - modified round macro so results are more consistent. Changed rand macro to acm_random routine. Mar 20, 1989 - added DBL_MAX and DBL_MIN for foreign systems. Apr 2, 1990 - added NIL definition. Apr 21, 1990 - added RANDOM for SGGR. Need extra paren. May 2, 1990 - moved sccsID to unique name. Added Mac contional compile. Oct 5, 1990 - added prototype macros. Oct 10, 1990 - fixed incorrect round statement. Oct 22, 1990 - added prototyping of memory manager calls. Oct 24, 1990 - added prototypes for void. Sun Nov 11 12:42:14 EST 1990 - fixed problem with void on sun. Tue Jan 15 01:27:47 EST 1991 - added vector prototypes. Fri Jan 18 18:46:02 PST 1991 - added undefs for TRUE and FALSE. Thu Jan 24 20:15:03 PST 1991 - added more vector routines. Mon Jan 28 01:34:49 EST 1991 - added P15 Wed Feb 6 23:33:12 EST 1991 - modified VOIDPTR to be of type INT *. Fri Mar 22 15:13:51 CST 1991 - added SHORT_LONG typedef for large designs. Sun Apr 28 13:46:49 EDT 1991 - added YALLOCATE, and YALLOCATEC macros. Mon Sep 16 22:17:20 EDT 1991 - modified for R6000. Wed Nov 20 11:25:58 EST 1991 - added new memory functions. Sun Dec 15 02:43:53 EST 1991 - added MEM_DEBUG conditional compile declarations. Sat Feb 8 21:51:39 EST 1992 - added SWAP macro. Tue Mar 3 16:03:45 EST 1992 - moved memory definitions to own file. ----------------------------------------------------------------- */ #ifndef YBASE_H #define YBASE_H #ifndef lint static char Ybase_HId[] = "@(#) base.h version 1.34 3/5/92" ; #endif /* Take care of prototyping first, so system file can include it */ #ifdef YALE #define PROTOTYPES_OK 1 /* WE wish this would work ... #ifndef __STDC__ #define __STDC__ 1 #endif __STDC__ */ #endif /* YALE */ #ifndef STDIO_H #define STDIO_H #include #ifdef linux #include /* needed for atof() */ #endif #endif #ifndef MATH_H #define MATH_H #include #endif /* ------------------------------------------------------- Use typedefs to make the code more portable. User just changes size here and all of the code will be modified. To avoid complaints in lint use defines instead of typedefs. Typedefs are better for errorchecking by the compiler. ---------------------------------------------------------- */ #ifndef lint /* Somewhat more rigorous 64-bit compatibility added by Tim, May 2, 2011 */ #ifndef SIZEOF_VOID_P #define SIZEOF_VOID_P 32 #endif #if SIZEOF_VOID_P == 32 typedef int INT ; #elif SIZEOF_VOID_P == 64 typedef long INT ; #else ERROR: Cannot compile without knowing the size of a pointer. See Ylib/include/base.h #endif typedef int TBOOL ; typedef int BOOL ; typedef unsigned long UNSIGNED_INT ; typedef short SHORT ; typedef long LONG ; typedef float FLOAT ; /* typedef double to have ability to change to float */ /* some machines float will be natural size. */ typedef double DOUBLE ; /* this allows the user to pick longs if large designs are present */ #ifdef S_LONG typedef short SHORT_LONG ; #else /* S_LONG */ typedef long SHORT_LONG ; #endif #else /* the lint case */ #define TBOOL int #define BOOL int #define INT int #define UNSIGNED_INT unsigned int #define SHORT short #define FLOAT float #define DOUBLE double #endif /* lint */ /* used to find when we didn't use the PORTABLE version */ #ifdef FIND_GARBAGE #define int garbage #define short garbage #define float garbage #define double garbage #endif /* FIND_GARBAGE */ #if defined(THINK_C) /* Mac */ #include #elif defined(linux) || defined(ultrix) #ifndef _LIMITS_H_ #include #endif /* _LIMITS_H_ */ #ifndef DBL_MIN #define DBL_MIN -1.0E38 #endif /* test on DBL_MIN */ #ifndef DBL_MAX #define DBL_MAX 1.0E38 #endif /* test on DBL_MAX */ #else /* not ultrix or linux; i.e., doesn't have limits.h (?) */ /* for foreign machines - conservative numbers */ #ifndef R6000 #undef SHRT_MIN /* -32768 */ #undef SHRT_MAX /* 32767 */ #undef INT_MIN /* -2147483648 */ #undef INT_MAX /* 2147483647 */ #undef DBL_MAX /* 1.0E38 */ #undef DBL_MIN /* -1.0E38 */ #define SHRT_MIN -32768 #define SHRT_MAX 32767 #define INT_MAX 2147483647 #define INT_MIN -2147483648 #define INT_MAX 2147483647 #define DBL_MAX 1.0E38 #define DBL_MIN -1.0E38 #endif /* R6000 */ #endif /* ultrix, linux */ #if defined(THINK_C) || defined(linux) #define PROTOTYPES_OK #endif /* Mac, linux */ #ifdef PROTOTYPES_OK #define P1( a ) a #define P2( a,b ) a,b #define P3( a,b,c ) a,b,c #define P4( a,b,c,d ) a,b,c,d #define P5( a,b,c,d,e ) a,b,c,d,e #define P6( a,b,c,d,e,f ) a,b,c,d,e,f #define P7( a,b,c,d,e,f,g ) a,b,c,d,e,f,g #define P8( a,b,c,d,e,f,g,h ) a,b,c,d,e,f,g,h #define P9( a,b,c,d,e,f,g,h,i ) a,b,c,d,e,f,g,h,i #define P10( a,b,c,d,e,f,g,h,i,j ) a,b,c,d,e,f,g,h,i,j #define P15( a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) \ a,b,c,d,e,f,g,h,i,j,k,l,m,n,o typedef void *VOIDPTR ; typedef void VOID ; #else /* PROTOTYPES don't exist */ #define P1( a ) #define P2( a,b ) #define P3( a,b,c ) #define P4( a,b,c,d ) #define P5( a,b,c,d,e ) #define P6( a,b,c,d,e,f ) #define P7( a,b,c,d,e,f,g ) #define P8( a,b,c,d,e,f,g,h ) #define P9( a,b,c,d,e,f,g,h,i ) #define P10( a,b,c,d,e,f,g,h,i,j ) #define P15( a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) typedef INT *VOIDPTR ; #define VOID INT #endif /* end PROTOTYPE_OK */ #ifdef VMS #define PGMOK 1 #define PGMFAIL 0 #else #define PGMOK 0 #define PGMFAIL -1 #endif /* BASIC MACRO DEFINITIONS */ #undef TRUE #undef FALSE #define YES 1 #define NO 0 #define TRUE (TBOOL) 1 #define ACCEPT 1 #define FALSE (TBOOL) 0 #define REJECT 0 #define LRECL 256 /* length of screen buffer */ #define STRINGEQ 0 #define EOS '\0' #define ZERO 0 /* ************* USEFUL MACRO DEFINITIONS **************** */ #define ABS(value) ( (value)>=0 ? (value) : -(value) ) #define MAX(a,b) ( (a) < (b) ? (b) : (a) ) #define MIN(a,b) ( (a) > (b) ? (b) : (a) ) #define SWAP(a,b,type_t) { type_t temp ; temp = a ; a = b ; b = temp ; } /* random number [0...INT_MAX] */ #define RAND (Yacm_random() ) /* random number [0...limit] */ #define RANDOM(limit) (Yacm_random() % (limit)) #define ROLL_THE_DICE() ((DOUBLE) RAND / (DOUBLE)0x7fffffff ) #define LINE printf(" file : %s line # %d\n", __FILE__,__LINE__); #define ROUND(value) ( (INT)(value + 0.5)) /* Always include memory defintions */ #include #endif /* YBASE_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/bitset.h000066400000000000000000000016441305746555600224610ustar00rootroot00000000000000#ifndef YBITSET_H #define YBITSET_H #define BITSET_GET( array, index ) (array[index>>5] & (1 <<(index & 0x1F))) #define BITSET_SET( array, index ) (array[index>>5] |= (1 << (index & 0x1F)) ) #define BITSET_RESET( array, i ) (array[i>>5] &= (~(1 << (i & 0x1F))) ) #define BITSET_ALLOC( num ) ( YCALLOC( (num>>5) + 1, UNSIGNED_INT) ) #define BITSET_ARRYSIZE( num ) ( (num>>5) + 1 ) #ifdef TEST main() { unsigned int *array ; int i ; int max ; max = 32 ; array = BITSET_ALLOC( max ) ; for( i = 0 ; i <= max ; i++ ){ if( i == 1 || i == 2 || i == 5 || i == 11 || i == 13 || i == 69 ){ BITSET_SET( array, i ) ; } else { BITSET_RESET( array, i ) ; } } for( i = 0 ; i <= max ; i++ ){ if( BITSET_GET( array, i ) ){ fprintf( stderr, "i:%d T\n", i ) ; } else { fprintf( stderr, "i:%d F\n", i ) ; } } } #endif /* TEST */ #endif /* YBITSET_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/buster.h000066400000000000000000000043411305746555600224700ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: buster.h DESCRIPTION:Include file for the utility routine to break a rectilinear cell up into tiles. CONTENTS: YBUSTBOXPTR Ybuster() BUSTBOXPTR A , R ; INT Ybuster_init() ; INT Ybuster_addpt( x, y ) ; INT x, y ; DATE: Aug 7, 1988 - rewrote to match new parser. REVISIONS: May 1, 1990 - made sure we cannot match the 0 record in the redundancy check for points. May 4, 1990 - moved to the library since it now occurs in many files. Thu Apr 18 00:49:05 EDT 1991 - rewrote buster_verify. ----------------------------------------------------------------- */ #ifndef YBUSTER_H #define YBUSTER_H #ifndef lint static char YbusterId[] = "@(#) buster.h version 1.5 4/18/91" ; #endif #include typedef struct ybustbox { INT x ; INT y ; } YBUSTBOX , *YBUSTBOXPTR ; extern Ybuster_init() ; /* Arguments: none Function: Initialize the buster routines. Must be called first before any points are added using Ybuster_addpt. Call this routine before the start of every object to be busted into tiles. */ extern Ybuster_addpt( P2( INT x, INT y ) ) ; /* Arguments: INT x, y ; Function: Add a point to the current arbitrary figure. */ extern YBUSTBOXPTR Ybuster() ; /* Arguments: none Function: Returns a tile of the arbitary figure. Call this function until it returns null to receive all the tiles of an arbitrary rectilinear shaped figure. The returning pointer list the four points of the tile starting at the point llx, lly and proceeding CW. To access say the urx,ury point use ptr[3].x, ptr[3].y if ptr is the returned pointer. */ extern Ybuster_free() ; /* Arguments: none Function: Free up the memory associated with buster. */ extern BOOL Ybuster_verify( P1(char *object_name) ) ; /* Arguments: char *object_name Function: Sanity checker. Returns TRUE if things look reasonable. It returns FALSE otherwise and outputs and error message to the screen. The object_name is a message string which is output on an error to describe the current object to be busted. This makes for better user messages. */ #endif /* YBUSTER_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/cleanup.h000066400000000000000000000050011305746555600226050ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) cleanup.h (Yale) version 1.6 11/2/91" FILE: cleanup.h DESCRIPTION:This file contains include file for cleanup handler routines. To use cleanup handler included '' at the top of main.c and #define CLEANUP_C either by uncommenting the define in this file or by setting the variable in the makefile: -DCLEANUP_H. In addition, the first executable line of the program must be INITCLEANUP() macro. In order for the handler to work, the INITCLEANUP call must occur in the top level routine, ie., main.c . CONTENTS: MACRO DEFINITIONS DATE: Feb 2, 1988 REVISIONS: Mar 9, 1989 - modified conditional compiles so you can avoid compilation on foreign machines. ----------------------------------------------------------------- */ /* cleanup.h definitions for cleanup handler system */ /* makefile sets this variable automatically but you can manually */ /* define it here if you want and your system supports UNIX signals */ /* #define CLEANUP_C - we want a cleanup handler. */ #ifndef CLEANUP_H #define CLEANUP_H #define NODUMP 0 #define YESDUMP 1 #define MAYBEDUMP 2 #ifdef CLEANUP_C #include #include #ifdef linux extern void Ycleanup(int); #else extern void Ycleanup(int, int, struct sigcontext *); #endif /* initialization cleanup macro */ /* first argument - argv[0] - program name */ /* second argument - function - user function that will be executed upon fault */ /* third argument - dumpFlag - allows users to control core dump */ /* signal(SIGQUIT,cleanup); - remove due to dbx bug */ /* signal(SIGINT,cleanup); - remove due to dbx bug */ #define YINITCLEANUP( argv, function, dumpFlag ) \ { \ signal(SIGHUP,Ycleanup); \ signal(SIGILL,Ycleanup);\ signal(SIGFPE,Ycleanup);\ signal(SIGSEGV,Ycleanup);\ signal(SIGBUS,Ycleanup);\ signal(SIGSYS,Ycleanup);\ signal(SIGTERM,Ycleanup);\ signal(SIGUSR1,Ycleanup);\ YinitCleanup( argv, function, dumpFlag ) ; \ } /*--------------------------------------------------------- initCleanup - sets static variables for cleanup handler. --------------------------------------------------------*/ VOID YinitCleanup( P3(char *argv, BOOL (*function)(), int dump) ); #else /* no cleanup handler - null it out */ #define YINITCLEANUP( argv, function, dumpFlag ) #endif /* CLEANUP_C */ #endif /* CLEANUP_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/colors.h000066400000000000000000000022751305746555600224710ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: colors.h DESCRIPTION:Insert file for Timberwolf standard colors. CONTENTS: DATE: Jan 25, 1989 - major rewrite of version 1.0 REVISIONS: Jan 27, 1989 - added frame num Sep 12, 1989 - added cyan to color table. Oct 5, 1990 - added more colors to color table. ----------------------------------------------------------------- */ #ifndef COLOR_H #define COLOR_H #ifndef lint static char colors_hId[] = "@(#) colors.h version 1.8 2/26/92" ; #endif #define TWWHITE 1 #define TWBLACK 2 #define TWGRAY 3 #define TWRED 4 #define TWBLUE 5 #define TWYELLOW 6 #define TWGREEN 7 #define TWVIOLET 8 #define TWORANGE 9 #define TWMEDAQUA 10 #define TWCYAN 11 #define TWLIGHTGREEN 12 #define TWLIGHTBLUE 13 #define TWBROWN 14 #define TWLIGHTBROWN 15 #define TWNAVY 16 #define TWLIGHTVIOLET 17 #define TWKHAKI 18 /* returns the standard color array */ extern char **TWstdcolors() ; /* returns the number of colors in standard color array */ extern INT TWnumcolors() ; #endif /* COLOR_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/dbinary.h000066400000000000000000000013411305746555600226110ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) dbinary.h (Yale) version 1.3 8/28/90" FILE: dbinary.h DESCRIPTION:include file for binary format for graphics routines CONTENTS: typedefs for binary format. DATE: Mar 21, 1989 - moved from draw.h REVISIONS: ----------------------------------------------------------------- */ #ifndef DBINARY_H #define DBINARY_H /* data record for draw binary files */ typedef struct { INT x1 ; INT x2 ; INT y1 ; INT y2 ; UNSIGNED_INT ref ; /* may be referenced by this number */ UNSIGNED_INT color ; UNSIGNED_INT label ; } DATABOX, *DATAPTR ; #endif /* DBINARY_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/debug.h000066400000000000000000000152201305746555600222500ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: debug.h CONTENTS: debug macros DATE: May 04, 1988 static char SccsId[] = "@(#) debug.h version 1.14 3/23/92" ; REVISIONS: Jan 24, 1989 - added selective turnoff of print debug or assertions. Jan 29, 1989 - made output nicer. Apr 10, 1990 - added new debug macros and updated for the debug utilities. Apr 29, 1990 - fixed cleanup handler problem. Also modified ASSERTs to call YdebugAssert instead of Ydebug so that ASSERTs are always on. Sep 9, 1990 - added DS macro - DEBUG source macro that is compiled when DEBUG is true. This is good for definitions etc. Thu Mar 5 03:38:04 EST 1992 - better output messages at the expense of not allow multiple line test without a \ continuation character. ----------------------------------------------------------------- */ #ifndef DEBUG_H #define DEBUG_H #ifdef DEBUG #include /* --------------------------------------------------------------- The assertions differ from the D macro in that the test is always executed in an assertion whereas the function part of the D macro is executed depending whether the given routine name has been turned on in the dbg file. NOTE NOW test_xc ***** MUST BE ON THE SAME LINE ******* or a compile error occurs. A alternate solution to allow multiple lines is the explicit enumeration of \ as a continuation character. ----------------------------------------------------------------- */ #define D(name_xz, func_xz) if(Ydebug(name_xz)) { func_xz ; } #define DS(name_xz) { name_xz } /* ***************** ASSERT MACROS ********************************/ /* NORMAL ASSERT - if not true, output message */ #define ASSERT(test_xz,routine_xz,userMsg_xz) \ {if (YdebugAssert()) {\ if (!(test_xz)) {\ char assertMsg_xz[LRECL] ; \ sprintf( assertMsg_xz,\ "Assertion failed in file %s, line %d:\n\t",\ __FILE__, __LINE__ ) ;\ M(ERRMSG,routine_xz,assertMsg_xz ) ;\ sprintf( assertMsg_xz, "%s\n", userMsg_xz ) ;\ M(MSG,NULL,assertMsg_xz) ;\ }}} /* ASSERT and if not true break */ #define ASSERTNBREAK(test_xz,routine_xz,userMsg_xz) \ {if (YdebugAssert()) {\ if (!(test_xz)) {\ char assertMsg_xz[LRECL] ; \ sprintf( assertMsg_xz,\ "Assertion failed in file %s, line %d:\n\t",\ __FILE__, __LINE__ ) ;\ M(ERRMSG,routine_xz,assertMsg_xz ) ;\ sprintf( assertMsg_xz, "%s\n", userMsg_xz ) ;\ M(MSG,NULL,assertMsg_xz) ;\ break ; \ }}} /* ASSERT and if not true continue */ #define ASSERTNCONT(test_xz,routine_xz,userMsg_xz) \ {if (YdebugAssert()) {\ if (!(test_xz)) {\ char assertMsg_xz[LRECL] ; \ sprintf( assertMsg_xz,\ "Assertion failed in file %s, line %d:\n\t",\ __FILE__, __LINE__ ) ;\ M(ERRMSG,routine_xz,assertMsg_xz ) ;\ sprintf( assertMsg_xz, "%s\n", userMsg_xz ) ;\ M(MSG,NULL,assertMsg_xz) ;\ continue ; \ }}} /* ASSERT and if not true return */ #define ASSERTNRETURN(test_xz,routine_xz,userMsg_xz) \ {if (YdebugAssert()) {\ if (!(test_xz)) {\ char assertMsg_xz[LRECL] ; \ sprintf( assertMsg_xz,\ "Assertion failed in file %s, line %d:\n\t",\ __FILE__, __LINE__ ) ;\ M(ERRMSG,routine_xz,assertMsg_xz ) ;\ sprintf( assertMsg_xz, "%s\n", userMsg_xz ) ;\ M(MSG,NULL,assertMsg_xz) ;\ return ; \ }}} #define ASSERTNRETURN2(test_xz,routine_xz,userMsg_xz) \ {if (YdebugAssert()) {\ if (!(test_xz)) {\ char assertMsg_xz[LRECL] ; \ sprintf( assertMsg_xz,\ "Assertion failed in file %s, line %d:\n\t",\ __FILE__, __LINE__ ) ;\ M(ERRMSG,routine_xz,assertMsg_xz ) ;\ sprintf( assertMsg_xz, "%s\n", userMsg_xz ) ;\ M(MSG,NULL,assertMsg_xz) ;\ return(NULL) ; \ }}} /* ASSERT and if not true exit program thru cleanup handler */ #define ASSERTNFAULT(test_xz,routine_xz,userMsg_xz) \ {if (YdebugAssert()) {\ if (!(test_xz)) {\ char assertMsg_xz[LRECL] ; \ sprintf( assertMsg_xz,\ "Assertion failed in file %s, line %d:\n\t",\ __FILE__, __LINE__ ) ;\ M(ERRMSG,routine_xz,assertMsg_xz ) ;\ sprintf( assertMsg_xz, "%s\n", userMsg_xz ) ;\ M(MSG,NULL,assertMsg_xz) ;\ YcleanupHandler( -1, NULL ) ; \ }}} /* ASSERT and ask user if he wishes to continue otherwise abort */ #define ASSERTNQUERY(test_xz,routine_xz,userMsg_xz) \ {if (YdebugAssert()) {\ if (!(test_xz)) {\ char assertMsg_xz[LRECL] ; \ sprintf( assertMsg_xz,\ "Assertion failed in file %s, line %d:\n\t",\ __FILE__, __LINE__ ) ;\ M(ERRMSG,routine_xz,assertMsg_xz ) ;\ sprintf( assertMsg_xz, "%s\n", userMsg_xz ) ;\ M(MSG,NULL,assertMsg_xz) ;\ M(MSG,NULL,"Do you wish to continue?") ;\ scanf( "%s", assertMsg_xz );\ if( assertMsg_xz[0] != 'Y' && assertMsg_xz[0] != 'y' ){\ YexitPgm( PGMFAIL ) ; \ }}}} /* ASSERT and if not true execute the function */ #define ASSERTNFUNC(test_xz,routine_xz,function_xz) \ {if (YdebugAssert()) {\ if (!(test_xz)) {\ { function_xz \ }}}} /* ************** function prototypes ************** */ extern BOOL Ydebug( P1(char *routine) ) ; /* Function: Return TRUE if the given routine has been turned on for debug. It returns FALSE otherwise. */ /* ASSERTIONS are always on */ extern BOOL YdebugAssert() ; /* Function: Returns TRUE if debug is on. It returns FALSE otherwise. */ extern YdebugWrite() ; /* Function: Write the debug data structure to a file. */ extern YsetDebug( P1(BOOL flag ) ) ; /* Function: Turn the debug functions on or off. It will cause the evaluation of the dbg file in the current working directory. */ #else /* remove debug code from source */ #define ASSERT(a_xz,b_xz,c_xz) #define ASSERTNBREAK(a_xz,b_xz,c_xz) #define ASSERTNCONT(a_xz,b_xz,c_xz) #define ASSERTNRETURN(a_xz,b_xz,c_xz) #define ASSERTNFAULT(a_xz,b_xz,c_xz) #define ASSERTNQUERY(a_xz,b_xz,c_xz) #define ASSERTNFUNC(a_xz,b_xz,c_xz) #define D(x_xz,func_xz) #define DS(name_xz) #endif /* DEBUG */ /* now selectively delete either ASSERTIONS or PRINT */ #ifdef TURNOFFPRINTD #undef D #define D(x_xz,func_xz) #undef DS #define DS(name_xz) #endif /* end TURNOFFPTRINTD */ #ifdef TURNOFFASSERT #undef ASSERT #undef ASSERTNBREAK #undef ASSERTNCONT #undef ASSERTNRETURN #undef ASSERTNFAULT #undef ASSERTNQUERY #undef ASSERTNFUNC #define ASSERT(a_xz,b_xz,c_xz) #define ASSERTNBREAK(a_xz,b_xz,c_xz) #define ASSERTNCONT(a_xz,b_xz,c_xz) #define ASSERTNRETURN(a_xz,b_xz,c_xz) #define ASSERTNFAULT(a_xz,b_xz,c_xz) #define ASSERTNQUERY(a_xz,b_xz,c_xz) #define ASSERTNFUNC(a_xz,b_xz,c_xz) #endif /* end TURNOFFASSERT */ #endif /* end DEBUG_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/deck.h000066400000000000000000000124231305746555600220720ustar00rootroot00000000000000/* ----------------------------------------------------------------- DESCRIPTION:Insert file for deck library routines. Add & subtract members from a top/bottom of doubly-linked list. Multiple decks may occur simultaneously. The complexity of the routines are as follows. Ydeck_top : O(1) Ydeck_bottom : O(1) Ydeck_up : O(1) Ydeck_down : O(1) Ydeck_pop : O(1) Ydeck_push : O(1) Ydeck_enqueue : O(1) Ydeck_dequeue : O(1) Ydeck_getTop : O(1) Ydeck_getBottom : O(1) Ydeck_getData : O(1) Ydeck_size : O(1) Ydeck_init : O(1) Ydeck_empty : O(n) Ydeck_free : O(n) ----------------------------------------------------------------- */ #ifndef DECK_H #define DECK_H #ifndef lint static char YdeckId[] = "@(#) deck.h (Yale) version 1.16 1/22/92" ; #endif #include #include /* *********** data structures *************** */ typedef struct Ydeck_info { VOIDPTR data; struct Ydeck_info *up ; struct Ydeck_info *down ; } YCARD, *YCARDPTR ; typedef struct { INT size ; /* size of list */ YCARDPTR top ; YCARDPTR bottom ; YCARDPTR current ; } YDECK, *YDECKPTR ; /* *********** list macros ***************** */ #define Ydeck_up( deck_xyz ) (deck_xyz->current = deck_xyz->current->up) /* Arguments: YDECK *deck_xyz ; Function: Returns element above the current element in the deck. */ #define Ydeck_down( deck_xyz ) (deck_xyz->current = deck_xyz->current->down) /* Arguments: YDECK *deck_xyz ; Function: Returns the element below the current element in the deck. */ #define Ydeck_top( deck_xyz ) (deck_xyz->current = deck_xyz->top) /* Arguments: YDECK *deck_xyz ; Function: Returns the top of the deck and resets position to head. */ #define Ydeck_bottom( deck_xyz ) ( deck_xyz->current = deck_xyz->bottom ) /* Arguments: YDECK *deck_xyz ; Function: Returns the bottom of the deck and resets position to bottom. */ #define Ydeck_size( deck_xyz ) (deck_xyz->size) /* Arguments: YDECK *deck_xyz ; Function: Returns the number of elements in the deck */ #define Ydeck_getData( deck_xyz ) (deck_xyz->current->data) /* Arguments: YDECK *deck_xyz ; Function: Returns a pointer to data stored on current card */ #define Ydeck_notEnd( deck_xyz ) (deck_xyz->current != Ydeck_sentinel()) /* Arguments: YDECK *deck_xyz ; Function: returns true if current card is the end of the deck. This is useful if the user wishes to make his own loop. eg) for(Ydeck_top(); Ydeck_notEnd() ; Ydeck_down() ) { operations on Ydeck_getData(); } */ #define Ydeck_getTop( deck_xyz ) (deck_xyz->top->data) /* Arguments: YDECK *deck_xyz ; Function: Returns a pointer to data stored on the top card */ #define Ydeck_getBottom( deck_xyz ) (deck_xyz->bottom->data) /* Arguments: YDECK *deck_xyz ; Function: Returns a pointer to data stored on the bottom card */ /* *********** deck routines *************** */ extern YDECK *Ydeck_init( /* */ ) ; /* Arguments: none. Function: Initialize deck structure and return pointer to deck memory. */ extern VOID Ydeck_push( P2( YDECK *deck, VOIDPTR data ) ) ; /* Arguments: YDECK *deck ; VOIDPTR data ; Function: Add a new element to top of the deck. User is required to maintain memory of the data element. */ extern VOID Ydeck_enqueue( P2( YDECK *deck, VOIDPTR data ) ) ; /* Arguments: YDECK *deck ; VOIDPTR data ; Function: Add a new element to bottom of the deck. User is required to maintain memory of the data element. */ extern VOIDPTR Ydeck_pop( P1(YDECK *deck) ) ; /* Arguments: YDECK *deck ; Function: Delete top item from deck. If item does not exist does nothing unless debug switch has been turned on. User is required to maintain memory of the data element. Returns data (interger or pointer) stored on card. */ extern VOIDPTR Ydeck_dequeue( P1(YDECK *deck) ) ; /* Arguments: YDECK *deck ; Function: Delete bottom item from deck. If item does not exist does nothing unless debug switch has been turned on. User is required to maintain memory of the data element. Returns data (interger or pointer) stored on card. */ extern VOID Ydeck_dump ( P2( YDECK *deckPtr, VOID (*userPrint)() ) ); /* Arguments: YDECK *deckPt ; INT (*userPrint)(); Function: For each data item in the deck, call the user print function. */ extern VOID Ydeck_empty( P2( YDECK *deck, VOID (*userDelete)() ) ) ; /* Arguments: YDECK *deck ; (*userDelete)(); Function: Frees deck memory. User userdelete function is used to free data if desired. Deck structure remains but links are removed. Should be used if deck is to be used again. */ extern VOID Ydeck_free( P2( YDECK *deck, VOID (*userDelete)() ) ) ; /* Arguments: YDECK *deck ; (*userdelete)(); Function: Frees deck memory. User userdelete function is used to free data */ extern YCARD *Ydeck_sentinel(); /* Arguments: none Function: returns address of deck sentinel. normally this is not used directly by the user. Use macro YNOTDECKEND */ extern int Ydeck_verify(P1(YDECK *deck)); #endif /* DECK_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/dialog.h000066400000000000000000000042361305746555600224260ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: dialog.h DESCRIPTION:user insert file for dialog box routines. CONTENTS: typedefs and definitions DATE: Sep 16, 1989 - original coding. REVISIONS: Dec 7, 1990 - added update function to dialog box. ----------------------------------------------------------------- */ #ifndef DIALOG_H #define DIALOG_H #ifndef lint static char dialogHId[] = "@(#) dialog.h version 1.4 12/7/90" ; #endif #include #define LABELTYPE 0 #define INPUTTYPE 1 #define BUTTONTYPE 2 #define CASETYPE 3 typedef struct { INT row, column, len ; char *string ; INT type ; INT color ; INT group ; /* used for CASETYPE - initial switch */ /* used for BUTTONTYPE - member of case group */ } TWDIALOGBOX, *TWDIALOGPTR ; typedef struct { INT type ; char *string ; BOOL bool ; } TWDRETURNBOX, *TWDRETURNPTR ; /* build a dialog box and get info */ extern TWDRETURNPTR TWdialog( P3(TWDIALOGPTR fieldp, char *name, INT (*user_function)() ) ) ; /* Arguments: TWDIALOGPTR fieldp ; char *name ; INT (*user_function)() ; Function: Creates a dialog box for user to enter data. Return a pointer to an array of type TWDRETURNPTR of the same size as input argument. Name is the name given to the dialogbox for .Xdefault control over the size of the dialog box upon creation. The easier way to use this routine is to use the TWread_dialog routine below to create a dialog.h file which has the necessary input to create the correct input field array. See a sample dialog file in graphics/example/example.dialog for more details. User function allows an incremental calculation update. */ #ifdef DEBUG extern TWDIALOGPTR TWread_dialog( P1(char *filename) ) ; /* Arguments: char *filename ; Function: Reads file and builds correct data structure, output a dialog.h file for inclusion in user program and then calls TWdialog. This allows fast development of dialog boxes for the codes yet the final result is stored in the program itself. */ #endif #endif /* DIALOG_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/draw.h000066400000000000000000000373671305746555600221370ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: draw.h DESCRIPTION:include file for draw programs and utilities CONTENTS: typedefs, and external routines for draw facility DATE: Jan 25, 1989 - major rewrite of version 1.0 REVISIONS: Jan 27, 1989 - added frame num Oct 8, 1989 - separated menu reading function for user friendliness. May 12, 1990 - added TWsetFrame to include file. Oct 5, 1990 - added prototypes. Oct 12, 1990 - added TWforceRedraw. Fri Jan 25 15:38:41 PST 1991 - fixed inconsistent def. Sun Feb 17 17:11:57 EST 1991 - added 3D graphics functions. Tue May 21 17:14:39 CDT 1991 - fixed problem with initgraphics prototype. ----------------------------------------------------------------- */ #ifndef DRAW_H #define DRAW_H #ifndef lint static char YdrawId[] = "@(#) draw.h (Yale) version 1.20 3/6/92" ; #endif #include /* need for BOOL definitions used below */ /**** THE MODES *******/ #define TWDRAWONLY 0 #define TWWRITEONLY 1 #define TWWRITENDRAW 2 /* defininition necessary for menus */ typedef struct { char *item ; /* menu or menu item */ char *bool_item ; /* used for Boolean items */ BOOL bool_init ; /* which item is initialized */ BOOL menuNotItem ; /* true if menu; false if menu item */ INT action_index ; /* when selected returns this number */ INT action_indexb ; /* when selected returns this number */ } TWMENUBOX, *TWMENUPTR ; /* the switchable routines */ extern VOID (*_TWdrawRect)(P7( INT ref_num, INT x1, INT y1, INT x2, INT y2, INT color, char *label )) ; extern VOID (*_TWdrawLine)(P7( INT ref_num, INT x1, INT y1, INT x2, INT y2, INT color, char *label )) ; extern VOID (*_TWdrawArb)(P3( INT ref_num, INT color, char *label )) ; /* make calls easier for the user so he doesn't know that the */ /* routines are switchable according to mode */ #define TWdrawRect(a_xz, b_xz, c_xz, d_xz, e_xz, f_xz, g_xz )\ ( (*_TWdrawRect)(a_xz, b_xz, c_xz, d_xz, e_xz, f_xz, g_xz) ) #define TWdrawLine(a_xz, b_xz, c_xz, d_xz, e_xz, f_xz, g_xz )\ ( (*_TWdrawLine)(a_xz, b_xz, c_xz, d_xz, e_xz, f_xz, g_xz) ) #define TWdrawArb(a_xz, b_xz, c_xz )\ ( (*_TWdrawArb)(a_xz, b_xz, c_xz) ) #define TWdrawPin(a_xz, b_xz, c_xz, d_xz, e_xz, f_xz, g_xz )\ ( (*_TWdrawRect)(a_xz, b_xz, c_xz, d_xz, e_xz, f_xz, g_xz) ) #define TWdrawNet(a_xz, b_xz, c_xz, d_xz, e_xz, f_xz, g_xz )\ ( (*_TWdrawLine)(a_xz, b_xz, c_xz, d_xz, e_xz, f_xz, g_xz) ) #define TWdrawCell(a_xz, b_xz, c_xz, d_xz, e_xz, f_xz, g_xz )\ ( (*_TWdrawRect)(a_xz, b_xz, c_xz, d_xz, e_xz, f_xz, g_xz) ) /* new defines for 3D graphics */ #define TW3DdrawAxis() _TW3DdrawAxis( TRUE ) #define TW3Darb_init() TWarb_init() #define TW3DdrawArb( ref, color, label ) TWdrawArb( ref, color, label ) #define TW3Darb_addpt( x1, y1, z1 ) \ { DOUBLE X1, Y1 ; \ TW3Dperspective( (DOUBLE)x1, (DOUBLE)y1, (DOUBLE)z1, &X1, &Y1 ); \ TWarb_addpt( (INT)X1, (INT)Y1 ); \ } #define TW3DdrawLine( ref_num, x1, y1, z1, x2, y2, z2, color, label) \ { DOUBLE X1, Y1, X2, Y2 ; \ TW3Dperspective( (DOUBLE)x1, (DOUBLE)y1, (DOUBLE)z1, &X1, &Y1 ); \ TW3Dperspective( (DOUBLE)x2, (DOUBLE)y2, (DOUBLE)z2, &X2, &Y2 ); \ TWdrawLine(ref_num,(INT)X1,(INT)Y1,(INT)X2,(INT)Y2,color, label) ; \ } extern _TW3DdrawAxis( P1(BOOL drawNotErase) ) ; /******** FUNCTIONS NORMALLY USED BY GRAPHIC PROGRAM USERS *********/ extern BOOL TWinitGraphics( P7(INT argc, char *argv[], INT numC, char *colors[], BOOL dumpOnly, TWMENUPTR menu, INT (*refresh_func)() )) ; /* Function: Initialization of graphics package. Needs to be called first. Argc is the number of arguments passed on the command line. Argv is the argument vector. Colors is an array of strings of the desired colors. The colors must agree with the standard color map of the machine and in addition element 1 must be "white" and element two "black". Also element 0 is not used at this time. Use TWstdcolors to use the graphics packages builtin standard colors. NumC is the number of colors in the color array counting white and black. DumpOnly should normally be set to FALSE. It should be only set to TRUE if you wish to only dump the DATA to the DATADIRECTORY. MenuPath is the pathname of the menu file. Refresh_func is the address of the function which repaints the entire drawing area. NOTE: it is advised that the TimberWolf standard colors be used if possible. Use TWstdcolors() for argument colors and TWnumcolors() for numC arg and use include file . */ extern BOOL TWinitParasite( P8( INT argc, char *argv[], INT numC, char **colors, BOOL dumpOnly,TWMENUPTR menu, INT (*refresh_func)(), INT w) ) ; /* Function: Take over the control of a window already created by TWinitGraphics by another process. One additional parameter to the TWinitGraphics argument list, windowId which is the top window Id. It is found by calling TWsaveState in the calling processs. */ extern TWcloseGraphics() ; /* Function: Closes graphics display and performs cleanup operations. Should be performed before end of program. */ extern TWsetMode( P1(INT mode) ) ; /* Function: Allows user to change mode during run. Helpful to dump the current state to the binary files and then continue drawing to the screen. WARNING: This should only be used if TWinitGraphics was called with mode TWWRITENDRAW; otherwise, error results. */ extern BOOL TWcheckServer() ; /* Function: Returns TRUE if a connection can be made to server. False otherwise. */ /* The following draw routines have been defined using macro calls */ /* so it is convenient for the user. Use the form shown in comments. */ /* TWdrawRect(ref_num, x1, y1, x2, y2, color, label ) */ /* Arguments: INT ref_num, x1, y1, x2, y2, color ; char *label ; Function: Draws a rectangle to screen and/or file. Ref_num is a reference number to associate rectangle - currently not used. X1, y1, x2, y2 are the lower left, upper right points of rectangle. Color is the element number in color array. For example white is 1 and black is 2. Label is optional - a label is attached to figure if non-null. */ /* TWdrawLine(ref_num, x1, y1, x2, y2, color, label ) */ /* Arguments: INT ref_num, x1, y1, x2, y2, color ; char *label ; Function: Draws a line to screen and/or file. Ref_num is a reference number to associate line - currently not used. X1, y1, x2, y2 are the two points of the line. Color is the element number in color array. For example white is 1 and black is 2. Label is optional - a label is attached to figure if non-null. */ /* TWdrawNet(ref_num, x1, y1, x2, y2, color, label ) */ /* Arguments: INT ref_num, x1, y1, x2, y2, color ; char *label ; Function: Draws a net to screen and/or file. Ref_num is a reference number to associate all lines of a net - currently not used. X1, y1, x2, y2 are the two points of the line of a net. Color is the element number in color array. For example white is 1 and black is 2. Label is optional - a label is attached to figure if non-null. */ /* TWdrawCell(ref_num, x1, y1, x2, y2, color, label ) */ /* Arguments: INT ref_num, x1, y1, x2, y2, color ; char *label ; Function: Draws a cell to screen and/or file. Ref_num is a reference number to associate cell - currently not used. X1, y1, x2, y2 are the lower left, upper right points of cell. Color is the element number in color array. For example white is 1 and black is 2. Label is optional - a label is attached to figure if non-null. */ /* TWdrawPin(ref_num, x1, y1, x2, y2, color, label ) */ /* Function: Draws a pin to screen and/or file. Ref_num is a reference number to associate pin - currently not used. X1, y1, x2, y2 are the lower left, upper right points of pin. Color is the element number in color array. For example white is 1 and black is 2. Label is optional - a label is attached to figure if non-null. */ extern TWarb_init() ; /* Arguments: none Function: Start a new arbitrary figure. */ extern TWarb_addpt( P2( INT xpos, INT ypos ) ) ; /* Function: Add a new point to the current arbitrary figure */ /* TWdrawArb( ref_num, color, label ) */ /* Function: Draws a arbitrary figure to screen and/or file. Ref_num is a reference number to associate figure - currently not used. The points of the arbitrary figure are first added using TWarb_init and the TWarb_addpt. There is no need to close the figure. Color is the element number in color array. For example white is 1 and black is 2. Label is optional - a label is attached to figure if non-null. */ /* copy pixmap to screen and flush screen output buffer */ extern TWflushFrame() ; /* Arguments: None. Function: Flush the screen output and/or file buffer. This call must be made after all data of a screen is written, that is after all TWdraws have performed. */ extern TWstartFrame() ; /* Arguments: None. Function: Start a new screen and/or file frame. This call must be made before data is written, that is before any TWdraws are performed for a given screen or frame. */ /********** ROUTINES USED BY SCREEN GRAPHICS ONLY ******************/ extern TWzoom() ; /* Arguments: None Function: Performs a zoom in main graphics window. */ extern TWtranslate() ; /* Arguments: None Function: Translate center to picked or entered point in main graphics window. */ extern TWfullView() ; /* Arguments: None Function: Returns to full screen after zoom. Full screen size is size determined by TWsetWindow. */ extern TWsetwindow( P4( INT left, INT bottom, INT right, INT top ) ) ; /* Function: set the boundary of the visible window according to user coordinates Must call this function before draws. */ extern TWcolorXOR( P2( INT color, BOOL exorFlag ) ) ; /* Function: set a particular colors draw function. If exorFlag is set to TRUE, then X will exor the next drawing with the current contents of the display. If exorFlag is set to FALSE, X will copy the new figure over any current contents blocking the view. The default is copy mode. */ extern TWhighLightRect( P4( INT x1,INT y1,INT x2,INT y2 )) ; /* Function: Highlight the given area in black. */ extern TWsync( ) ; /* Arguments: None Function: Make program wait until XServer has processed all requests. This function should not be need by the user normally. It is used internally in the graphics module. */ extern TWmoveRect( P6( INT *x1, INT *y1, INT *x2, INT *y2, INT ptx, INT pty )) ; /* Function: Draw ghost figure of rectangle as the user moves it on the screen. X1, y1, x2, y2 are pointer to the original position of the rectangle in user data coordinates. Ptx, and pty are the reference point of the mouse pointer. The figure will move relative to the offset between the pointer and the given rectangle coordinates. The routine will return in x1, y1, x2, y2 the new position of the rectangle when the mouse button is pushed. */ /********** MENU ROUTINES-USED BY SCREEN GRAPHICS ONLY ******************/ extern INT TWcheckMouse() ; /* Arguments: None Function: Check to see if mouse button was clicked in menu window. If so, put up appropriate menu and wait for user response. Return integer value corresponding to the function value given in the menu file. */ extern TWgetPt( P2( INT *x, INT *y )) ; /* Function: Wait for user to enter point with a mouse pointer. Returns x,y position of pointer when clicked in user coordinate system. */ extern TWmessage( P1( char *message ) ) ; /* Function: Write messsage to the message window. */ extern char *TWgetString( P1( char *directions ) ) ; /* Function: Write directions on what to do to message window and then return back a string in what the user entered in the window. */ extern BOOL TWgetPt2( P2( INT *x, INT *y ) ) ; /* Function: Wait for user to enter point with a mouse pointer or by entering string in message window. Returns x,y position in user coordinate system. Returns TRUE (1) if user entered data from keyboard and FALSE (0) if entered by picking with the mouse. */ /* check to see if main window has been covered by another window */ extern BOOL TWcheckExposure() ; /* Arguments:None Function: Check to see if main window has been covered by another window. Returns TRUE (1) if this has occurred and FALSE (0) otherwise. User uses this knowledge for redraw of window data. */ extern INT TWsaveState() ; /* Arguments:None Function: Save the graphics state before calling a grahics parasite. Returns the window ID which is needed in the TWinitParasite argument list. */ extern TWrestoreState() ; /* Arguments:None Function: Return the graphics state to the state before the graphics parasite was called. */ /* check to see if main window has been requested to change size */ extern TWcheckReconfig() ; /* Arguments:None Function: Check to see if main window has been requested to change size and perform necessary modifications to windows. Note: normally the user will not need to call this function since it is performed during each call of TWcheckMouse. */ extern TWsetFrame( P1(INT number) ) ; /* Function: Set the dump file to the given frame number. Valid frame numbers start at 1. If 0 is passed, the frame will be set to the next available frame in the DATADIR. */ extern TWMENUPTR TWread_menus( P1(char *filename) ) ; /* Function: This convenience function reads a menu file and create the menu box structure necessary for TWinitgraphics. Upon execution of the function, a menus.h file will be created in the current directory with all the necessary definitions for creating the menus. */ extern TWforceRedraw() ; /* Function: This function forces a redraw by sending an exposure event to the server. This is added so the user can control exposure events. */ extern TWdrawString( P4(INT x, INT y, INT color, char *label ) ) ; /* Function: Draw a string left justified from the given location. */ /* *************** NEW 3D TRANSFORMATIONS ********************* */ /* TW3DdrawAxis() */ /* Function: TW3DdrawAxis draws the x y z axis. */ extern VOID TW3Dnormal_view() ; /* Function: Turn off the 3D viewing. */ extern VOID TW3DsetCamera() ; /* Function: Turn on the 3D viewing. The view is set with the mouse. */ /*------------------ Perform a 3D transformation. ------------------*/ extern VOID TW3Dperspective(P5(DOUBLE x, DOUBLE y, DOUBLE z, DOUBLE *pX, DOUBLE *pY)); /* Perform a 3D transformation. */ extern VOID TW3DperspectiveOn() ; /* Function: Turn on the 3D perspective. Make things farther away smaller. */ extern VOID TW3DperspectiveOff() ; /* Function: Turns off the 3D perspective. */ /* TW3DdrawLine( INT ref_num, INT x1, INT y1, INT z1, INT x2, INT y2, INT z2, INT color, char *label) */ /* Function: Draws a line in 3 dimensions. */ extern INT TW3DdrawCube( P9(INT ref_num, INT x1, INT y1, INT z1, INT x2, INT y2, INT z2, INT color, char *label ) ) ; /* Function: Draws a 3 dimensional cube. */ /* TW3Darb_init() */ /* Function: Starts an arbitrary figure in 3 dimensions. */ /* TW3Darb_addptr() */ /* Function: Adds another point to current arbitrary figure in 3D. */ /* TW3DdrawArb( INT ref, INT color, char *label ) */ /* Function: Finished arbitrary point and draws it to the screen. */ extern TWarb_fill( P1(BOOL flag ) ) ; /* Function: If flag is true, arbitrary figures (both 2D and 3D) will be filled. Otherwise, no fill will be added. */ #endif /* DRAW_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/dset.h000066400000000000000000000116251305746555600221260ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: dset.h DESCRIPTION:include file for disjoint set utility functions CONTENTS: DATE: Apr 26, 1991 REVISIONS: Sun Dec 8 23:30:16 EST 1991 - removed indirection from the comparison functions. Sun Dec 15 02:44:47 EST 1991 - now store sub/superset tree with the set itself. ----------------------------------------------------------------- */ #ifndef YDSET_H #define YDSET_H #ifndef lint static char Ydset_h_SccsId[] = "@(#) dset.h version 1.6 3/28/92"; #endif #include #include typedef struct ydsetrec { YTREEPTR dtree ; /* rbtree holding sets */ INT (*compare_func)() ; /* how to compare functions in rbtree */ VOID (*user_delete)() ; /* how to delete functions in rbtree */ YTREEPTR superset_tree ; /* tree to store the superset */ YTREEPTR subset_tree ; /* tree to store the subsets */ YTREEPTR parent_tree ; /* tree to store the parents */ } YDSETBOX, *YDSETPTR ; /*--------------------------------------- Ydset_init() NOTE that the users comparison function will be similar to comparison function used in the rbtree package. ---------------------------------------*/ extern YDSETPTR Ydset_init( P1(INT (*compare_func)() ) ) ; /* Function: Initialize the union/find routines. Returns back a set. A set of sets is implemented. Therefore, many union find data structures may be used at once. A comparison function must be supplied to sort the data. See rbtree.h for more details about comparison functions. */ /*--------------------------------------- Ydset_empty Free all elements in the set but leaves the set intact This may be used recursively. ---------------------------------------*/ extern VOID Ydset_empty( P2(YDSETPTR set,VOID (*userDelete)() ) ); /* free all elements of a superset. Function userDelete is applied to user data. */ /*--------------------------------------- ---------------------------------------*/ extern VOIDPTR Ydset_enumerate( P2(YDSETPTR set, BOOL startFlag)); /* Function: Enumerate all of the elements of the super set */ /*--------------------------------------- ---------------------------------------*/ extern VOIDPTR Ydset_enumerate_superset( P2(YDSETPTR set, BOOL startFlag)); /* Function: Enumerate all of the elements of the super set */ extern VOIDPTR Ydset_enumerate_parents( P2(YDSETPTR dset, BOOL startFlag) ) ; /* Function: Enumerate the parents of the super set */ /*--------------------------------------- ---------------------------------------*/ extern VOIDPTR Ydset_enumerate_subset( P3 (YDSETPTR set,VOIDPTR subsetData, BOOL startFlag)); /* Function: Find the set which subsetData is an element of. Enumerate all the elements of that set. */ /*--------------------------------------- ---------------------------------------*/ extern VOIDPTR Ydset_find( P2(YDSETPTR dset, VOIDPTR data ) ) ; /* Function: Returns subset name for the given data of the given set. If data does not exist, it is created and put in set. */ /*------------------------------------------------- Ydset_find_set() Searches for the set an item belongs to. This routine avoids makeset of the item which Ydset_find does by default -------------------------------------------------*/ VOIDPTR Ydset_find_set( P2( YDSETPTR dset, VOIDPTR data )); /*--------------------------------------- Ydset_free Free all elements in the set and the set. This can be used recursively. ---------------------------------------*/ extern VOID Ydset_free( P2(YDSETPTR set,VOID (*userDelete)() ) ); /* free the entire superset. Function userDelete is applied to user data. */ /*--------------------------------------- ---------------------------------------*/ extern VOIDPTR Ydset_union( P3(YDSETPTR set, VOIDPTR x, VOIDPTR y ) ) ; /* Function: Perform union operation on two data items for the given set. If either data item does not exist, the item is created and put in set. Returns the subset name. */ /*--------------------------------------- ---------------------------------------*/ extern VOIDPTR Ydset_search( P2(YDSETPTR set,VOIDPTR data)); /* Search for an elment in the super set */ /*--------------------------------------- ---------------------------------------*/ INT Ydset_subset_size( P2(YDSETPTR set, VOIDPTR data)); /* returns the size of the subset data is an element of. */ /*--------------------------------------- ---------------------------------------*/ extern INT Ydset_superset_size(P1(YDSETPTR set)); /* returns the size of the entire superset */ /*----------------------- Ydset_verify -----------------------*/ extern INT Ydset_verify( P1(YDSETPTR set)); /*------------------------ Ydset_dump ------------------------*/ extern Ydset_dump(P2( YDSETPTR set, VOID (*printFunc)() ) ); #endif /* YDSET_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/file.h000066400000000000000000000037201305746555600221030ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) file.h version 1.7 4/21/91" FILE: file.h - file utility routine insert file DESCRIPTION:The file utilities open and close files, check to see if files and directories exist. NOTE: The define statements are designed so that external users may customize their I/O routines. CONTENTS: Definitions for file routines. DATE: Apr 10, 1989 REVISIONS: Thu Apr 18 00:51:06 EDT 1991 - added lock routines. Sun Apr 21 21:22:40 EDT 1991 - added Yfile_slink. ----------------------------------------------------------------- */ #ifndef FILE_H #define FILE_H #include extern FILE *YopenFile( P3(char *filename,char *readwrite, BOOL abort ) ) ; /* Function: Open the given file name for reading and/or writing. Readwrite is the standard C lib control string. It may be "w", "r", "a", "w+", etc. If abort is set to TRUE, the program will exit if the file cannot be found and an appropriate error message will be output. If abort is set to FALSE, the routine will return a NULL pointer if the file could not be opened. */ extern BOOL YfileExists( P1(char *pathname ) ) ; /* Function: Returns TRUE if the given file exists. It returns FALSE otherwise. */ extern BOOL YdirectoryExists( P1(char *pathname) ) ; /* Function: Returns TRUE if the given pathname is a directory and it exists. It returns FALSE otherwise. */ extern FILE *Yfile_create_lock( P2(char *filename, BOOL readNotWrite ) ) ; /* Function: Creates a lock file ready for read or write */ extern BOOL Yfile_test_lock( P1( char *filename ) ) ; /* Function: See if a file is locked. */ extern char *Yfile_slink( P1( char *pathname ) ) ; /* Function: Return symbolic link of a file. */ #define TWOPEN( a_z, b_z, c_z ) YopenFile( a_z, b_z, c_z ) #define TWCLOSE( a_z ) fclose( a_z ) /* I/O MACRO DEFINITIONS */ #define ABORT 1 #define NOABORT 0 #endif /* FILE_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/graph.h000066400000000000000000000572621305746555600222770ustar00rootroot00000000000000/*----------------------------------------------------------------- FILE: Graph.h DESCRIPTION:Graph include file for set of generic graph routines CONTENTS: DATE: Jun 01, 1991 REVISIONS: ----------------------------------------------------------------- */ #ifndef YGRAPH_H #define YGRAPH_H #ifndef lint static char YgraphId[] = "@(#) Graph.h version 1.8 8/19/91"; #endif #include #include #include #include #ifndef GRAPH_DEFINED typedef struct graph *YGRAPHPTR; typedef struct graph_node *YNODEPTR; typedef struct graph_edge *YEDGEPTR; #endif #define YGRAPH_DIRECTED 1 #define YGRAPH_NONDIRECTED 0 /*------------------------------------------------------------- Ygraph_init: Initialize a graph. User must make either make the compare_edge function unique or set compare_edge equal to NULL The user can set an edge's weight statically. Or, the use can set an edge's weight dynamicallly. Thus, the user edge weight function is optional and only should be used if the user need dynamic edge weights. -------------------------------------------------------------*/ extern YGRAPHPTR Ygraph_init(P4(INT(*compare_node)(), INT(*compare_edge)(), INT(*user_edge_weight)(), INT flags)); /* Arguments: INT (*compare_node)() - users node data comparison function INT (*compare_edge)() - users edge data comparicson function INT (*user_edge_weight)() - users edge weight function INT flags - the bits in the field allow for things like directed edges and redundant edges. Function: This function initializes the data structures used by the various graphics routines. In order to use all of the graph routines, the user must create two functions. The compare_node comparison function should be unique as some of the graph routines make use of disjoint sets. The compare_edge function can be anything the user desires, however, the use may want to define the compare_edge in terms of compare_node so that an edge may be retreived on the basis of nodeData only. The bits in the flags variable can be used to turn on directed graph behavior. The default setting is non directed edges. Example: 1) myGraph = Ygraph_init( myNodeCompare, myEdgeCompare, 0, 0); This initializes a graph with non directed edges. 2) myGraph = Ygraph_init( myNodeCompare, myEdgeCompare, 0, YGRAPH_DIRECTED ); This initializes a graph with directed edges. */ /*------------------------------------------------- Ygraph_flagsSet Set flags for graph operation. Use YGRAPH_DIRECTED, YGRAPH_NONDIRECTED -------------------------------------------------*/ INT Ygraph_flagsSet( P2(YGRAPHPTR graph, INT flag) ); /*------------------------------------------------- Ygraph_nodeInsert: insert a node into the graph -------------------------------------------------*/ extern YNODEPTR Ygraph_nodeInsert( P2(YGRAPHPTR graph, VOIDPTR nodeData )); /* Arguments: YGRAPHPTR graph - the graph created with Ygraph_init(); INT node - identification of node VOIDPTR nodeData - users optional node Data Function: This routine inserts a node into the graph data structure. A new node is not created if the node already exists. Example: 1) Ygraph_nodeInsert( myGraph, 3, myNodeData); This creates a node with id 3. */ /*-------------------------------------------------- Ygraph_edgeDelete: free edges from data structure --------------------------------------------------*/ extern VOID Ygraph_edgeDelete(P3(YGRAPHPTR graph,YEDGEPTR edge,VOID (*userEdgeFree)())); /*------------------------------------------------- Ygraph_edgeInsert: insert an edge into the graph The new YEDGEPTR is returned. If the edge already existed, NULL is returned. -------------------------------------------------*/ extern YEDGEPTR Ygraph_edgeInsert( P5(YGRAPHPTR graph, VOIDPTR edgeData, INT edgeWeight, VOIDPTR nodeData1, VOIDPTR nodeData2 )); /* Arguments YGRAPHPTR graph - the graph created with Ygraph_init(); INT node1 - identification of first node in edge; INT node2 - identification of second node in edge; INT edgeWeight - weight of the edge VOIDPTR edgeData - users optional edge Data Function: This routine inserts an edge into the graph data structure. Redundant edges are not added to the data structure. If the graph flag YGRAPH_DIRECTED is set, then only node2 will be in node1's adjacency list. Otherwise, node1 will also be put into node2's adjacency list. The new YEDGEPTR is returned. If the edge already exists, then NULL returned. Example: 1) Ygraph_insert( myGraph, 3, 5, 20, myEdgeData); This creates an edge between node 3 and node 5 with a weight of 20 */ /*--------------------------------------------- empty all nodes and edge from the graph ---------------------------------------------*/ VOID Ygraph_empty(P3(YGRAPHPTR graph,VOID (*nodeDelete)(),VOID (*edgeDelete)())); /*------------------------------------------------- Ygraph_nodeCount -------------------------------------------------*/ extern INT Ygraph_nodeCount( P1( YGRAPHPTR graph )); /*------------------------------------------------- Ygraph_edgeCount -------------------------------------------------*/ extern INT Ygraph_edgeCount( P1( YGRAPHPTR graph )); /*------------------------------------------------- Ygraph_edgeWeight Returns the weigh of an edge -------------------------------------------------*/ INT Ygraph_edgeWeight( P1 (YEDGEPTR edge) ); /*------------------------------------------------- Ygraph_edgeWeightSet Sets the edge weight to weight -------------------------------------------------*/ INT Ygraph_edgeWeightSet( P2 (YEDGEPTR edge, INT weight) ); /*------------------------------------------------- Ygraph_edgeNode1Data -------------------------------------------------*/ int Ygraph_edgeType( P1 (YEDGEPTR edge) ); /*------------------------------------------------- Ygraph_nodeDegree -------------------------------------------------*/ extern INT Ygraph_nodeDegree(P1(YNODEPTR node)); /*------------------------------------------------- Ygraph_nodeFind -------------------------------------------------*/ extern YNODEPTR Ygraph_nodeFind(P2(YGRAPHPTR graph,VOIDPTR nodeData)); /*------------------------------------------------- Ygraph_nodeFindClosest - find closest node in graph Use same functions as rbtree_search_closest. -------------------------------------------------*/ extern YNODEPTR Ygraph_nodeFindClosest(P3(YGRAPHPTR graph, VOIDPTR nodeData,INT function)); /*------------------------------------------------- Ygraph_nodeSuc -------------------------------------------------*/ extern YNODEPTR Ygraph_nodeSuc(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_nodePred -------------------------------------------------*/ extern YNODEPTR Ygraph_nodePred(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_edgeFind -------------------------------------------------*/ extern YEDGEPTR Ygraph_edgeFind(P4(YGRAPHPTR graph,VOIDPTR edgeData, VOIDPTR node1Data,VOIDPTR node2Data)); /*------------------------------------------------- Ygraph_edgeFindByNodes -------------------------------------------------*/ extern YEDGEPTR Ygraph_edgeFindByNodes( P3(YGRAPHPTR graph, YNODEPTR node1, YNODEPTR node2 ) ) ; /*------------------------------------------------- Ygraph_edgeFindByNodeData -------------------------------------------------*/ extern YEDGEPTR Ygraph_edgeFindByNodeData( P3(YGRAPHPTR graph, VOIDPTR node1Data, VOIDPTR node2Data ) ) ; /*------------------------------------------------- Ygraph_edgeData -------------------------------------------------*/ extern VOIDPTR Ygraph_edgeData( P1( YEDGEPTR edge)); /*------------------------------------------------- Ygraph_edgeNode1 -------------------------------------------------*/ extern YNODEPTR Ygraph_edgeNode1( P1(YEDGEPTR edge)); /*------------------------------------------------- Ygraph_edgeNode2 -------------------------------------------------*/ extern YNODEPTR Ygraph_edgeNode2( P1( YEDGEPTR edge)); /*------------------------------------------------- Ygraph_edgeNode1Data -------------------------------------------------*/ extern VOIDPTR Ygraph_edgeNode1Data( P1(YEDGEPTR edge)); /*------------------------------------------------- Ygraph_edgeNode2Data -------------------------------------------------*/ extern VOIDPTR Ygraph_edgeNode2Data( P1( YEDGEPTR edge)); /*------------------------------------------------- Ygraph_nodeData -------------------------------------------------*/ extern VOIDPTR Ygraph_nodeData( P1( YNODEPTR node)); /*-------------------------------------------------- free and empty the graph --------------------------------------------------*/ extern VOID Ygraph_free(P3(YGRAPHPTR graph,VOID (*nodeDelete)(),VOID (*edgeDelete)())); /*------------------------------------------------- Ygraph_edgeEnumerate -------------------------------------------------*/ extern YEDGEPTR Ygraph_edgeEnumerate(P2( YGRAPHPTR graph, BOOL startFlag)); /*------------------------------------------------- Ygraph_edgeEnumeratePush -------------------------------------------------*/ extern VOID Ygraph_edgeEnumeratePush(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_edgeEnumeratePop -------------------------------------------------*/ extern VOID Ygraph_edgeEnumeratePop(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_edgeMin -------------------------------------------------*/ extern YEDGEPTR Ygraph_edgeMin(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_edgeMax -------------------------------------------------*/ extern YEDGEPTR Ygraph_edgeMax(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_listAdjEdges -------------------------------------------------*/ extern YEDGEPTR Ygraph_listAdjEdges(P2(YNODEPTR node, INT listNum)); /*------------------------------------------------- Ygraph_listBackEdges -------------------------------------------------*/ extern YEDGEPTR Ygraph_listBackEdges(P2(YNODEPTR node, INT listNum)); /*------------------------------------------------- Ygraph_nodeEnumerate -------------------------------------------------*/ extern YNODEPTR Ygraph_nodeEnumerate(P2( YGRAPHPTR graph, BOOL startFlag)); /*------------------------------------------------- Ygraph_nodeEnumeratePop -------------------------------------------------*/ extern VOID Ygraph_nodeEnumeratePop( P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_nodeEnumeratePush -------------------------------------------------*/ extern VOID Ygraph_nodeEnumeratePush( P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_nodeMin -------------------------------------------------*/ extern YNODEPTR Ygraph_nodeMin(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_nodeMax -------------------------------------------------*/ extern YNODEPTR Ygraph_nodeMax(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_listAdjNodes -------------------------------------------------*/ extern YNODEPTR Ygraph_listAdjNodes(P2(YNODEPTR node,INT listNum)); /*------------------------------------------------- Ygraph_listBackNodes -------------------------------------------------*/ extern YNODEPTR Ygraph_listBackNodes(P2(YNODEPTR node,INT listNum)); /*------------------------------------------------- Ygraph_nodeInterval -------------------------------------------------*/ extern YNODEPTR Ygraph_nodeInterval( P4(YGRAPHPTR graph, VOIDPTR loData, VOIDPTR hiData, BOOL startFlag) ); /*------------------------------------------------- Ygraph_nodeIntervalPush -------------------------------------------------*/ VOID Ygraph_nodeIntervalPush(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_nodeIntervalPop -------------------------------------------------*/ VOID Ygraph_nodeIntervalPop(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_edgeInterval -------------------------------------------------*/ extern YEDGEPTR Ygraph_edgeInterval( P4(YGRAPHPTR graph, VOIDPTR loData, VOIDPTR hiData, BOOL startFlag) ); /*------------------------------------------------- Ygraph_edgeIntervalPush -------------------------------------------------*/ VOID Ygraph_edgeIntervalPush(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_edgeIntervalPop -------------------------------------------------*/ VOID Ygraph_edgeIntervalPop(P1(YGRAPHPTR graph)); /*-------------------------------------------------- free_node: free node from data structure --------------------------------------------------*/ extern VOID Ygraph_nodeDelete(P4(YGRAPHPTR graph,YNODEPTR node, VOID (*nodeFree)(),VOID (*edgeFree)())); /*------------------------------------------------- Ygraph_nodeVeriy: exercise node data structure -------------------------------------------------*/ extern int Ygraph_nodeVerify(P1(YNODEPTR node)); /*------------------------------------------------- Ygraph_edgeVeriy: exercise edge data structure -------------------------------------------------*/ extern int Ygraph_edgeVerify(P1(YEDGEPTR edge)); /*------------------------------------------------- Ygraph_copy: returns a copy of a graph -------------------------------------------------*/ extern YGRAPHPTR Ygraph_copy(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_size() Returns the graph size field. The size of the graph is set if the graph is returned by Ygraph_steiner(). Also, Ygraph_edgeWeights2Size() can be called to add up all of the edge weights into a single size. -------------------------------------------------*/ extern INT Ygraph_size( P1 (YGRAPHPTR graph) ); /*------------------------------------------------- Ygraph_edgeWeights2Size Sum all of the edge weights, and put into the graph size field. -------------------------------------------------*/ extern INT Ygraph_edgeWeights2Size( P1 (YGRAPHPTR graph) ); /*------------------------------------------------------------ Ygraph_bfs() Perform a beadth first seach rooted at sourceNode. Optionally, the user can provide a targetNode beyond which the search is terminated. ------------------------------------------------------------*/ extern VOID Ygraph_bfs(P3(YGRAPHPTR graph,YNODEPTR source,YNODEPTR target)); /*----------------------------------------------------------- Ygraph_path: returns a deck containing a path between a source and target. To use, first run Ygraph_bfs or Ygraph_dijkstra on a graph. Then, run Ygraph_path. Node target will be traced back to its source, and the path will be returned in a deck. NOTE: The path deck is passed to the user and the user is responsible for freeing it. -----------------------------------------------------------*/ extern YDECKPTR Ygraph_path(P2(YGRAPHPTR graph,YNODEPTR target)); /*-------------------------------------------------- Ygraph_dfs: Perform a depth first search --------------------------------------------------*/ extern YDECKPTR Ygraph_dfs(P1(YGRAPHPTR graph)); /*---------------------------------------------------------- Ygraph_mst_Kruskal: Find a mst using Kruskal's algorithm ----------------------------------------------------------*/ extern YDECKPTR Ygraph_mst_kruskal(P1(YGRAPHPTR graph)); /*---------------------------------------------------------- Ygraph_mst_prim: Find a mst using prim's algorithm ----------------------------------------------------------*/ extern YDECKPTR Ygraph_mst_prim(P2(YGRAPHPTR graph,YNODEPTR source)); /*---------------------------------------------------------- Ygraph_mst_dijkstra: Find a shortest paths from source ----------------------------------------------------------*/ extern VOID Ygraph_dijkstra(P2(YGRAPHPTR graph,YNODEPTR source)); /*---------------------------------------------------------- Ygraph_bellman_ford: single source shortest path for directed edge graph. Returns TRUE if shortest path found. Returns FALSE if negative weight cycle exists ----------------------------------------------------------*/ extern BOOL Ygraph_bellman_ford(P2(YGRAPHPTR graph,YNODEPTR source)); /*------------------------------------------------------- Ygraph_cycles: uses depth first search to find cycles in a graph. The returned deck contains all cycles. Each cycle is a deck. Thus, the returned deck contains decks. The user is responsible for freeing memory. ---------------------------------------------------------*/ extern YDECKPTR Ygraph_cycles(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_clearRequired: clear all nodes which must part of any steiner tree -------------------------------------------------*/ extern VOID Ygraph_clearRequired(P1(YGRAPHPTR graph)); /*------------------------------------------------- Ygraph_nodeRequired: insert a node which must be part of any steiner tree -------------------------------------------------*/ extern YNODEPTR Ygraph_nodeRequired(P3(YGRAPHPTR graph,YNODEPTR node,YNODEPTR equiv)); /*------------------------------------------------- Ygraph_nodeRequiredCount: Returns the number of nodes in the required node set. -------------------------------------------------*/ INT Ygraph_nodeRequiredCount( P1(YGRAPHPTR graph) ); /*------------------------------------------------- Ygraph_enumerateRequired: enumerates all nodes which must be part of any steiner tree or required path. -------------------------------------------------*/ extern YNODEPTR Ygraph_enumerateRequired(P2(YGRAPHPTR graph,BOOL startFlag)); /*------------------------------------------------------------ Ygraph_requiredPath() Perform a beadth first seach to find a single path between nodes of different sets. Use Ygraph_nodeRequired() to set up initial sets. Use Ygraph_clearRequired() to clear initial sets. ------------------------------------------------------------*/ extern YDECKPTR Ygraph_requiredPath(P1(YGRAPHPTR graph)); /*-------------------------------------------------- Return size of last required path --------------------------------------------------*/ extern INT Ygraph_requiredPathSize(P1(YGRAPHPTR graph)); /*---------------------------------------------------------- Ygraph_steiner: Find the mst for a set of nodes. Returns a graph which spans the required nodes. The returned graph is not guaranteed to be optimal. A random interchange is performed maxImproves times in an attempt to reduce the weight of the spanning graph. The user can use Ygraph_size() to find the total cost of the returned steiner tree. ----------------------------------------------------------*/ extern YGRAPHPTR Ygraph_steiner(P2(YGRAPHPTR graph,int maxImproves)); /*---------------------------------------- Improves the steiner tree. The original graph must have its required nodes properly set. ----------------------------------------*/ VOID Ygraph_steinerImprove(P3(YGRAPHPTR graph,YGRAPHPTR steinerGraph, int maxIterations)); /*--------------------------------------- Ygraph_copy: copy a graph. ---------------------------------------*/ extern YGRAPHPTR Ygraph_copy( P1(YGRAPHPTR graph) ); /*---------------------------------------------------------- Ygraph_nodeVerify: Verify a nodes data structure ----------------------------------------------------------*/ extern int Ygraph_nodeVerify(P1( YNODEPTR node )); /*---------------------------------------------------------- Ygraph_verify: exercise graph data structure ----------------------------------------------------------*/ extern int Ygraph_verify(P1(YGRAPHPTR graph)); /*------------------------------------------------------------ Ygraph_dump: print graph stats and call user print functions ------------------------------------------------------------*/ extern VOID Ygraph_dump(P3(YGRAPHPTR graph,VOID (*printNode)(),VOID (*printEdge)())); /*--------------------------------------------------------- Sets up the users draw functions for Ygraph_draw. ---------------------------------------------------------*/ extern VOID Ygraph_drawFunctions(P3( YGRAPHPTR graph, VOID (*userNodeDraw)(), VOID (*userEdgeDraw)())); /*--------------------------------------------------------- Get the current edge weight function ---------------------------------------------------------*/ extern INT (*Ygraph_getEdgeWeightFunction(P1(YGRAPHPTR graph)))(); /*--------------------------------------------------------- Set the current edge weight function ---------------------------------------------------------*/ extern VOID Ygraph_setEdgeWeightFunction(P2(YGRAPHPTR graph, INT (*userEdgeWeight)())); /*--------------------------------------------------------- Call the users drawing functions for all required nodes To use this function first call Ygraph_drawFunctions(). The user's node draw function will be passed a node and a color. The user's edge draw function will be passed an edge and a color. Some sample edge and node draw function are below: VOID drawNode(node,color) YNODEPTR node; int color; { myNodeType n; n = (myNodeType) Ygraph_nodeData(node); TW3DdrawLine(0,n->x,n->y,n->z,n->x,n->y,n->z,color,0); } VOID drawEdge(edge,color) YEDGEPTR edge; int color; { myEdgeType e; e = (myEdgeType) Ygraph_edgeData(edge); TW3DdrawLine(0,e->x1,e->y1,e->z1,e->x2,e->y2,e->z2,color,0); } ---------------------------------------------------------*/ extern VOID Ygraph_drawRequired(P1(YGRAPHPTR graph)); /*--------------------------------------------------------- Call the users drawing functions for all primed edges User must write drawing routines since library has no way of knowing what node and edge data is. To use this function first call Ygraph_drawFunctions(). The user's node draw function will be passed a node and a color. The user's edge draw function will be passed an edge and a color. Some sample edge and node draw function are below: VOID drawNode(node,color) YNODEPTR node; int color; { myNodeType n; n = (myNodeType) Ygraph_nodeData(node); TW3DdrawLine(0,n->x,n->y,n->z,n->x,n->y,n->z,color,0); } VOID drawEdge(edge,color) YEDGEPTR edge; int color; { myEdgeType e; e = (myEdgeType) Ygraph_edgeData(edge); TW3DdrawLine(0,e->x1,e->y1,e->z1,e->x2,e->y2,e->z2,color,0); } ---------------------------------------------------------*/ extern VOID Ygraph_drawPrime(P1(YGRAPHPTR graph)); /*--------------------------------------------------------- Call the users drawing functions for all nodes and edges User must write drawing routines since library has no way of knowing what node and edge data is. To use this function first call Ygraph_drawFunctions(). The user's node draw function will be passed a node and a color. The user's edge draw function will be passed an edge and a color. Some sample edge and node draw function are below: VOID drawNode(node,color) YNODEPTR node; int color; { myNodeType n; n = (myNodeType) Ygraph_nodeData(node); TW3DdrawLine(0,n->x,n->y,n->z,n->x,n->y,n->z,color,0); } VOID drawEdge(edge,color) YEDGEPTR edge; int color; { myEdgeType e; e = (myEdgeType) Ygraph_edgeData(edge); TW3DdrawLine(0,e->x1,e->y1,e->z1,e->x2,e->y2,e->z2,color,0); } ---------------------------------------------------------*/ extern VOID Ygraph_draw(P1(YGRAPHPTR graph)); #endif /* YGRAPH_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/hash.h000066400000000000000000000070071305746555600221110ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) hash.h version 1.7 9/22/91" FILE: hash.h DESCRIPTION:Insert file for threaded hash routines. CONTENTS: DATE: Jul 17, 1988 REVISIONS: Nov 6, 1988 - added user delete function to delTable. Jan 18, 1989 - added DELETE operation to hash_search. Apr 27, 1989 - added Y prefix. Thu Apr 18 00:52:26 EDT 1991 - renamed functions. ----------------------------------------------------------------- */ #ifndef HASH_H #define HASH_H #include typedef struct ytable_rec { char *key ; char *data ; struct ytable_rec *next ; struct ytable_rec *threadNext ; /* thread thru entire table */ } YTABLEBOX, *YTABLEPTR ; typedef struct { YTABLEPTR *hash_table ; YTABLEPTR thread ; INT size ; } YHASHBOX, *YHASHPTR ; #define ENTER (INT) 1 #define FIND (INT) 0 #define DELETE (INT) 2 extern YHASHPTR Yhash_table_create( P1(INT numentries) ) ; /* Function: Returns a hash table with the given number of entries. More that one hash table can coexist at the same time. */ extern INT Yhash_table_get( P1( YHASHPTR hashtable ) ) ; /* Function: Returns the current size of hash table set by Yhash_table_create */ extern char *Yhash_search( P4(YHASHPTR hashtable, char *key, VOIDPTR data, INT operation ) ) ; /* Function: Hash table search routine. Given a hashtable and a key, perform the following operations: ENTER:if key is in table it, returns a pointer to the item. if key is not in table, add it to the table. returns NULL. FIND:if key is in table, it returns a pointer to the item. if key is not in the table, it returns NULL. DELETE:if key is in table, it returns -1 if key is not in table, it return NULL. Memory is not freed in the delete case, but marked dirty. Data is a pointer to the information to be store with the given key. */ extern char *Yhash_add( P4( YHASHPTR hashtable, char *key, char *(*add_function)(), BOOL *new_flag ) ) ; /* Function: Hash table search convenience routine. It avoids two calls to hash_search in the case of always adding to the table it the item does not exist. Hash_add adds to table if it doesn't already exist - new flag will be set to true. If key already exists in table then hash add will not add it to the hash table but will notify the user by setting new flag to false. The add_function is used to associate the information with the key. It should return a pointer to the memory where the information is stored. This function always returns a pointer to the data. */ extern Yhash_table_delete( P2(YHASHPTR hashtable,INT (*userdelete)() ) ) ; /* Function: Frees the memory associated with a hash table. The user make supply a function which deletes the memory associated with the data field. This function must have the data pointer supplied by the hash add routines as an argument,ie. Yhash_table_delete( my_hash_table, my_free_func ) ; my_free_func( data ) char *data ; { } */ extern INT Yhash_set_size( P1( YHASHPTR hashtable ) ) ; /* Function: Since this is a threaded hash table we can find the size of all the valid entries in the table in O(n) where n is the number of valid entries. Returns the number of valid entries. One may enumerate the hash table by writing the following loop. TABLEPTR ptr ; for( ptr = mytable->thread; ptr ; ptr= ptr->threadNext ){ ... } */ #endif /* HASH_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/heap.h000066400000000000000000000037701305746555600221060ustar00rootroot00000000000000 /**************************************************************************** **************************************************************************** File : heap.h Author : Ted Stanion Date : Mon Apr 30 22:36:17 1990 Abstract : Include file for heap.c Revisions : Futures : **************************************************************************** ****************************************************************************/ #ifndef HEAP_H #define HEAP_H #ifndef lint static char YHeap_SccsId[] = "@(#) heap.h version 1.3 7/11/91"; #endif #include /**************************************************************************** Structure : heap Author : Ted Stanion Date : Mon Apr 30 22:57:04 1990 Abstract : Top level data structure for heaps. *****************************************************************************/ typedef struct heap { INT (*heap_cmp)(); struct heap_el *top; } YHEAP, *YHEAPPTR; /**************************************************************************** Macro : heap_empty Author : Ted Stanion Date : Tue May 1 16:40:02 1990 Abstract : Returns TRUE if the heap is empty. *****************************************************************************/ #define heap_empty(h) (((h)->top) ? FALSE : TRUE) /************************************************************************ * * * Global Functions * * * ************************************************************************/ extern YHEAPPTR Yheap_init(); extern YHEAPPTR Yheap_init_with_parms(P1(INT (*fn)())); extern VOID Yheap_empty(P1(YHEAPPTR)); extern VOID Yheap_free(P1(YHEAPPTR)); extern VOID Yheap_insert(P2(YHEAPPTR, VOIDPTR)); extern VOIDPTR Yheap_delete_min(P1(YHEAPPTR)); extern VOIDPTR Yheap_top(P1(YHEAPPTR)); extern YHEAPPTR Yheap_meld(P2(YHEAPPTR, YHEAPPTR)); extern INT Yheap_cmp_num(P2(INT, INT)); extern INT Yheap_cmp_ptr(P2(VOIDPTR, VOIDPTR)); extern VOID Yheap_check_mem(); extern INT Yheap_verify(P1(YHEAPPTR)); #endif graywolf-0.1.4+20170307gite1bf319/include/yalecad/linalg.h000066400000000000000000000023211305746555600224260ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: linalg.h DESCRIPTION:Include file for linear algebra package. CONTENTS: DATE: Tue Jan 15 01:29:36 EST 1991 - original coding. REVISIONS: ----------------------------------------------------------------- */ #ifndef YLINALG_H #define YLINALG_H #ifndef lint static char YlinAlgId[] = "@(#) linalg.h version 1.1 1/15/91" ; #endif #define YEPSILON 1.0E-12 #define YMIN -1.0E-38 #define YZERO 0.0 #define YMATRIX( matrix, r, c ) matrix->m[r][c] /* the matrix itself */ typedef struct { INT rows ; INT columns ; DOUBLE **m ; } YMBOX, *YMPTR ; extern YMPTR Ymatrix_create( P2(INT rows, INT columns ) ) ; extern YMPTR Ymatrix_free( P1( YMPTR mptr ) ) ; extern YMPTR Ymatrix_transpose( P1( YMPTR mptr ) ) ; extern YMPTR Ymatrix_mult( P2(YMPTR aptr, YMPTR bptr ) ) ; extern YMPTR Ymatrix_sub( P2(YMPTR aptr, YMPTR bptr ) ) ; extern Ymatrix_disp( P1(YMPTR mptr ) ) ; extern YMPTR Ymatrix_eye( P1(INT size ) ) ; extern Ymatrix_zero( P1(YMPTR matrix ) ) ; extern YMPTR Ymatrix_copy( P1(YMPTR input ) ) ; extern YMPTR Ymatrix_linv( P1(YMPTR aptr ) ) ; extern YMPTR Ymatrix_cofactors( P1(YMPTR aptr ) ) ; #endif /* LINALG_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/list.h000066400000000000000000000157111305746555600221420ustar00rootroot00000000000000/* ---------------------------------------------------------------- FILE: list.h DESCRIPTION: Declarations for list management package. DATE: Dec 9, 1989 REVISIONS: Sun Nov 3 12:56:37 EST 1991 - modified from Ted. 12/09/91 - cleanup for non-ANSI compilers -R.A.Weier ----------------------------------------------------------------- */ #ifndef YLIST_H #define YLIST_H #ifndef lint static char Ylist_h_SID[] = "@(#) list.h Yale Version 1.7 12/9/91" ; #endif #include /**************************************************************************** Structure : Ylist Author : Ted Stanion Date : Thu Apr 19 22:16:29 1990 Abstract : Top level structure for holding lists. *****************************************************************************/ typedef struct ylist { INT (*comp)(); INT size; struct ylist_el *first, *last; struct ylist *next; } YLIST_STRUCT, *YLIST; /**************************************************************************** Structure : Ylist_el Author : Ted Stanion Date : Thu Apr 19 22:19:07 1990 Abstract : Structure for list element. *****************************************************************************/ typedef struct ylist_el { VOIDPTR data; struct ylist_el *next, *prev; } YLIST_EL_STRUCT, *YLIST_EL; /**************************************************************************** Macro : ylist_first Author : Ted Stanion Date : Fri Apr 20 13:22:58 1990 Abstract : Returns the first element in a list. *****************************************************************************/ #define Ylist_first(l) (l)->first /**************************************************************************** Macro : Ylist_last Author : Ted Stanion Date : Fri Apr 20 13:23:38 1990 Abstract : Returns the last element of a list. *****************************************************************************/ #define Ylist_last(l) (l)->last /**************************************************************************** Macro : Ylist_next Author : Ted Stanion Date : Tue Apr 24 13:52:00 1990 Abstract : Returns the next element of a list. *****************************************************************************/ #define Ylist_next(e) (e)->next /**************************************************************************** Macro : Ylist_prev Author : Ted Stanion Date : Tue Apr 24 13:52:42 1990 Abstract : Returns the previous element of a list. *****************************************************************************/ #define Ylist_prev(e) (e)->prev /**************************************************************************** Macro : Ylist_data Author : Ted Stanion Date : Tue Apr 24 13:53:27 1990 Abstract : Returns the data item contained by a list element. *****************************************************************************/ #define Ylist_data(e) (e)->data /************************************************************************* Macro : Ylist_data_replace Author : Ted Stanion Date : Wed Jan 16 15:16:39 1991 Abstract : Replaces data item contained by a list elelement. **************************************************************************/ #define Ylist_data_replace(e, i) (e)->data = (i) /**************************************************************************** Macro : Ylist_empty Author : Ted Stanion Date : Fri Apr 20 13:25:14 1990 Abstract : Returns TRUE if a list has no elements, FALSE otw. *****************************************************************************/ #define Ylist_empty(l) ((l)->size ? FALSE : TRUE) /************************************************************************* Macro : Ylist_size Author : Ted Stanion Date : Sat Feb 16 13:48:58 1991 Abstract : Retruns th number of elements in the list. **************************************************************************/ #define Ylist_size(l) ((l)->size) /**************************************************************************** Macro : Ylist_for_all Author : Ted Stanion Date : Thu Apr 19 22:30:59 1990 Abstract : Starts the walking of a list. Elements may NOT be deleted while walking the list. L is the list to be walked. E is a pointer to a YLIST_EL. Use YLIST_DATA to get to the actual data item. If you want to delete a list item while walking through the list, use YLIST_FOR_ALL_SAFE. Ylist_for_all(my_list, my_data) { do something to my_data ... } Ylist_for_all_end; *****************************************************************************/ #define Ylist_for_all(l, e) { \ for (e = (l)->first; e; e = e->next) { \ /**************************************************************************** Macro : Ylist_for_all_end Author : Ted Stanion Date : Thu Apr 19 23:17:45 1990 Abstract : Closes list-walking loop. *****************************************************************************/ #define Ylist_for_all_end }} /************************************************************************* Macro : Ylist_for_all_safe Author : Ted Stanion Date : Tue Feb 5 10:57:18 1991 Abstract : Starts the walking of a list. Elements may be deleted while walking the list. L is the list to be walked. E is a pointer to a YLIST_EL. Use YLIST_DATA to get to the actual data item. Close the loop with YLIST_FOR_ALL_SAFE_END. **************************************************************************/ #define Ylist_for_all_safe(l, e) \ { \ YLIST_EL LIST_xx_tmp; \ for (e = (l)->first; e; e = LIST_xx_tmp){ \ LIST_xx_tmp = (e)->next; \ /************************************************************************* Macro : Ylist_for_all_safe_end Author : Ted Stanion Date : Tue Feb 5 11:01:35 1991 Abstract : Ends safe list walking loop. **************************************************************************/ #define Ylist_for_all_safe_end }} /************************************************************************ * * * Global Functions * * * ************************************************************************/ extern YLIST Ylist_create(); extern YLIST Ylist_create_with_parms(P1(INT (*comp)())); extern VOID Ylist_enqueue(P2(YLIST list, VOIDPTR data)); extern VOID Ylist_push(P2(YLIST list, VOIDPTR data)); extern VOID Ylist_insert_after(P3(YLIST list, YLIST_EL item, VOIDPTR data)); extern VOID Ylist_insert_before(P3(YLIST list, YLIST_EL item, VOIDPTR data)); extern VOID Ylist_insert_in_order(P2(YLIST list, VOIDPTR data)); extern VOIDPTR Ylist_dequeue(P1(YLIST)); extern VOIDPTR Ylist_pop(P1(YLIST)); extern VOID Ylist_delete(P3(YLIST, YLIST_EL, INT (*user_delete)() )); extern BOOL Ylist_find_and_delete(P3(YLIST list,VOIDPTR data,INT (*user_delete)())); extern YLIST Ylist_sort(P1(YLIST list)); extern VOID Ylist_append(P2(YLIST l1, YLIST l2)); extern VOID Ylist_clear(P1(YLIST list)); extern VOID Ylist_free(P1(YLIST list)); extern VOID Ylist_check_mem(); #endif /* YLIST_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/mac.h000066400000000000000000000012511305746555600217210ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: mac.h CONTENTS: Definitions for directing conditional compiles on the Mac. DATE: May 2, 1990 REVISIONS: ----------------------------------------------------------------- */ #ifndef MAC_H #define MAC_H #ifndef lint static char Ymac_HId[] = "@(#) mac.h version 1.4 1/8/92" ; #endif #ifdef THINK_C #include #include #define ALTERNATE #define DEBUG /* #define CLEANUP_C */ #define SIGUSR1 1 #endif /* THINK_C */ #ifdef _AUX_SOURCE #define NBPG 4096 /* number of bytes per page */ #endif /* _AUX_SOURCE */ #endif /* MAC_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/message.h000066400000000000000000000135531305746555600226150ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: message.h DESCRIPTION:This file contains include file for message screen output routines. Various macros are defined in order that the user may substitute their own input/output routines. CONTENTS: MACRO DEFINITIONS DATE: Feb 2, 1988 static char SccsId[] = "@(#) message.h version 1.8 9/16/91" ; REVISIONS: Jan 27, 1989 - changed msg to YmsgG to denote that it is global variable. Apr 10, 1990 - now automatically add base.h for user. Fri Feb 15 15:40:07 EST 1991 - renamed message functions. Mon Sep 16 22:18:40 EDT 1991 - added missing extern. ----------------------------------------------------------------- */ /* message.h definitions for message system */ #ifndef MESSAGE_H #define MESSAGE_H #include #define MSG 0 #define ERRMSG 1 #define WARNMSG 2 #define DBGMSG 3 #define M_NORMAL 0 #define M_VERBOSE 1 #define M_SILENT 2 /* global definitions in message.c */ extern char *YmsgG ; /* use printMessage for the message system at this time */ #define M(x,y,z) (Ymessage_print( x,(char *)y,(char *)z)) #define FLUSHOUT() (Ymessage_flush()) /* define the output functions */ /* ----------------------------------------------------------------- Although seems pain in the neck to have a specific output macro for each number of file output, compiler will warn us of argument mismatch. This could also be done with vargs function but it is unknown if this is portable over all machines and compilers. */ #define OUT9(a,b,c,d,e,f,g,h,i) { sprintf(YmsgG,a,b,c,d,e,f,g,h,i) ; \ Ymessage_output(YmsgG) ; \ } #define OUT8(a,b,c,d,e,f,g,h) { sprintf(YmsgG,a,b,c,d,e,f,g,h) ; \ Ymessage_output(YmsgG) ; \ } #define OUT7(a,b,c,d,e,f,g) { sprintf(YmsgG,a,b,c,d,e,f,g) ; \ Ymessage_output(YmsgG) ; \ } #define OUT6(a,b,c,d,e,f) { sprintf(YmsgG,a,b,c,d,e,f) ; \ Ymessage_output(YmsgG) ; \ } #define OUT5(a,b,c,d,e) { sprintf(YmsgG,a,b,c,d,e) ; \ Ymessage_output(YmsgG) ; \ } #define OUT4(a,b,c,d) { sprintf(YmsgG,a,b,c,d) ; \ Ymessage_output(YmsgG) ; \ } #define OUT3(a,b,c) { sprintf(YmsgG,a,b,c) ; \ Ymessage_output(YmsgG) ; \ } #define OUT2(a,b) { sprintf(YmsgG,a,b) ; \ Ymessage_output(YmsgG) ; \ } #define OUT1(a) { sprintf(YmsgG,a) ; \ Ymessage_output(YmsgG) ; \ } /* catch errors with this one */ #define OUT() { sprintf(YmsgG,a) ; \ Ymessage_output(YmsgG) ; \ } /* message routines */ extern Ymessage_print( P3(INT messageType, char *routine, char *message) ) ; /* Function: Print a message to screen and/or to a file. There are the following types of messages: TYPE MODE ACTION ---- ---- ------ MSG Normal Written to stdout. File Redirect Written to file. File Redirect & verbose Written to stdout and to given file. Silent Ignored. Silent && File Redirect Written to file. ERRMSG Normal Written to stderr. Error count incremented. File Redirect Written to file & stderr. Error count inc. File Redirect & verbose Written to file & stderr. Error count inc. Silent Written to stderr. Error count incremented. Silent && File Redirect Written to file & stderr. Error count inc. DBGMSG Normal Written to stdout. File Redirect Written to file. File Redirect & verbose Written to stdout and to given file. Silent Ignored. Silent && File Redirect Written to file. WARNMSG Normal Written to stderr. Warning count inc. File Redirect Written to file. Warning count inc. File Redirect & verbose Written to stderr and to given file. WC inc. Silent Written to stderr. WC incremented. Silent && File Redirect Written to file & stderr. WC inc. YmsgG is a global pointer to a character buffer workspace. */ extern Ymessage_warn_count() ; /* Function: Increment the warning count. */ extern Ymessage_error_count() ; /* Function: Increment the error count. */ extern INT Ymessage_get_warncount() ; /* Function: Returns the warning count. */ extern INT Ymessage_get_errorcount() ; /* Function: Returns the error count. */ extern Ymessage_init( P1(FILE *fileptr) ) ; /* Function: Redirects the messages to the given file. */ extern Ymessage_output( P1(char *messageString ) ) ; /* Function: Output message to screen if verbose mode has been set or output message to a file if message have been redirected. Otherwise it does nothing. Used in the OUT macros. */ extern Ymessage_mode( P1(INT mode) ) ; /* Function: Set the message mode. It may be one of M_VERBOSE, M_NORMAL, or M_SILENT. */ extern BOOL Ymessage_get_mode() ; /* Function: Returns the state of the message mode switch. */ extern Ymessage_flush() ; /* Function: Flush the buffered output. */ extern Ymessage_close() ; /* Function: Close the output streams. */ #endif /* MESSAGE_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/okmalloc.h000066400000000000000000000072061305746555600227700ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: okmalloc.h CONTENTS: macro definitions for memory manager. DATE: Tue Mar 3 16:05:51 EST 1992 REVISIONS: ----------------------------------------------------------------- */ #ifndef YOKMALLOC_H #define YOKMALLOC_H #ifndef lint static char Yokmalloc_HId[] = "@(#) okmalloc.h version 1.1 3/5/92" ; #endif /* memory definitions - for portability and ease of use */ #ifndef MEM_DEBUG #define NIL( type ) (type) NULL #define YMALLOC(n, els) (els *) Ysafe_malloc((n)*sizeof(els)) #define YCALLOC(n, els) (els *) Ysafe_calloc(n, sizeof(els)) #define YREALLOC(ar,n,els) (els *) Ysafe_realloc(ar,(n)*sizeof(els)) #define YFREE(els) Ysafe_free(els) #define YVECTOR_MALLOC(lo, hi, els) (els *) Yvector_alloc(lo,hi,sizeof(els)) #define YVECTOR_CALLOC(lo, hi, els) (els *) Yvector_calloc(lo,hi,sizeof(els)) #define YVECTOR_FREE(ar,lo) Yvector_free( ar,lo,sizeof(* ar)) #define YVECTOR_REALLOC(ar,lo,hi,els) (els *) Yvector_realloc( ar,lo,hi,sizeof(els)) /* memory manager definitions - safety net between memory manager */ extern VOID Ysafe_free( P1(void *ptr) ) ; extern VOID Ysafe_cfree( P1(void *ptr) ) ; extern char *Ysafe_malloc( P1(INT bytes) ) ; extern char *Ysafe_calloc( P2(INT num_entries, INT bytes) ) ; extern char *Ysafe_realloc( P2(void *ptr, INT bytes) ) ; extern char *Yvector_alloc( P3(INT lo, INT hi, INT size ) ) ; extern char *Yvector_calloc( P3(INT lo, INT hi, INT size ) ) ; extern char *Yvector_realloc( P4(VOIDPTR array,INT lo,INT hi,INT size )) ; extern VOID Yvector_free( P3( VOIDPTR array, INT lo, INT size ) ) ; #else /* MEM_DEBUG - memory debug functions */ #define NIL( type ) (type) NULL #define YMALLOC(n, els) \ (els *) Ysafe_malloc((n)*sizeof(els),__FILE__,__LINE__) #define YCALLOC(n, els) \ (els *) Ysafe_calloc(n, sizeof(els),__FILE__,__LINE__) #define YREALLOC(ar,n,els) \ (els *) Ysafe_realloc(ar,(n)*sizeof(els),__FILE__,__LINE__) #define YFREE(els) \ Ysafe_free(els,__FILE__,__LINE__) #define YVECTOR_MALLOC(lo, hi, els) \ (els *) Yvector_alloc(lo,hi,sizeof(els),__FILE__,__LINE__) #define YVECTOR_CALLOC(lo, hi, els) \ (els *) Yvector_calloc(lo,hi,sizeof(els), __FILE__,__LINE__) #define YVECTOR_REALLOC(ar,lo,hi,els) \ (els *) Yvector_realloc( ar,lo,hi,sizeof(els),__FILE__,__LINE__) #define YVECTOR_FREE(ar,lo) \ Yvector_free( ar,lo,sizeof(* ar),__FILE__,__LINE__) /* memory manager definitions - safety net between memory manager */ extern VOID Ysafe_free( P3(void *ptr,char *file,INT line) ) ; extern VOID Ysafe_cfree( P3(void *ptr,char *file,INT line) ) ; extern char *Ysafe_malloc( P3(INT bytes,char *file,INT line) ) ; extern char *Ysafe_calloc( P4(INT num_entries, INT bytes,char *file,INT line) ) ; extern char *Ysafe_realloc( P4(void *ptr, INT bytes,char *file,INT line) ) ; extern char *Yvector_alloc( P5(INT lo, INT hi, INT size,char *file,INT line ) ) ; extern char *Yvector_calloc( P5(INT lo, INT hi, INT size,char *file,INT line ) ) ; extern char *Yvector_realloc( P6(VOIDPTR a,INT lo,INT h,INT s,char *f,INT l )) ; extern VOID Yvector_free( P5( VOIDPTR array, INT lo, INT size,char *f,INT l ) ) ; #endif /* MEM_DEBUG */ /* In both cases, define these */ extern INT YgetCurMemUse( P1(void) ) ; extern INT YgetMaxMemUse( P1(void) ) ; extern INT YcheckMemObj( P1(char *ptr) ) ; extern VOID YdebugMemory( P1(INT flag ) ) ; extern INT YcheckDebug( P1(VOIDPTR where ) ) ; extern VOID Yinit_memsize( P1(INT memsize) ) ; extern VOID Ydump_mem( P1(void) ) ; extern VOID Ypmemerror( P1(char *message ) ) ; #endif /* YOKMALLOC_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/program.h000066400000000000000000000025241305746555600226340ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) program.h version 1.5 3/5/92" FILE: program.h DESCRIPTION:Insert file for program utility routines. DATE: Mar 16, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef PROGRAM_H #define PROGRAM_H #include extern char *YinitProgram( P3(char *name, char *version, VOID (*introTextFunction)() ) ) ; /* Function: Returns string with program name, version, and compile date. This string is built with YmsgG (actually a global note G suffix ). The user may perform various initialization in introTextFunction. There are no arguments to introTextFunction but user may get at the return string by peeking at YmsgG. This routine also starts the elapsed timer. */ extern YexitPgm( P1(INT status) ) ; /* Function: Exit a program gracefully. It always outputs a message with the number of errors and warnings during the execution. A nonzero status means the execution failed. Status follows the normal UNIX rules. Exit program also calls the debug write function to create a dbg file if debug has been set. */ extern char *YgetProgName() ; /* Function: Returns the program name given in YinitProgram. */ #endif /* PROGRAM_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/project.h000066400000000000000000000025541305746555600226360ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: project.h CONTENTS: definitions for projection package. DATE: Tue Oct 29 15:05:57 EST 1991 REVISIONS: Thu Mar 5 03:41:11 EST 1992 - added very useful macro function Yproject_intersect. ----------------------------------------------------------------- */ #ifndef YPROJECT_H #define YPROJECT_H #ifndef lint static char Yproject_HId[] = "@(#) project.h version 1.2 3/5/92" ; #endif #define NOTOUCH 0 /* tiles don't touch or overlap */ #define TOUCH -1 /* tiles touch but dont overlap */ #define OVERLAP1 1 /* tiles overlap completely */ #define OVERLAP2 2 /* tiles overlap to right (top) */ #define OVERLAP3 3 /* tiles overlap to left (bot) */ /* very useful macro which determines intersection */ #define Yproject_intersect( t1_l, t1_r, t1_b, t1_t, t2_l, t2_r, t2_b, t2_t ) \ ( YprojectX((t1_l),(t1_r),(t2_l),(t2_r) ) ? \ YprojectY((t1_b),(t1_t),(t2_b),(t2_t) ) : 0 ) extern Yproject_space( P2(INT xspace, INT yspace ) ) ; extern INT YprojectX( P4( INT tile1_left, INT tile1_right, INT tile2_left, INT tile2_right ) ) ; extern INT YprojectY( P4( INT tile1_bot, INT tile1_top, INT tile2_bot, INT tile2_top ) ) ; #endif /* YPROJECT_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/queue.h000066400000000000000000000032151305746555600223070ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) queue.h version 1.4 10/9/90" FILE: queue.h DESCRIPTION:Insert file for queue library routines. DATE: Mar 16, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef QUEUE_H #define QUEUE_H #include /* *********** data structures *************** */ typedef struct yqueue_info { char *data ; struct yqueue_info *next ; } YQUEUEBOX, *YQUEUEPTR ; typedef struct { YQUEUEPTR top_of_queue ; YQUEUEPTR bot_of_queue ; } YQUEUE ; /* *********** FIFO routines *************** */ extern YinitQueue( P2(YQUEUE *queue, char *node ) ) ; /* Arguments: YQUEUE *queue ; char *node ; Function: Initialization of the queue handler (FIFO) for a given queue. User supplies a pointer to the data that should be stored in queue. */ extern char *YtopQueue( P1(YQUEUE *queue ) ) ; /* Arguments: YQUEUE *queue ; Function: Returns the users pointer to the first element in the FIFO. */ extern Yadd2Queue( P2(YQUEUE *queue, char *node ) ) ; /* Arguments: YQUEUE *queue ; char *node ; Function: Add a new element to the end of the queue. */ /* check status of the queue */ extern YQUEUEPTR YqueueNotEmpty( P1(YQUEUE *queue ) ) ; /* Arguments: YQUEUE *queue ; Function: Returns the QUEUEPTR if queue is not empty. NULL otherwise. */ /* debug function to dump the contents of the queue */ extern YdumpQueue( P1(YQUEUE *queue ) ) ; /* Arguments: YQUEUE *queue ; Function: Debug function for queue handler. */ #endif /* QUEUE_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/quicksort.h000066400000000000000000000010051305746555600232020ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: quicksort.h CONTENTS: quicksort definitions. DATE: Tue Mar 3 16:01:25 EST 1992 ----------------------------------------------------------------- */ #ifndef YQUICKSORT_H #define YQUICKSORT_H #ifndef lint static char Yquicksort_HId[] = "@(#) quicksort.h version 1.1 3/5/92" ; #endif extern VOID Yquicksort( P4(VOIDPTR base, INT n, INT size, INT (*compare)() ) ) ; #endif /* YQUICKSORT_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/radixsort.h000066400000000000000000000015001305746555600231750ustar00rootroot00000000000000#ifndef YRADIXSORT_H #define YRADIXSORT_H #include extern int Yradixsort7( P7(VOIDPTR *l1,INT n,UNSIGNED_INT endchar, VOIDPTR *tab, INT indexstart,char *(*ralloc)(), VOID (*rfree)() ) ) ; extern int Yradixsort5( P5(VOIDPTR *l1,INT n,UNSIGNED_INT endchar,VOIDPTR *tab, INT indexstart) ) ; extern int Yradixsort_pref( P2(VOIDPTR *l1,INT n) ) ; extern int Yradixsort4( P4(VOIDPTR *l1,INT n,UNSIGNED_INT endchar,VOIDPTR *tab)); extern int Yradixsort( P4(VOIDPTR *l1,INT n,VOIDPTR *tab,UNSIGNED_INT endchar)) ; extern int Yradixsort3( P3(VOIDPTR *l1,INT n, UNSIGNED_INT endchar) ) ; extern char *Yradix_prefix( P2(char *buffer, INT num ) ) ; extern int Yradix_number( P1(char *buffer ) ) ; extern char *Yradix_suffix( P1(char *buffer) ) ; extern char *Yradix_pref_clone( P1(char *buffer) ) ; #endif graywolf-0.1.4+20170307gite1bf319/include/yalecad/rbtree.h000066400000000000000000000277111305746555600224550ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: rbtree.h DESCRIPTION:Tree include file for binary and red-black trees. The same functionality as binary trees but better performance for trees > 100 elements. CONTENTS: DATE: Mar 30, 1990 REVISIONS: Oct 8, 1990 - added prototypes and tree size. Oct 22, 1990 - changed prototypes for rbtree_free. Apr 19, 1991 - added Yrbtree_verify for debugging -RAW Mon Aug 12 15:49:34 CDT 1991 - got rid of offset argument to rbtree. Sun Nov 3 12:55:27 EST 1991 - added missing function definitions: Yrbtree_search_... Fri Feb 7 16:29:58 EST 1992 - added Yrbtree_interval_size. ----------------------------------------------------------------- */ #ifndef RBTREE_H #define RBTREE_H #ifndef lint static char YrbtreeId[] = "@(#) rbtree.h version 1.20 5/22/92" ; #endif #include #ifndef YTREE_H_DEFS typedef struct tree YTREEBOX ; typedef struct tree *YTREEPTR ; #endif /* macro definition for tree structure see Yrbtree_init */ #define YRBTREE_INIT( tree_xz, compare_xz ) \ { \ tree_xz = Yrbtree_init( compare_xz ) ; \ } /* THE DEFINITIONS FOR SEARCH CLOSEST FUNCTIONALITY */ #define SEARCH_CLOSEST_NOP 0 #define SEARCH_CLOSEST_BELOW 1 #define SEARCH_CLOSEST_ABOVE 2 #define SEARCH_CLOSEST 3 /* ******************* BINARY TREE INCLUDE FILES ****************** */ extern YTREEPTR Yrbtree_init( P1(INT (*compare_func)() ) ) ; /* Arguments: INT compare_func() ; Function: Initializes a binary tree. The user should supply a compare comparison function similar to the one used by the UNIX quicksort routine. The function compare_func is assumed to have two arguments which are pointers to the arguments being compared. The function should return an integer less than, equal to, or greater than 0 according as the first argument is to be considered less than, equal to , or greater than the second. the distance in bytes that the key is offset from the beginning of the data record. The function returns a pointer to the tree data structure. Use the tree pointer returned by Yrbtree_init for all routines to work on this tree. The comparison function no longer needs to be unique. See Yrbtree_deleteCurrentEnumerate and Yrbtree_deleteCurrentInterval for more details. */ extern VOIDPTR Yrbtree_search( P2(YTREEPTR tree, VOIDPTR key ) ) ; /* Arguments: YTREEPTR tree ; VOIDPTR key ; Function: Given a binary tree data structure, it return the a pointer to the stored data object that matches the given key. It returns NULL if no match is found. Sets the search marker for subsequent search_suc and search_pred calls. */ extern VOIDPTR Yrbtree_min( P1(YTREEPTR tree) ) ; /* Arguments: YTREEPTR tree ; Function: Given a binary tree data structure, it return the a pointer to the minimum data object stored in the tree. It returns NULL if nothing is in the tree. Sets the search marker for subsequent search_suc and search_pred calls. */ extern VOIDPTR Yrbtree_max( P1(YTREEPTR tree ) ) ; /* Arguments: YTREEPTR tree ; Function: Given a binary tree data structure, it return the a pointer to the maximum data object stored in the tree. It returns NULL if nothing is in the tree. Sets the search marker for subsequent search_suc and search_pred calls. */ extern VOIDPTR Yrbtree_suc( P2(YTREEPTR tree, VOIDPTR key ) ) ; /* Arguments: YTREEPTR tree ; VOIDPTR key ; Function: Given a binary tree data structure, it return the a pointer to the successor to the given key stored in the tree. It returns NULL if nothing is in the tree or if no match to the key is found. */ extern VOID Yrbtree_insert( P2(YTREEPTR tree, VOIDPTR data ) ) ; /* Arguments: YTREEPTR tree ; VOIDPTR data ; Function: Insert an element into the tree. Data is a pointer to the users record to be store in the tree. Each record must contain a key to sort upon. */ extern VOIDPTR Yrbtree_enumerate( P2(YTREEPTR tree, BOOL startFlag) ) ; /* Arguments: YTREEPTR tree ; Function: Enumerate all the data in a tree. First time call with startFlag set to TRUE to get first element in tree starting at the minimum element. For all subsequent calls, pass a FALSE argument to get all the remaining members of the tree. Returns a pointer to the user record. Returns NULL when all elements have been requested or when no match can be found. */ extern VOID Yrbtree_enumeratePush( P1(YTREEPTR tree) ) ; /* Arguments: YTREEPTR tree ; Function: Push the current enumeratation posistion pointer on to a stack. This is useful if the user wishes to recursively enumerate trees. */ extern VOID Yrbtree_enumeratePop( P1(YTREEPTR tree) ) ; /* Arguments: YTREEPTR tree ; Function: Pop the current enumeratation posistion pointer off of the stack. This is useful if the user wishes to recursively enumerate trees. */ extern VOIDPTR Yrbtree_interval( P4(YTREEPTR tree, VOIDPTR low_key, VOIDPTR high_key, BOOL startFlag ) ) ; /* Arguments: YTREEPTR tree ; VOIDPTR low_key, *high_key ; BOOL startFlag; Function: Enumerate all the data in a tree between low_key and high_key. First time call with startFlag=TRUE to get first element in tree >= the low_key. For all subsequent calls, pass startFlag=FALSE to get all the remaining members of the tree. Returns NULL when element > high_key or no match can be found. */ extern INT Yrbtree_interval_size( P3(YTREEPTR tree,VOIDPTR low_key, VOIDPTR high_key) ) ; /* Arguments: YTREEPTR tree ; VOIDPTR low_key, *high_key ; Function: Given an interval describe by the low and high keys, it returns the number of elements in that interval. */ extern VOID Yrbtree_intervalPush( P1(YTREEPTR tree) ) ; /* Arguments: YTREEPTR tree ; Function: Push the current interval posistion pointer on to a stack. This is useful if the user wishes to recursively enumerate trees. */ extern VOID Yrbtree_intervalPop( P1(YTREEPTR tree) ) ; /* Arguments: YTREEPTR tree ; Function: Pop the current interval posistion pointer on to a stack. This is useful if the user wishes to recursively enumerate trees. */ extern VOID Yrbtree_interval_free( P4(YTREEPTR tree, VOIDPTR low_key, VOIDPTR high_key, VOID (*userDelete)()) ); /* Arguments: YTREEPTR tree ; VOIDPTR low_key, *high_key ; BOOL startFlag; Function: Enumerate all the data in a tree between low_key and high_key. All nodes between low_key and high_key are deleted from the tree. The data can be freed by specifying the userDelete parameter. See below for an example. */ extern BOOL Yrbtree_delete( P3(YTREEPTR tree, VOIDPTR key, VOID (*userDelete)() ) ) ; /* Arguments: YTREEPTR tree ; VOIDPTR key ; Function: Delete a node in the tree by using the key. If userDelete !=0, the user delete function supplied is executed with the pointer of the data stored at the tree node as its argument. For example, when we need to delete the tree node we also need to free a field of the data stored in addition to the data. If no user delete function is supplied, only memory corresponding to the tree structure is freed. . . . Yrbtree_delete( my_tree, key, my_data_delete ) ; . . . VOID my_data_delete( data ) MY_DATA_TYPE *data ; { Ysafe_free( data->my_allocated_field ) ; Ysafe_free( data ) ; } Returns 1 if successful, 0 otherwise. */ extern BOOL Yrbtree_deleteCurrentInterval(P2(YTREEPTR tree,VOID (*userDelete)())); /* Function: While in an interval loop, deletes the current element. This allows one to delete individual items that are not distinct with respect to the comparison function. See the rbtree test program to see how it is used. */ extern BOOL Yrbtree_deleteCurrentEnumerate(P2(YTREEPTR tree,VOID (*userDel)())); /* Function: Like Yrbtree_deleteCurrentInterval, this routine is call from inside an Yrbtree_enumerate loop. It will delete the current element and yet allow the user to continue enumeration. This allows one to delete individual items that are not distinct with respect to the comparison function. See the rbtree test program to see how it is used. */ extern VOID Yrbtree_empty( P2(YTREEPTR tree, VOID (*userDelete)() ) ) ; /* Arguments: YTREEPTR tree; BOOL freeDataflag; Function: Removes all nodes in the tree. If userDelete != 0, node data unallocated using userDelete function */ extern VOID Yrbtree_free( P2(YTREEPTR tree, VOID (*userDelete)() ) ) ; /* Arguments: YTREEPTR tree; BOOL freeDataflag; Function: Removes tree and all nodes in the tree. If userDelete != 0, node data unallocated using userDelete function */ extern INT Yrbtree_size( P1(YTREEPTR tree) ) ; /* Function: Find the total elements in the tree. */ extern INT(*Yrbtree_get_compare( P1(YTREEPTR tree) ))() ; /* Function: Returns a pointer to the tree's comparison function. */ extern INT Yrbtree_verify( P1(YTREEPTR tree) ) ; /* Function: Exercise tree pointers by walking through the tree. Useful for dubugging. The routine will fault or return a 0 if verification fails. The routine will return a 1 if verification is successful. */ extern VOIDPTR Yrbtree_search_closest( P3(YTREEPTR tree,VOIDPTR key,INT func) ) ; /* Function: Finds the closest match for a given key. Will return the exact match if it exists. Returns NULL if no items exist in tree. Sets the search marker for subsequent search_suc and search_pred calls. Func is used to control the meaning of closest relative to the comparison function. Ithas four values: SEARCH_CLOSEST_NOP SEARCH_CLOSEST SEARCH_CLOSEST_BELOW SEARCH_CLOSEST_ABOVE SEARCH_CLOSEST_NOP should be specified when the comparison function does not give an integer measure of the distance from a perfect match. SEARCH_CLOSEST is the normal mode. It returns the closest element to the key value based on the comparison functions return value. SEARCH_CLOSEST_BELOW returns the element closest to the key which is less than or equal to the given key. SEARCH_CLOSEST_ABOVE returns the element closest to the key which is greater than or equal to the given key. */ extern VOIDPTR Yrbtree_search_suc( P1(YTREEPTR tree) ) ; /* Function: Returns the sucessor to current search object (set by the search marker). Returns NULL if no such item exists. This routine should only be called after the search marker has been set by one of: Yrbtree_search_closest, Yrbtree_min, Yrbtree_max, or Yrbtree_search. */ extern VOIDPTR Yrbtree_search_pred( P1(YTREEPTR tree) ) ; /* Function: Returns the predecessor to current search object (set by the search marker). Returns NULL if no such item exists. This routine should only be called after the search marker has been set by one of: Yrbtree_search_closest, Yrbtree_min, Yrbtree_max, or Yrbtree_search. */ extern VOIDPTR Yrbtree_revlist( P2(YTREEPTR tree, BOOL startFlag) ) ; /* Function: Enumerate the tree in reverse order. */ extern VOID Yrbtree_dump( P2(YTREEPTR tree, VOID (*print_key)() )) ; /* Function: Dump the contents of a tree. Print keys takes one argument, a key. */ extern VOID Yrbtree_resort( P2(YTREEPTR tree, INT (*compare_func)() )) ; /* Function: Takes a tree and resorts the tree with a new comparison function. All search markers are reset to NIL. */ extern YTREEPTR Yrbtree_copy( P2(YTREEPTR tree,INT (*compare_func)() ) ); /* Function: Make a copy of a tree sorted with the given comparison function. Old tree remains allocated and all markers remain undisturbed. */ extern BOOL Yrbtree_insertIfUnique( P2(YTREEPTR tree, VOIDPTR data ) ) ; /* Arguments: YTREEPTR tree ; VOIDPTR data ; Function: Insert an element into the tree if it does exist in the tree. Returns TRUE if added to tree; otherwise returns FALSE. */ #endif /* RBTREE_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/relpos.h000066400000000000000000000152351305746555600224740ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: relpos.h DESCRIPTION:macro definition for relative position to global position. CONTENTS: REL_POS( orient_R, globalY_R, globalX_R, relativeX_R, relativeY_R, cellX_R, cellY_R ) ; INT orient_R, globalY_R, globalX_R, relativeX_R, relativeY_R, cellX_R, cellY_R ; DATE: Jun 30, 1988 REVISIONS: Aug 13, 1990 - moved to library for MC. Thu Feb 7 00:04:51 EST 1991 - now correctly handle the truncated center regardless of orientation with the addtion of the REL_POST MACROs. ----------------------------------------------------------------- */ /* ***************************************************************** static char SccsId[] = "@(#) relpos.h version 1.5 3/16/92" ; ***************************************************************** */ /* ----------------------------------------------------------------- The following is a macro which calculates the global pin position given an orientation, a cell center ( global position ) and the pin position relative to the cell center. The macro was designed for speed. For test purposes, the macro can be short circuited, and instead call a the rel_pos function - defined in output.c The _R is an attempt to avoid variable substition problems. ----------------------------------------------------------------- */ #ifndef RELPOS_H #define RELPOS_H #ifndef YTRANS_DEFS #define EXTERN extern #else #define EXTERN #endif #ifndef RELPOSFUNC #define REL_POS( orient_R,globX_R,globY_R,relX_R,relY_R,cellX_R,cellY_R )\ { switch( orient_R ){ \ case 0: \ globX_R = cellX_R + relX_R ; \ globY_R = cellY_R + relY_R ; \ break ; \ case 1: \ globX_R = cellX_R + relX_R ; \ globY_R = cellY_R - relY_R ; \ break ; \ case 2: \ globX_R = cellX_R - relX_R ; \ globY_R = cellY_R + relY_R ; \ break ; \ case 3: \ globX_R = cellX_R - relX_R ; \ globY_R = cellY_R - relY_R ; \ break ; \ case 4: \ globX_R = cellX_R - relY_R ; \ globY_R = cellY_R - relX_R ; \ break ; \ case 5: \ globX_R = cellX_R + relY_R ; \ globY_R = cellY_R + relX_R ; \ break ; \ case 6: \ globX_R = cellX_R - relY_R ; \ globY_R = cellY_R + relX_R ; \ break ; \ case 7: \ globX_R = cellX_R + relY_R ; \ globY_R = cellY_R - relX_R ; \ break ; \ } \ } /* this macro performs centering in addition */ #define REL_POST( orient_R,globX_R,globY_R,relX_R,relY_R,cellX_R,cellY_R )\ { switch( orient_R ){ \ case 0: \ globX_R = cellX_R + relX_R ; \ globY_R = cellY_R + relY_R ; \ break ; \ case 1: \ globX_R = cellX_R + relX_R ; \ globY_R = cellY_R - relY_R ; \ break ; \ case 2: \ globX_R = cellX_R - relX_R ; \ globY_R = cellY_R + relY_R ; \ break ; \ case 3: \ globX_R = cellX_R - relX_R ; \ globY_R = cellY_R - relY_R ; \ break ; \ case 4: \ globX_R = cellX_R - relY_R ; \ globY_R = cellY_R - relX_R ; \ break ; \ case 5: \ globX_R = cellX_R + relY_R ; \ globY_R = cellY_R + relX_R ; \ break ; \ case 6: \ globX_R = cellX_R - relY_R ; \ globY_R = cellY_R + relX_R ; \ break ; \ case 7: \ globX_R = cellX_R + relY_R ; \ globY_R = cellY_R - relX_R ; \ break ; \ } \ if( Ytrans_xflagG ){ \ globX_R++ ; \ } \ if( Ytrans_yflagG ){ \ globY_R++ ; \ } \ } #else /* defeat macro call function for test */ /* Note we need to pass address of global_R variable to effect a change */ #define REL_POS( orient_R,globX_R,globY_R,relX_R,relY_R,cellX_R,cellY_R )\ { \ Ytrans_rel_pos( orient_R, &(globX_R), &(globY_R), \ relX_R, relY_R, \ cellX_R, cellY_R ) ; \ } #define REL_POST(orient_R,globX_R,globY_R,relX_R,relY_R,cellX_R,cellY_R)\ { \ Ytrans_rel_post( orient_R, &(globX_R), &(globY_R), \ relX_R, relY_R, \ cellX_R, cellY_R ) ; \ } #endif /* RELPOSFUNC */ /* global variables */ EXTERN BOOL Ytrans_xflagG ; EXTERN BOOL Ytrans_yflagG ; /* global function definitions */ extern VOID Ytranslate( P5(INT *l,INT *b,INT *r,INT *t, INT orient) ) ; extern VOID Ytranslatef( P5(DOUBLE *l,DOUBLE *b,DOUBLE *r,DOUBLE *t, INT orient)); extern VOID Ytrans_init( P5(INT l,INT b,INT r,INT t, INT new_orient ) ) ; extern INT Ytrans_inv_orient( P1(INT orient ) ) ; extern VOID YtranslateC( P5(INT *l,INT *b,INT *r,INT *t, INT orient) ) ; extern VOID YtranslateT( P5(INT *l,INT *b,INT *r,INT *t, INT orient) ) ; extern VOID Ytrans_rel_pos(P7(INT ort,INT *gX,INT *gY,INT lX,INT lY,INT cx,INT cy)); /* extern VOID Ytrans_rel_post(P7(INT ort,INT *X,INT *Y,INT lX,INT lY,INT cx,INT cy)); */ extern VOID Ytrans_boun_init( P1(void) ) ; extern VOID Ytrans_boun_add( P2(INT x,INT y ) ) ; extern VOID Ytrans_boun( P4(INT orient,INT xc,INT yc,BOOL use_new_orient ) ) ; extern BOOL Ytrans_boun_pt( P2(INT *x_ret,INT *y_ret ) ) ; extern VOID Ytrans_boun_free( P1(void) ) ; #endif /* RELPOS_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/set.h000066400000000000000000000076201305746555600217620ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: set.h DESCRIPTION:Insert file for the set utility routines. The set members of the set are integers in a range [lowerLimitt..upperLimit]. The routines add & subtract members from the set efficiently. Multiple sets may be handled simultaneously. The complexity of the routines are as follows. Yset_init : O(n) Yset_free : O(n) Yset_member : O(1) Yset_add t : O(1) Yset_enumerate : O(1) Yset_empty : O(1) Yset_size : O(1) The Yset_empty gets its speed by incrementing the value of in_set. Since all tests for membership check a match of this value, all members of set can be deleted at once. NOTE: These set routines are best suited for applications where you need to enumerate the members of the set and the set is bounded by an integer. In other applications, they may not be as suitable. CONTENTS: Typedefs and definitions for set routines. DATE: Apr 10, 1989 REVISIONS: Dec 4, 1989 added Yset_size and made Yenumerate a macro. Apr 18, 1990 - now Yset_init allocate the set. Apr 19, 1990 - added YcompSet Fri Feb 15 15:39:18 EST 1991 - renamed set functions. ----------------------------------------------------------------- */ #ifndef SET_H #define SET_H #ifndef lint static char YsetId[] = "@(#) set.h (Yale) version 1.7 2/15/91" ; #endif #include typedef struct ysetlist { INT member ;/* Determining membership by finding match */ INT node ; /* name of node */ struct ysetlist *next ; /* set is a threaded array */ struct ysetlist *prev ; } YSETLISTBOX, *YSETLISTPTR ; typedef struct { INT size ; /* size of set */ INT cardinality ; /* number of members in the set */ INT in_set ; /* match for determining membership */ INT lowerLimit ; /* lower bound for set */ INT upperLimit ; /* upper bound for set */ YSETLISTPTR list ; /* a list enumerating members of set */ YSETLISTPTR *set ; /* set is an array of YLISTBOXes */ } YSET, *YSETPTR ; #define SETNULL (YSETLISTPTR) 0 /* set macro for finding size of the set */ #define Yset_size(x_xz) (x_xz->cardinality) /* Arguments: YSETPTR set ; Function: returns the cardinality of the set at current time. */ /* set macro for enumeration return the first item in the list of set */ #define Yset_enumerate(x_xz) (x_xz->list ) /* Arguments: YSETPTR set ; Function: returns the head of a list of nodes in the set. Use node record field as an indication of the element. */ extern YSETPTR Yset_init( P2(INT lowerLimit, INT upperLimit ) ) ; /* Arguments: INT lowerLimit, upperLimit ; Function: initialize set. lowerLimit and upperLimit specify set boundaries. returns a pointer to the set data structure. */ extern Yset_free( P1(YSETPTR set ) ) ; /* Arguments: YSETPTR set ; Function: free set previously allocated - set is pointer to a set record allocated by YinitSet. */ extern BOOL Yset_member( P2(YSETPTR set, INT node ) ) ; /* Arguments: YSETPTR set ; INT node ; Function: tests whether node is member of set. Returns true if member;otherwise it returns false. */ extern BOOL Yset_add( P2(YSETPTR set, INT node ) ) ; /* Arguments: YSETPTR set ; INT node ; Function: add node as member of set. returns TRUE if this a new member of set FALSE if already a member. */ extern Yset_delete( P2(YSETPTR set, INT node ) ) ; /* Arguments: YSETPTR set ; INT node ; Function: removes node from set. */ extern Yset_empty( P1(YSETPTR set ) ) ; /* Arguments: YSETPTR set ; Function: makes the set an empty set. */ extern Yset_comp( P1(YSETPTR set ) ) ; /* Arguments: YSETPTR set ; Function: takes the complement of the given set. */ #endif /* SET_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/stack.h000066400000000000000000000021761305746555600222750ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: stack.h DESCRIPTION:Macro descriptions for implementing simple stack operations. CONTENTS: DATE: Dec 6, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef lint static char StackSccsId[] = "@(#) stack.h version 1.3 10/9/90" ; #endif #ifndef STACK_H #define STACK_H #define YSIZE_STACK 0 #define YSTACK_POINT 1 #include #define YINITSTACK( stack_xyz, size_xyz ) \ { \ stack_xyz = (INT *) Ysafe_malloc( (size_xyz+2) * sizeof(int) ) ; \ stack_xyz[YSIZE_STACK] = size_xyz + 1 ; \ stack_xyz[YSTACK_POINT] = 1 ; \ } #define YCLEARSTACK( stack_xyz ) \ { \ stack_xyz[YSTACK_POINT] = 1 ; \ } #define YPOPSTACK( stack_xyz ) \ ( stack_xyz[YSTACK_POINT] > YSTACK_POINT ? stack_xyz[stack_xyz[YSTACK_POINT]--] : 0 ) #define YPUSHSTACK( stack_xyz, data_xyz ) \ { \ if( ++stack_xyz[YSTACK_POINT] <= stack_xyz[YSIZE_STACK] ){ \ stack_xyz[ stack_xyz[YSTACK_POINT] ] = data_xyz ; \ } else { \ M( ERRMSG, "YPUSHSTACK", "stack_overflow\n" ) ; \ } \ } #endif /* STACK_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/stat.h000066400000000000000000000032161305746555600221370ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: stat.h DESCRIPTION:utility routines to calculate min, max, mean, and variance. CONTENTS: DOUBLE Ystat_min( array, number_ele, size_ele ) char *array ; INT num_ele, INT size_ele ; DOUBLE Ystat_max( array, number_ele, size_ele ) char *array ; INT num_ele, INT size_ele ; DOUBLE Ystat_mean( array, number_ele, size_ele ) char *array ; INT num_ele, INT size_ele ; DOUBLE Ystat_var( array, number_ele, size_ele, mean ) char *array ; INT num_ele, INT size_ele ; DOUBLE mean ; DATE: Mar 7, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef YSTAT_H #define YSTAT_H #ifndef lint static char SccsYstat_H[] = "@(#) stat.h (Yale) version 1.1 4/21/91" ; #endif /* Function: Given an array of number_elements of size_element, calculate min */ extern DOUBLE Ystat_min( P3( VOIDPTR array, INT number_elements, INT size_element ) ) ; /* Function: Given an array of number_elements of size size_element,calculate max */ extern DOUBLE Ystat_max( P3( VOIDPTR array, INT number_elements, int size_element ) ) ; /* Function: Given an array of number_elements of size size_ele, calculate mean */ extern DOUBLE Ystat_mean( P3( VOIDPTR array, INT number_elements, INT size_element ) ) ; /* Function: Given an array of number_elements of size size_ele, calculate variance. NOTE also need to give mean calculated from above */ extern DOUBLE Ystat_var( P4(VOIDPTR array,INT number_elements, INT size_element, DOUBLE mean ) ) ; #endif /* YSTAT_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/string.h000066400000000000000000000040371305746555600224740ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) string.h version 1.7 3/6/92" FILE: string.h DESCRIPTION:Insert file for string library routines. DATE: Mar 16, 1989 REVISIONS: Tue Oct 23 01:29:24 EDT 1990 - added string prototypes. ----------------------------------------------------------------- */ #ifndef YSTRING_H #define YSTRING_H #include extern char *Ystrclone( P1(char *str) ) ; /* Function: Clone a string by allocating memory. User must free memory when done. */ extern char **Ystrparser( P3(char *str, char *delimiters,INT *numtokens ) ) ; /* Function: This string parsing function uses strtok to break up the string into tokens delimited by the set of characters given in the delimiter string. Numtokens is set to the number of parsed tokens. The function returns a pointer to an array of all the tokens each of which has been terminated with EOS. This function destroys the given string so remember to copy the string if you need the original string for future use. */ extern char *Yremove_lblanks( P1(char *bufferptr) ) ; /* Function: Remove leading blanks and tabs from a string. */ /* Function: Very often used string functions that are defined by system. See man pages for details. */ #ifndef __GNUC__ extern char *strcat( P2( char *str1, char *str2 ) ) ; extern char *strncat( P3( char *str1, char *str2, INT n ) ) ; extern char *strcpy( P2( char *str1, char *str2 ) ) ; extern char *strncpy( P3( char *str1, char *str2, INT n) ) ; extern char *strtok( P2( char *str, char *delimiters ) ) ; extern char *strchr( P2( char *str, char c ) ) ; extern char *strrchr( P2( char *str, char c ) ) ; extern char *index( P2( char *str, char c ) ) ; extern char *rindex( P2( char *str, char c ) ) ; extern unsigned int strlen( P1( char *str) ) ; extern INT strcmp( P2( char *str1, char *str2 ) ) ; extern INT strncmp( P3( char *str1, char *str2, INT n ) ) ; #endif /* __GNUCC__ */ #endif /* YSTRING_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/system.h000066400000000000000000000032741305746555600225140ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: system.h CONTENTS: definitions for system functions. DATE: Tue Oct 29 15:05:57 EST 1991 REVISIONS: ----------------------------------------------------------------- */ #ifndef YSYSTEM_H #define YSYSTEM_H #ifndef lint static char Ysystem_HId[] = "@(#) system.h version 1.1 3/5/92" ; #endif /* Ysystem - Function: An abstract interface to the system call. The first argument is the name of the program to be executed. It is used in the error message when the system call fails for some reason. The second argument is whether to abort the program or not. The third argument is the actual command that is to be processed. The fourth argument is the function to call upon failure. It has no arguments. Ysystem return the system error code if failure; 0 otherwise. */ extern INT Ysystem( P4(char *program,BOOL abortFlag,char *exec_statement, INT (*abort_func)() ) ) ; /* YcopyFile - Function: Copy a file from the source to the destination name. Aborts pgm if a failure. */ extern VOID YcopyFile( P2(char *sourcefile, char *destfile) ) ; /* YmoveFile - Function: Move a file from the source to the destination name. Aborts pgm if a failure. */ extern VOID YmoveFile( P2(char *sourcefile, char *destfile) ) ; /* Yrm_files - Function: Remove files from system. Wildcards are available. May be system dependent however. Never aborts pgm if a failure. */ extern VOID Yrm_files( P1(char *files) ) ; /* Ygetenv - Function: Interface to getenv system function. */ extern char *Ygetenv( P1(char *env_var) ) ; #endif /* YSYSTEM_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/tech.h000066400000000000000000000024601305746555600221070ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: tech.h DESCRIPTION:include file for technology lookup. DATE: Oct 13, 1990 REVISIONS: ----------------------------------------------------------------- */ #ifndef YTECH_H #define YTECH_H #ifndef lint static char YassignId[] = "@(#) tech.h (Yale) version 1.1 10/22/90" ; #endif #include #define TECH_CHARACTERISTIC (DOUBLE) 1000.0 #define LAYER1 "layer1" #define LAYER2 "layer2" #define LAYER3 "layer3" #define VIA1_2 "via1/2" #define VIA2_3 "via2/3" extern Ytech_init( P1(char *designName ) ) ; /* Function: Read a technology file for a given design. Must be called first before using other technology functions. */ extern INT Ytech_spacing( P2(char *object1, char *object2 ) ) ; /* Function: Returns the spacing between the two given objects. If it does not exist it defaults to zero. */ extern INT Ytech_width( P1(char *object) ) ; /* Function: Returns the width of the given object. If it does not exist it defaults to zero. */ extern INT Ytech_pitch( P1(char *object) ) ; /* Function: Convenience function that returns the pitch of a given object. It returns the sum of width and spacing for that object. */ #endif /* YTECH_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/tree.h000066400000000000000000000120401305746555600221160ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: tree.h DESCRIPTION:Tree include file for binary and red-black trees. CONTENTS: DATE: Mar 30, 1990 REVISIONS: ----------------------------------------------------------------- */ #ifndef TREE_H #define TREE_H #ifndef lint static char treeId[] = "@(#) tree.h version 1.3 10/9/90" ; #endif #ifndef RBTREE_H typedef struct tree { char *root ; /* the root of the tree */ INT (*compare_func)() ; /* how to compare two keys */ INT offset ; /* how to get the key */ } YTREEBOX, *YTREEPTR ; #endif /* macro definition for tree structure see Ytree_init */ #define YTREE_INIT( tree_xz, compare_xz, name_xz, key_name_xz ) \ { \ name_xz *p_xz ; \ p_xz = (name_xz *) Ysafe_malloc( sizeof(name_xz) ) ; \ tree_xz = Ytree_init( compare_xz, \ (int) &(p_xz->key_name_xz)-(int) (p_xz) ) ;\ Ysafe_free( p_xz ) ; \ } /* ******************* BINARY TREE INCLUDE FILES ****************** */ extern YTREEPTR Ytree_init( P2(INT compare_func(), INT offset ) ) ; /* Arguments: INT compare_func() ; INT offset ; Function: Initializes a binary tree. The user should supply a compare comparison function similar to the one used by the UNIX quicksort routine. The function compare_func is assumed to have two arguments which are pointers to the arguments being compared. The function should return an integer less than, equal to, or greater than 0 according as the first argument is to be considered less than, equal to , or greater than the second. Offset is the distance in bytes that the key is offset from the beginning of the data record. The function returns a pointer to the tree data structure. Use the tree pointer returned by Ytree_init for all routines to work on this tree. The macro YTREE_INIT has been designed to make calling this routine easier. The macro has the following syntax: YTREE_INIT( tree, compare_func, datarecordname, keyname ) where tree is the name of the returned tree. Compare_func is the name of the compare function. Data record name is the name of the record to be stored, and key name is the field to be used as the key to the record. */ extern char *Ytree_search( P2(YTREEPTR tree, char *key ) ) ; /* Arguments: YTREEPTR tree ; char *key ; Function: Given a binary tree data structure, it return the a pointer to the stored data object that matches the given key. It returns NULL if no match is found. */ extern char *Ytree_min( P1(YTREEPTR tree ) ) ; /* Arguments: YTREEPTR tree ; Function: Given a binary tree data structure, it return the a pointer to the minimum data object stored in the tree. It returns NULL if nothing is in the tree. */ extern char *Ytree_max( P1(YTREEPTR tree ) ) ; /* Arguments: YTREEPTR tree ; Function: Given a binary tree data structure, it return the a pointer to the maximum data object stored in the tree. It returns NULL if nothing is in the tree. */ extern char *Ytree_suc( P2(YTREEPTR tree, char *key ) ) ; /* Arguments: YTREEPTR tree ; char *key ; Function: Given a binary tree data structure, it return the a pointer to the successor to the given key stored in the tree. It returns NULL if nothing is in the tree or if no match to the key is found. */ extern Ytree_insert( P2(YTREEPTR tree, char *data ) ) ; /* Arguments: YTREEPTR tree ; char *data ; Function: Insert an element into the tree. Data is a pointer to the users record to be store in the tree. Each record must contain a key to sort upon. */ extern char *Ytree_enumerate( P1(YTREEPTR tree ) ) ; /* Arguments: YTREEPTR tree ; Function: Enumerate all the data in a tree. First time call with tree as argument to get first element in tree starting at the minimum element. For all subsequent calls, pass a NULL argument to get all the remaining members of the tree. Returns a pointer to the user record. Returns NULL when all elements have been requested or when no match can be found. Restrictions:can only be performed on 1 tree at a time. Use rbtree in this case. */ extern char *Ytree_interval( P3(YTREEPTR tree, char *low_key, char *high_key ) ) ; /* Arguments: YTREEPTR tree ; char *low_key, *high_key ; Function: Enumerate all the data in a tree between low_key and high_key. First time call with tree as argument to get first element in tree >= the low_key. For all subsequent calls, pass a NULL argument to get all the remaining members of the tree. Returns NULL when element > high_key or no match can be found. Restrictions:can only be performed on 1 tree at a time. Use rbtree in this case. */ extern BOOL Ytree_delete( P2(YTREEPTR tree, char *key ) ) ; /* Arguments: YTREEPTR tree ; char *key ; Function: Delete a node in the tree by using the key. Returns 1 if successful, 0 otherwise. */ #endif /* TREE_H */ graywolf-0.1.4+20170307gite1bf319/include/yalecad/wgraphics.h000066400000000000000000000107631305746555600231600ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: wgraphics.h DESCRIPTION:include file for binary file draw utilities NOTE: avoids X11 library link if graphics is to be dumped to file to be read later by the draw utility program. CONTENTS: typedefs, and external routines for draw facility DATE: Mar 21, 1989 - began as derivative of draw.h REVISIONS: May 15, 1990 - added TWsetFrame to include file Mon Aug 12 15:51:04 CDT 1991 - fixed problems with missing functions. ----------------------------------------------------------------- */ #ifndef WGRAPHICS_H #define WGRAPHICS_H #ifndef lint static char YwgraphicsId[] = "@(#) wgraphics.h (Yale) version 1.7 8/12/91" ; #endif /******** FUNCTIONS NORMALLY USED BY GRAPHIC PROGRAM USERS *********/ #define TWinitGraphics( argc, argv, numC, colors,menuPath,refresh_func) \ TWinitWGraphics( numC, colors ) /* Arguments: INT numC ; char **colors ; Function: Initialization of graphics package. Needs to be called first. DesiredColors is an array of strings of the desired colors. The colors must agree with the standard color map of the machine and in addition element 1 must be "white" and element two "black". Also element 0 is not used at this time. Use TWstdcolors to use the graphics packages builtin standard colors. NumC is the number of colors in the color array counting white and black. NOTE: it is advised that the TimberWolf standard colors be used if possible. Use TWstdcolors() for argument desiredColors and TWnumcolors() for numC arg and use include file . NOTE: In this use argc, argv, menuPath and refresh_func are ignored */ #define TWcloseGraphics() (TWcloseWGraphics()) /* Arguments: None Function: Closes graphics display and performs cleanup operations. Should be performed before end of program. */ #define TWdrawNet(ref_num, x1, y1, x2, y2, color, label ) \ TWdrawWLine(ref_num, x1, y1, x2, y2, color, label ) #define TWdrawLine(ref_num, x1, y1, x2, y2, color, label ) \ TWdrawWLine(ref_num, x1, y1, x2, y2, color, label ) /* Arguments: INT ref_num, x1, y1, x2, y2, color ; char *label ; Function: Draws a net/line to screen and/or file. Ref_num is a reference number to associate all lines of a net - currently not used. X1, y1, x2, y2 are the two points of the line of a net. Color is the element number in color array. For example white is 1 and black is 2. Label is optional - a label is attached to figure if non-null. */ #define TWdrawCell(ref_num, x1, y1, x2, y2, color, label )\ TWdrawWRect(ref_num, x1, y1, x2, y2, color, label ) #define TWdrawRect(ref_num, x1, y1, x2, y2, color, label )\ TWdrawWRect(ref_num, x1, y1, x2, y2, color, label ) /* Arguments: INT ref_num, x1, y1, x2, y2, color ; char *label ; Function: Draws a cell to screen and/or file. Ref_num is a reference number to associate cell - currently not used. X1, y1, x2, y2 are the lower left, upper right points of cell. Color is the element number in color array. For example white is 1 and black is 2. Label is optional - a label is attached to figure if non-null. */ #define TWdrawPin(ref_num, x1, y1, x2, y2, color, label ) \ TWdrawWPin(ref_num, x1, y1, x2, y2, color, label ) /* Arguments: INT ref_num, x1, y1, x2, y2, color ; char *label ; Function: Draws a pin to screen and/or file. Ref_num is a reference number to associate pin - currently not used. X1, y1, x2, y2 are the lower left, upper right points of pin. Color is the element number in color array. For example white is 1 and black is 2. Label is optional - a label is attached to figure if non-null. */ /* copy pixmap to screen and flush screen output buffer */ #define TWflushFrame() TWflushWFrame() /* Arguments: None. Function: Flush the screen output and/or file buffer. This call must be made after all data of a frame is written, that is after all TWdraws have performed. */ #define TWstartFrame() TWstartWFrame() /* Arguments: None. Function: Start a new file frame. This call must be made before data is written, that is before any TWdraws are performed for a given frame. */ #define TWsetFrame( frame_xz ) TWsetWFrame( frame_xz ) /* Arguments: INT frame_x ; Function: Resets dump to screen dump to given file. If zero is given, it set the frame to one past the last frame found in the specified DATA directory. */ #endif graywolf-0.1.4+20170307gite1bf319/include/yalecad/yreadpar.h000066400000000000000000000076451305746555600230050ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: readpar.h DESCRIPTION:The include file for reading TimberWolf parameter files. CONTENTS: DATE: Oct 25, 1990 REVISIONS: Sat Jan 26 12:36:04 PST 1991 - added genrows GENR to list of programs. Sat Feb 23 00:46:29 EST 1991 - added TOMUS program and added wildcarding argument to Yreadpar_next. Thu Apr 18 00:53:01 EDT 1991 - added design rule parameter extraction routines. ----------------------------------------------------------------- */ #ifndef YREADPAR_H #define YREADPAR_H #ifndef lint static char YreadParId[] = "@(#) yreadpar.h version 1.4 4/18/91" ; #endif #include #include /* The following are valid programs */ #define ALLP -1 #define UNKN 0 #define CMPT 1 #define GENR 2 #define MICK 3 #define MINC 4 #define PART 5 #define SGGR 6 #define TWAR 7 #define TWMC 8 #define TWSC 9 #define USER 10 #define MAXID USER /* set this to the last program */ typedef YTREEPTR YPARPTR ; typedef YTREEBOX YPARBOX ; extern VOID Yreadpar_init( P4(char *design_name, INT program, INT filter, BOOL abortFlag ) ) ; /* ******************* READPAR ROUTINES ****************** */ /* Function: Initializes the readpar mechanism. This must be call before any other readpar functions. Restrictions: only one parameter file may be read at a time. Design_name is the name of the design. Program is one of the listed program id's at the top of this file. The filter is used to screen out other programs. There are two ways of initializing the parameter files. In the first case program = USER, and filter is one of the programs such as SGGR. The second way is to specify program = filter = program such as SGGR. If abort flag is set true, the routine will exit program if file is not found. If abort flag is set false, it will ignore any subsequent readpar commands relating to this file. */ extern char **Yreadpar_next( P5(char **lineptr,INT *line, INT *numtokens,BOOL *onNotOff,BOOL *wildcard)) ; /* Function: Reads a parameter one line at a time ignoring comments. Returns only parameters which pertain to the given program. Nothing is stored in memory. Lineptr is the contents of the current line, line is the current line number. Numtokens is the number of tokens returned and onNotOff tells the state of the variable. Wildcard returns whether this line is a wildcard. Wildcard should not generate error messages in the programs readpar file. */ extern YPARPTR Yreadpar_file(); /* Function: Reads the an entire parameter file and stores the data in memory to be accessed randomly using Yreadpar_lookup. Returns a par_object to be used with Yreadpar_lookup. */ extern char **Yreadpar_lookup( P4(YPARPTR par_object, char *param, INT program, INT *numtokens )) ; /* Function: Given a par object, and a program id, look up the given parameter. If the parameter is found it will return a token buffer similar to argv[]. In addition, numtokens will be set to the number of tokens in the argument vertor. If no match is found for the parameter, a NULL ptr is returned. */ /* The routines below get spacing, width, pitch, etc. for the design */ extern DOUBLE Yreadpar_spacing( P2(char *object1, char *object2 ) ) ; extern DOUBLE Yreadpar_width( P1(char *object) ) ; extern DOUBLE Yreadpar_pitch( P1(char *object) ) ; extern DOUBLE Yreadpar_layer_res( P1(char *object) ) ; extern DOUBLE Yreadpar_layer_cap( P1(char *object) ) ; extern BOOL Yreadpar_layer_HnotV( P1(char *object) ) ; extern INT Yreadpar_layer2id( P1(char *object) ) ; extern char *Yreadpar_id2layer( P1(INT layerid) ) ; extern INT Yreadpar_numlayers() ; extern char *Yreadpar_vianame( P2(char *object1, char *object2) ) ; extern char *Yreadpar_viaId2name( P1(INT viaid) ) ; #endif /* YREADPAR_H */ graywolf-0.1.4+20170307gite1bf319/script/000077500000000000000000000000001305746555600172705ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/script/CMakeLists.txt000066400000000000000000000007571305746555600220410ustar00rootroot00000000000000 add_custom_command(OUTPUT show_flows COMMAND sed 's;TWFLOWDIR;${CMAKE_INSTALL_PREFIX}/lib/graywolf;' ${CMAKE_SOURCE_DIR}/script/show_flows.in > ${CMAKE_BINARY_DIR}/script/show_flows) add_custom_target(run ALL DEPENDS ${CMAKE_BINARY_DIR}/script/show_flows) install(FILES ${CMAKE_BINARY_DIR}/script/show_flows DESTINATION lib/graywolf/bin PERMISSIONS OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_READ GROUP_READ WORLD_READ OWNER_WRITE) install(FILES splt_file.a DESTINATION lib/graywolf/bin) graywolf-0.1.4+20170307gite1bf319/script/show_flows.in000066400000000000000000000037621305746555600220220ustar00rootroot00000000000000#!/bin/sh # # Copyright (C) 1991 Yale University # # This work is distributed in the hope that it will be useful; you can # redistribute it and/or modify it under the terms of the # GNU General Public License as published by the Free Software Foundation; # either version 2 of the License, # or any later version, on the following conditions: # # (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS # ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, # SALE OR # OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY # PATENT OR # OTHER RIGHTS NOT VESTED IN YALE. # # (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND # WARRANTIES # WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, # INCLUDING, # BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A # PARTICULAR # PURPOSE. # # (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES # WHATSOEVER TO # ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN # ARTICLE # (a) AND (b) above. # # (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, # EMPLOYEES AND # AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR # INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE # ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE # POSSIBILITY OF THE FOREGOING. # # # This shell script shows the flow directory options # "@(#) show_flows version 1.1 4/27/91" #set test = ${?TWDIR} #if $test != 1 then # echo "" # echo "ERROR[show_flows]:TWDIR environment variable not set" # echo "TWDIR is pathname of TimberWolf root directory" # echo "" # exit(1) ; #endif echo " " echo " " echo "Available installed flow directories are:" # get environment variable TWDIR #set twdir = /usr/lib/timberwolf /bin/ls -1l TWFLOWDIR/bin/flow | awk '{ print $8 $9 $10 }' echo " " echo "The current default flow directory is denoted by the arrow." echo " " echo " " exit 0 graywolf-0.1.4+20170307gite1bf319/script/splt_file.a000066400000000000000000000023561305746555600214210ustar00rootroot00000000000000########################################################################## # # FILENAME : splt_file.a # # FUNCTION : Split circuitName.cel into two files, called # circuitName.mcel and circuitName.scel respectively. The # file circuitName.mcel contains the part of various macro # cells and pads in file circuitName.cel; while file # circuitName.scel contains the standard cell part. # # RESTRICTION : All cells must be separated by a blank line. # # USAGE : awk -f [/path/]splt_file.a circuitName.cel # # CHANGES : GNU awk does not set FILENAME in the BEGIN block. # FILENAME picked up from arguments list. (8/27/03) # # "@(#) splt_file.a (Yale) version 1.2 12/18/89" ########################################################################## BEGIN { mfile = ARGV[ARGC - 1] ; sfile = ARGV[ARGC - 1] ; sub( /\..+/ , ".mcel" , mfile ) ; sub( /\..+/ , ".scel" , sfile ) ; printf( "\n" ) > sfile } $1 == "cell" { sc = 1; print $0 >> sfile; next } $1 == "hardcell" { sc = 0; print $0 >> mfile; next } $1 == "softcell" { sc = 0; print $0 >> mfile; next } $1 == "pad" { sc = 0; print $0 >> mfile; next } sc == 1 { print $0 >> sfile } sc == 0 { print $0 >> mfile } graywolf-0.1.4+20170307gite1bf319/src/000077500000000000000000000000001305746555600165535ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/src/CMakeLists.txt000066400000000000000000000003371305746555600213160ustar00rootroot00000000000000 add_subdirectory(Ylib) add_subdirectory(date) add_subdirectory(twmc) add_subdirectory(genrows) add_subdirectory(twflow) add_subdirectory(mincut) add_subdirectory(twsc) add_subdirectory(syntax) add_subdirectory(mc_compact) graywolf-0.1.4+20170307gite1bf319/src/Ylib/000077500000000000000000000000001305746555600174525ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/src/Ylib/CMakeLists.txt000066400000000000000000000014041305746555600222110ustar00rootroot00000000000000 #add_executable(mincut main.c output.c readcells.c ${CMAKE_SOURCE_DIR}/src/date/date.c) add_library(ycadgraywolf SHARED assign.c buster.c cleanup.c colors.c deck.c dialog.c draw.c dset.c edcolors.c file.c getftime.c graph.c grid.c hash.c heap.c list.c log.c menus.c message.c mst.c mytime.c okmalloc.c path.c plot.c program.c project.c queue.c quicksort.c radixsort.c rand.c rbtree.c relpath.c set.c stat.c stats.c string.c system.c time.c timer.c trans.c wgraphics.c ydebug.c yreadpar.c ) target_link_libraries(ycadgraywolf X11) target_link_libraries(ycadgraywolf m) set_target_properties(ycadgraywolf PROPERTIES VERSION 1.0.0 SOVERSION 1) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include) install(TARGETS ycadgraywolf DESTINATION lib) graywolf-0.1.4+20170307gite1bf319/src/Ylib/assign.c000066400000000000000000000353451305746555600211140ustar00rootroot00000000000000/* * Copyright (C) 1990-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: assign.c DESCRIPTION:solve the linear assignment problem. DATE: Jan 26, 1990 - modified mighty code. REVISIONS: Sun Nov 3 12:49:49 EST 1991 - made assign more memory efficient by using YVECTOR routines. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) assign.c (Yale) version 1.4 4/16/92" ; #endif #include #include #include #include #include static INT **costS = (INT **) NULL ; static INT *capS = (INT *) NULL ; static INT *rowS = (INT *) NULL ; static INT *colS = (INT *) NULL ; static INT *nextS = (INT *) NULL ; static INT *h1S = (INT *) NULL ; static INT *h2S = (INT *) NULL ; static INT *h3S = (INT *) NULL ; static INT *h4S = (INT *) NULL ; static INT *h5S = (INT *) NULL ; static INT *h6S = (INT *) NULL ; static void initassign(); static void shortestpath(); static void augmentation(); static void transformation(); static INT *allocatevector() ; static INT **allocatematrix() ; INT *Yassign( cost_matrix, m, n ) INT **cost_matrix ; INT m, n; /* * For bipatite graph with m source nodes ( i : rows ) * and n sink nodes ( j : cols ) connected by edges with costS[i][j] >=0 * an assignment of rows i to columns j is calculated which mininimizes * the costS * * z = sum costS[i][j] * x[i][j] i,j * subject to * * sum x[i][j] <= capS[j]; sum x[i][j] = 1; x[i][j] >= 0 * i j * * INPUT : The capacity vector capS[1..n] * costS matrix costS[1..m][1..n] * problem size m, n. m <= sum capS[j] * i * OUTPUT : Two vectors rowS[1..n], colS[1..m] describing rows and * columns of the selected matrix entries. * rowS[j] points to one of the rows assigned to col j. * Others may be accessed by next[rowS[j]] ... * scratch : h1S[1..m], h2S[1..n], h3S[1..m], h4S[1..n], h5S[1..n], h6S[1..n] * * method : First an optimal assignment of a subset of rows and * columns is constructed heuristically. Then shortest * augmenting paths are generated starting from unassigned * source nodes to sink nodes with free capacity, to determine * the solution of the complete problem. * REF : Lauther's class note; Burkhard & Derigs, "assignment * and matching problems, springer 1980 * * Problems with m < n are handled as an n by n problem with * c[i][j] = INFINITY for i > m. * Sink nodes j with capS[j] > 1 are handled like a bunch of * capS[j] nodes with capacity 1 each. */ { INT i, j, k; /* static void initassign(); static void shortestpath(); static void augmentation(); static void transformation(); */ costS = cost_matrix ; /* * Initialize candidate list for shortest path */ initassign(h1S, h2S, m, n); for( j = 2; j <= n; j++ ){ h6S[j] = j - 1; } h6S[1] = n; for( i = 1; i <= m; i++ ){ if( colS[i] == 0 ) { shortestpath( h1S, h2S, h3S, h4S, h5S, h6S, i, &j, &k, m, n ); augmentation( h5S, i, j ); transformation( h1S, h2S, h3S, h4S, k, m, n ); } } D( "Yassign/print", Yassign_print( costS, m, n ) ; ) ; #if 1 for( i = 1; i <= m; i++ ) { colS[0] += cost_matrix[i][colS[i]] ; } #endif return( colS ); } /* end assign */ static void initassign(ys, yt, m, n) INT ys[], yt[]; INT m, n; /* * Initializes, checks feasibility and constructs an optimal assignment * for a subset of rowSs and colSumns : * First we calculate ys[i] = min costS[i][j]; yt[j] = min (costS[i][j] - ys[i]) * j i * * Then admissible assignments (i,j) with c[i][j] = ys[i] + yt[j] * are made. */ { INT i, j, j0, ui, cij; INT neff = 0; /* total capacity */ /* initial assignment */ for( j = 1; j <= n; j++ ) { rowS[j] = 0; neff += capS[j]; } if( neff < m ) { M( ERRMSG, "initassign", "total capacity too small\n"); fprintf(stderr, "failed\n"); YexitPgm( 03 ); } /* * calculate ys and make trvial assignments */ for( i = 1; i <= m; i++ ) { colS[i] = 0; ui = ASSIGN_INF ; for( j = 1; j <= n; j++ ) { if( costS[i][j] < ui ) { ui = costS[i][j]; j0 = j; } } ys[i] = ui; if( capS[j0] > 0 ) { capS[j0]--; nextS[i] = rowS[j0]; rowS[j0] = i; colS[i] = j0; yt[j0] = 0; } } /* * calculate yt */ if( m < neff ) { for( j = 1; j <= n; j++ ){ yt[j] = 0; } } else { for( j = 1; j <= n; j++ ) { if( rowS[j] == 0 ) { ui = ASSIGN_INF ; for( i = 1; i <= m; i++ ) { if( (cij = costS[i][j] - ys[i]) < ui ){ ui = cij; } } yt[j] = ui; } } } /* * make admissible assignments */ for( i = 1; i <=m; i++ ) { if( colS[i] == 0 ) { ui = ys[i]; for( j = 1; j <=n; j++ ) { if( capS[j] > 0 ) { if( costS[i][j] == ui + yt[j] ) { capS[j]--; nextS[i] = rowS[j]; rowS[j] = i; colS[i] = j; goto DONE; } } } } DONE : continue; } } /* end initassign */ static void shortestpath( ys, yt, dplus, dminus, back, next, i, indexp, dp, m, n ) INT ys[], yt[], dplus[], dminus[], back[], next[]; INT *indexp; INT *dp; INT i, m, n; /* * Finds a shortest path from starting node i to sink node index * using Dijkstra's algorithm and modify costs. * next is a cyclic list of all sink nodes. * next[headcand..lastcand] are the active candidate nodes. * back points back in the path. */ { INT lastcand, headcand, v, vgl, j, dalt, ysi; for( j = 1; j <= n; j++ ) dminus[j] = ASSIGN_INF ; for( j = 1; j <= m; j++ ) dplus[j] = ASSIGN_INF ; lastcand = headcand = n; *dp = 0; /* till sink node with free capacity is reached */ for( ;; ) { dplus[i] = dalt = *dp; *dp = ASSIGN_INF ; v = headcand; ysi = ys[i]; /* for all active and feasible sink nodes */ for( ;; ) { j = next[v]; if( capS[j] > 0 || rowS[j] > 0 ) { /* update distance */ vgl = dalt + costS[i][j] - ysi - yt[j]; if( vgl < dminus[j] ) { dminus[j] = vgl; back[j] = i; } if( dminus[j] < *dp ) { *dp = dminus[j]; *indexp = v; } } v = j; if( v == lastcand ) break; } /* * remove next[v] from candidate set */ v = *indexp; *indexp = next[v]; if( *indexp == lastcand ){ lastcand = v; } else { next[v] = next[*indexp]; next[*indexp] = next[headcand]; next[headcand] = *indexp; headcand = *indexp; } i = rowS[*indexp]; if( capS[*indexp] > 0 ){ break; } } } /* end shortest path */ static void augmentation( back, u, ind ) INT back[]; INT u, ind; /* * tracing back the augmenting path from index back to u, * assignments are updated accordingly. */ { INT oldind; INT w = (INT)NULL; (capS[ind])--; for( ; w != u; ) { oldind = ind; w = back[ind]; if( w != u ) { /* remove w, colS[w] from list associated with colS[w] */ ind = colS[w]; rowS[ind] = nextS[w]; } /* add ede w, index to list associated with index */ nextS[w] = rowS[oldind]; rowS[oldind] = w; colS[w] = oldind; } } /* end augmentation */ static void transformation( ys, yt, dplus, dminus, d, m, n ) INT ys[], yt[], dplus[], dminus[] ; INT d ; /* * update ys and yt */ { INT i; for( i = 1; i <= m; i++ ) { if( dplus[i] != ASSIGN_INF ){ ys[i] = ys[i] + d - dplus[i]; } } for( i = 1; i <= n; i++ ) { if( dminus[i] < d ){ yt[i] = yt[i] - d + dminus[i]; } } } /* end transformation */ INT **Yassign_init(m, n) INT m, n ; { INT j ; INT **cost_matrix ; /* static INT *allocatevector() ; static INT **allocatematrix() ; */ capS = allocatevector( n ) ; for( j = 1; j <= n; j++ ){ capS[j] = 1 ; } cost_matrix = allocatematrix( m, n ); rowS = allocatevector( n ); #if 1 colS = YVECTOR_CALLOC( 0, m, INT ) ; #else colS = allocatevector( m ); #endif nextS = allocatevector( m ); h1S = allocatevector( m ); h2S = allocatevector( n ); h3S = allocatevector( m ); h4S = allocatevector( n ); h5S = allocatevector( n ); h6S = allocatevector( n ); return( cost_matrix ); } /* end structure */ void Yassign_reset(cost_matrix, m, n ) INT m, n ; INT **cost_matrix ; /* * reset to 0 all the entries, except capacities which are 1 */ { INT i, j; for( j = 1; j <= n; j++ ) capS[j] = 1; for( i = 1; i <= m; i++ ) for( j = 1; j <= n; j++ ) cost_matrix[i][j] = 0; for( j = 1; j <= n; j++ ) rowS[j] = 0; for( i = 1; i <= m; i++ ) colS[i] = 0; #if 1 colS[0] = 0; #endif for( i = 1; i <= m; i++ ) nextS[i] = 0; for( i = 1; i <= m; i++ ) h1S[i] = 0; for( j = 1; j <= n; j++ ) h2S[j] = 0; for( i = 1; i <= m; i++ ) h3S[i] = 0; for( j = 1; j <= n; j++ ) h4S[j] = 0; for( j = 1; j <= n; j++ ) h5S[j] = 0; for( j = 1; j <= n; j++ ) h6S[j] = 0; } /* end Yassign_reset */ static INT **allocatematrix ( rows, cols ) INT rows, /* number of rows */ cols; /* number of columns */ { INT i ; /* loop counters */ INT ** matrix; /* the allocated matrix */ /* * Allocate space for the matrix */ matrix = YVECTOR_MALLOC( 1, rows, INT * ) ; for (i = 1; i <= rows; i++){ matrix[i] = YVECTOR_CALLOC( 1, cols, INT ) ; } return( matrix ); } /* end allocatematrix */ static INT *allocatevector( cols ) INT cols; /* number of columns */ { INT * vector; /* used to allocate the vector */ /* * Allocate space for the vector */ vector = YVECTOR_CALLOC( 1, cols, INT ) ; return( vector ) ; } /* end allocatevector */ void Yassign_print( cost_matrix, m, n ) INT m, n ; INT **cost_matrix ; { INT i, j, sum = 0, max = 0, cij; for( i = 1; i <= m; i++ ) { if( (cij = cost_matrix[i][colS[i]]) > max ){ max = cij; } sum += cij; } /* if too high, exit */ if( max >= ASSIGN_PREASSIGN ){ fprintf(stderr,"ERROR in assignment\n"); } fprintf(stderr,"sum = %d, max = %d\n", sum, max ); for( j = 1; j <= n; j++ ){ fprintf(stderr,"%d %d\n", j, capS[j]); } for( i = 1; i<= m; i++ ) { for( j = 1; j <=n; j++ ) { if( colS[i] == j ){ fprintf( stderr, "[%d]", cost_matrix[i][j]); } else { fprintf( stderr, " %d ", cost_matrix[i][j]); } } fprintf( stderr, "\n"); } } /* end Yassign_print */ void Yassign_free( cost_matrix, m, n ) INT **cost_matrix ; INT m, n ; { INT i ; for (i = 1; i <= m; i++){ YVECTOR_FREE( cost_matrix[i], 1 ) ; } YVECTOR_FREE( cost_matrix, 1 ) ; if( capS ){ YVECTOR_FREE( capS, 1 ) ; capS = (INT *) NULL ; } if( rowS ){ YVECTOR_FREE( rowS, 1 ) ; rowS = (INT *) NULL ; } if( colS ){ #if 1 YVECTOR_FREE( colS, 0 ) ; #else YVECTOR_FREE( colS, 1 ) ; #endif colS = (INT *) NULL ; } if( nextS ){ YVECTOR_FREE( nextS, 1 ) ; nextS = (INT *) NULL ; } if( h1S ){ YVECTOR_FREE( h1S, 1 ) ; h1S = (INT *) NULL ; } if( h2S ){ YVECTOR_FREE( h2S, 1 ) ; h2S = (INT *) NULL ; } if( h3S ){ YVECTOR_FREE( h3S, 1 ) ; h3S = (INT *) NULL ; } if( h4S ){ YVECTOR_FREE( h4S, 1 ) ; h4S = (INT *) NULL ; } if( h5S ){ YVECTOR_FREE( h5S, 1 ) ; h5S = (INT *) NULL ; } if( h6S ){ YVECTOR_FREE( h6S, 1 ) ; h6S = (INT *) NULL ; } } /* end Yassign_free */ #ifdef TEST #include main( argc , argv ) INT argc ; char *argv[] ; { INT i ; INT **c ; INT *answer ; char *intro ; /* start up cleanup handler */ YINITCLEANUP( argv[0], NULL, MAYBEDUMP ) ; Yinit_memsize( 1024 * 1024 ) ; YdebugMemory( FALSE ) ; intro = YinitProgram( "Test assignment", "v0.0", NULL ); fprintf( stderr, "\n%s\n\n", intro ) ; /* Yassign_init initializes a cost matrix of size x by y */ c = Yassign_init( 5, 5 ) ; c[1][1] = 7; c[1][2] = 2; c[1][3] = 1; c[1][4] = 9; c[1][5] = 4; c[2][1] = 9; c[2][2] = 6; c[2][3] = 9; c[2][4] = 5; c[2][5] = 5; c[3][1] = 3; c[3][2] = 8; c[3][3] = 3; c[3][4] = 1; c[3][5] = 8; c[4][1] = 7; c[4][2] = 9; c[4][3] = 4; c[4][4] = 2; c[4][5] = 2; c[5][1] = 8; c[5][2] = 4; c[5][3] = 7; c[5][4] = 4; c[5][5] = 8; answer = Yassign( c, 5, 5 ) ; /* returns a vector with the answers */ fprintf( stderr, "The answer is:" ) ; for( i = 1; i <= 5; i++ ){ fprintf( stderr, "%d ", answer[i] ) ; } fprintf( stderr, "\n" ) ; Yassign_print( c, 5, 5 ) ; /* now if you know that the memory size is ok and just want to */ /* change the cost matrix use Yassign_reset */ Yassign_reset(c, 5, 5 ) ; c[1][1] = 9; c[1][2] = 4; c[1][3] = 3; c[1][4] =11; c[1][5] = 6; c[2][1] =11; c[2][2] = 8; c[2][3] =11; c[2][4] = 7; c[2][5] = 7; c[3][1] = 5; c[3][2] =10; c[3][3] = 5; c[3][4] = 3; c[3][5] =10; c[4][1] = 9; c[4][2] =11; c[4][3] = 6; c[4][4] = 4; c[4][5] = 4; c[5][1] =10; c[5][2] = 6; c[5][3] = 9; c[5][4] = 6; c[5][5] =10; answer = Yassign( c, 5, 5 ) ; /* returns a vector with the answers */ fprintf( stderr, "The answer is:" ) ; for( i = 1; i <= 5; i++ ){ fprintf( stderr, "%d ", answer[i] ) ; } fprintf( stderr, "\n" ) ; Yassign_print( c, 5, 5 ) ; /* when you are done use Yassign_free */ Yassign_free( c, 5, 5 ) ; } /* end main */ #endif graywolf-0.1.4+20170307gite1bf319/src/Ylib/buster.c000066400000000000000000000252171305746555600211310ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: buster.c DESCRIPTION:This file contains the utility routine to break a rectilinear cell up into tiles. CONTENTS: YBUSTBOXPTR Ybuster() INT Ybuster_init() ; INT Ybuster_addpt( x, y ) ; void Ybuster_free() ; void Ybuster_clear() ; INT x, y ; DATE: Aug 7, 1988 - rewrote to match new parser. REVISIONS: May 1, 1990 - made sure we cannot match the 0 record in the redundancy check for points. May 4, 1990 - moved to the library since it now occurs in many files. Aug 23,1990 - added Ybuster_free, Ybuster_clear. Sat Dec 15 22:55:53 EST 1990 - added debug_verify code to buster. Wed Apr 17 23:39:20 EDT 1991 - rewrote buster verify for more extensive error checking. Thu Oct 17 11:08:18 EDT 1991 - added buster_chcek_rect. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) buster.c version 3.8 12/15/91" ; #endif #include #include #include #include #define EXPECTEDPTS 50 /* detect problems with clockwise rotation pattern */ #define E_STATE 0 #define U_STATE 1 #define L_STATE 2 #define R_STATE 3 #define D_STATE 4 #define S_STATE 5 /* start state */ /* ####################### STATIC definitions ######################### */ static INT cornerCountS ; /* current number of corners */ static INT ptAllocS = 0 ; /* current allocation for pts */ static YBUSTBOXPTR ptS = NIL(YBUSTBOXPTR) ;/* array of pts for boundary */ static YBUSTBOXPTR resultS; /* the array of pts to break into tiles */ static INT cur_stateS ; /* current state direction of edge */ static char *user_messageS; /* output message on error */ /* ################## END STATIC definitions ########################## */ static BOOL check_rect( P4(INT xx1, INT yy1, INT xx2, INT yy2 ) ) ; YBUSTBOXPTR Ybuster() { INT k , Pk[2] , Pl[2] , Pm[2] ; INT xmin , ymin , kmin , found ; if( cornerCountS <= 0 ){ return( NIL(YBUSTBOXPTR) ) ; } D( "Ybuster/debug", Ybuster_verify( NULL ) ; ) ; /* find Pk */ ymin = INT_MAX ; for( k = 1 ; k <= cornerCountS ; k++ ) { if( ptS[k].y < ymin ) { ymin = ptS[k].y ; } } /* we have the lowest y coordinate */ xmin = INT_MAX ; for( k = 1 ; k <=cornerCountS ; k++ ) { if( ptS[k].y == ymin ) { if( ptS[k].x < xmin ) { xmin = ptS[k].x ; kmin = k ; } } } /* we have the leftmost lowest corner */ Pk[0] = xmin ; Pk[1] = ymin ; xmin = INT_MAX ; for( k = 1 ; k <= cornerCountS ; k++ ) { if( k == kmin ) { continue ; } if( ptS[k].y == ymin ) { if( ptS[k].x < xmin ) { xmin = ptS[k].x ; } } } /* we have the next leftmost lowest corner */ Pl[0] = xmin ; Pl[1] = ymin ; ymin = INT_MAX ; for( k = 1 ; k <= cornerCountS ; k++ ) { if( ptS[k].y == Pk[1] ) { continue ; } if( ptS[k].y < ymin ) { ymin = ptS[k].y ; } } /* we have the next lowest y coordinate */ xmin = INT_MAX ; for( k = 1 ; k <= cornerCountS ; k++ ) { if( ptS[k].y == ymin ) { if( ptS[k].x < Pk[0] || ptS[k].x > Pl[0] ) { continue ; } if( ptS[k].x < xmin ) { xmin = ptS[k].x ; } } } /* we have the leftmost next lowest corner */ Pm[0] = xmin ; Pm[1] = ymin ; /* * According to the instruction sheet I read, we can * output the bounding rectangle of Pk , Pl , Pm. */ resultS[1].x = Pk[0] ; resultS[1].y = Pk[1] ; resultS[2].x = Pk[0] ; resultS[2].y = Pm[1] ; resultS[3].x = Pl[0] ; resultS[3].y = Pm[1] ; resultS[4].x = Pl[0] ; resultS[4].y = Pk[1] ; /* * Now weed out those elements of R which are in A and * add those elements of R which are not in A. * Note that index 1 and 4 are necessarily in A, and thus * have to be removed from A. */ for( k = 1 ; k <= cornerCountS ; k++ ) { if( resultS[1].x == ptS[k].x && resultS[1].y == ptS[k].y ) { ptS[k].x = ptS[ cornerCountS ].x ; ptS[k].y = ptS[ cornerCountS-- ].y ; break ; } } for( k = 1 ; k <= cornerCountS ; k++ ) { if( resultS[4].x == ptS[k].x && resultS[4].y == ptS[k].y ) { ptS[k].x = ptS[ cornerCountS ].x ; ptS[k].y = ptS[ cornerCountS-- ].y ; break ; } } found = 0 ; for( k = 1 ; k <= cornerCountS ; k++ ) { if( resultS[2].x == ptS[k].x && resultS[2].y == ptS[k].y ) { ptS[k].x = ptS[ cornerCountS ].x ; ptS[k].y = ptS[ cornerCountS-- ].y ; found = 1 ; break ; } } if( found == 0 ) { /* * Add the thing to the list A */ ptS[ ++cornerCountS ].x = resultS[2].x ; ptS[ cornerCountS ].y = resultS[2].y ; } found = 0 ; for( k = 1 ; k <= cornerCountS ; k++ ) { if( resultS[3].x == ptS[k].x && resultS[3].y == ptS[k].y ) { ptS[k].x = ptS[ cornerCountS ].x ; ptS[k].y = ptS[ cornerCountS-- ].y ; found = 1 ; break ; } } if( found == 0 ) { /* * Add the thing to the list A */ ptS[ ++cornerCountS ].x = resultS[3].x ; ptS[ cornerCountS ].y = resultS[3].y ; } return( resultS ) ; } /* end buster */ /* ***************************************************************** */ Ybuster_addpt( xpos, ypos ) INT xpos, ypos ; { if( xpos == ptS[cornerCountS].x && ypos == ptS[cornerCountS].y ){ /* avoid redundant points */ return ; } /* increase the space if necessary */ if( ++cornerCountS >= ptAllocS ){ ptAllocS += EXPECTEDPTS ; ptS = YREALLOC( ptS, ptAllocS, YBUSTBOX ) ; } ptS[cornerCountS].x = xpos ; ptS[cornerCountS].y = ypos ; } /* end add_arb_pt */ /* ***************************************************************** */ Ybuster_init() { /* allocate memory if needed */ if(!(ptS)){ ptAllocS = EXPECTEDPTS ; ptS = YMALLOC( ptAllocS, YBUSTBOX ); resultS = YMALLOC( 5, YBUSTBOX ) ; } /* make sure we cannot match the 0 record in the redundancy */ /* check above in add_arb_pt */ ptS[0].x = INT_MIN ; ptS[0].y = INT_MIN ; cornerCountS = 0 ; } /* end Ybuster_init */ /* ***************************************************************** */ Ybuster_free() { /* free allocate memory */ if(ptS){ YFREE( ptS ) ; YFREE( resultS ) ; ptS = NULL ; } } /* end Ybuster_free */ /* ***************************************************************** */ /*-------------------------------- run a sanity check on data. returns TRUE if data might be ok reutrns FALSE if data not ok --------------------------------*/ BOOL Ybuster_verify( user_string ) char *user_string ; { INT l; cur_stateS = S_STATE ; user_messageS = user_string ; /* verify corner count */ if (cornerCountS < 4) { sprintf(YmsgG," %s : There must be at least 4 corners\n", user_messageS ) ; M(ERRMSG,"Ybuster_verify",YmsgG); return(FALSE) ; } if ( cornerCountS & 1) { sprintf(YmsgG," %s : There must be an even # of corners\n", user_messageS ) ; M(ERRMSG,"Ybuster_verify",YmsgG); return(FALSE) ; } /* check all points for consistency */ for (l=1; l < cornerCountS;l++) { if( Ybuster_check_rect( ptS[l].x, ptS[l].y, ptS[l+1].x, ptS[l+1].y )){ return( FALSE ) ; } } /* check the last and the first point */ if( Ybuster_check_rect( ptS[l].x,ptS[l].y, ptS[1].x, ptS[1].y ) ){ return( FALSE ) ; } /* if we get to this point, everything is ok */ return(TRUE); } /* end Ybuster_verify */ /* ***************************************************************** */ /* ***************************************************************** */ /* detect problems with clockwise rotation pattern */ BOOL Ybuster_check_rect( xx1, yy1, xx2, yy2 ) INT xx1, yy1, xx2, yy2 ; { INT next_state ; /* the next direction of the edge */ static INT errorArrayL[6] = { /* E - U - L - R - D - S */ E_STATE, D_STATE, R_STATE, L_STATE, U_STATE, R_STATE } ; if( xx1 == xx2 && yy1 == yy2 ) { M(ERRMSG,"Ybuster_verify","a zero length side was found "); sprintf(YmsgG,"%s @(%d,%d)\n", user_messageS, xx1, yy1 ); M(ERRMSG,NULL,YmsgG); return( TRUE ) ; } else if( xx1 != xx2 && yy1 != yy2 ) { M(ERRMSG,"Ybuster_verify","a non rectilinear side was found"); sprintf(YmsgG," %s @(%d,%d)\n", user_messageS, xx1, yy1 ); M(ERRMSG,NULL,YmsgG); return( TRUE ) ; } else if( xx2 == xx1 ){ if( yy2 < yy1 ){ next_state = D_STATE ; } else { next_state = U_STATE ; } } else if( yy2 == yy1 ){ if( xx2 < xx1 ){ next_state = L_STATE ; } else { next_state = R_STATE ; } } /* check to see if this is an error by looking in error array */ /* the first state has two bad states explicitly enum. the second */ if( next_state == errorArrayL[cur_stateS] || (cur_stateS == S_STATE && next_state != U_STATE )){ sprintf( YmsgG, "%s is not specified in a CW direction\n", user_messageS ) ; M(ERRMSG,"Ybuster_check_rect", YmsgG ) ; return( TRUE ) ; } /* update state */ cur_stateS = next_state ; return( FALSE ) ; } /* end Ybuster_check_rect */ Ybuster_check_rect_init( user_string ) char *user_string ; { cur_stateS = S_STATE ; user_messageS = user_string ; } /* end Ybuster_check_init */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/cleanup.c000066400000000000000000000140141305746555600212450ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: cleanup.c DESCRIPTION:This file contains cleanup handler routines. To use cleanup handler included '' at the top of main.c . In addition, the first executable line of the program must be INITCLEANUP() macro. For everything to work the compiler directive MEMORYMAN must be defined. In order for the handler to work, the INITCLEANUP macro call (see cleanup.h) must occur in the top level routine, ie., main.c . The user may supply a parameterless function to be executed upon the completion of the handler; otherwise, pass a null pointer. CONTENTS: initCleanup( argv, function, dump ) char *argv ; INT (*function)() ; BOOL dump ; cleanup(sigNum, code, scp ) INT sigNum ; INT code ; struct sigcontext *scp ; void YcleanupHandler(status) int status ; DATE: Feb 2, 1988 REVISIONS: Sep 25, 1988 - converted to common utility. Jan 18, 1988 - added SIGKILL to list on user terminated conditions. Mar 20, 1989 - removed call to finderror. User should just call it from cshell. May 3, 1989 - added Yprefix. Apr 29, 1990 - fixed missing Yprefix on YcleanupHandler Fri Jan 18 18:38:36 PST 1991 - fixed to run on AIX. Fri Jan 25 16:16:50 PST 1991 - fixed to run on HPUX. Mon Sep 16 22:20:09 EDT 1991 - fixed to run on R6000. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) cleanup.c version 3.13 11/2/91" ; #endif #include /* conditional compile switch is set in cleanup.h */ #ifdef CLEANUP_C #include #include #ifdef R6000 #include #include #include #endif /* R6000 */ static INT dumpFlag ; static char programPath[LRECL] ; static BOOL (*userFunction)() ; /* ***************************************************************** initCleanup - sets static variables for cleanup handler. */ VOID YinitCleanup( argv, function, dump ) char *argv ; BOOL (*function)() ; int dump ; { sprintf( programPath, "%s", argv ) ; userFunction = function ; dumpFlag = dump ; } /* ***************************************************************** cleanup - the installed cleanup handler. */ #ifdef linux /* maybe others? */ void Ycleanup(int sigNum) #else Ycleanup(sigNum, code, scp ) int sigNum ; int code ; struct sigcontext *scp ; #endif /* linux */ { if( sigNum != SIGINT && sigNum != SIGQUIT && sigNum != SIGKILL ){ fprintf(stderr, "\nSystem has detected an error!\n") ; #ifdef apollo { INT pid ; char command[LRECL] ; pid = getpid() ; sprintf( command, "/com/tb %d", pid ) ; if(Ysystem("traceback", FALSE, command, NULL )){ fprintf(stderr,"ERROR[cleanup]:could not perform traceback.\n"); } } #endif #ifdef UNIX #ifndef SYS5 #ifndef mips #ifdef linux fprintf(stderr, "Stack pointer unknown\n"); #else fprintf(stderr,"Stack pointer :%0x\n", scp->sc_sp ) ; #endif #endif #ifndef AIX #ifdef linux fprintf(stderr, "Program counter unknown\n"); #else fprintf(stderr,"Program counter:%0x\n", scp->sc_pc ) ; #endif #else /* AIX */ #ifdef R6000 fprintf(stderr,"Instruction Address Register :%0x\n", scp->sc_jmpbuf.jmp_context.iar ) ; #else /* R6000 */ fprintf(stderr,"Stack pointer :%0x\n", scp->sc_psw ) ; #endif /* R6000 */ #endif /* AIX */ #endif /* SYS5 */ #endif /* UNIX */ } YcleanupHandler(sigNum) ; } /* ***************************************************************** YcleanupHandler - after system work process user information. */ YcleanupHandler(status) INT status ; { char responseBuf[LRECL], *response = responseBuf ; if( status == SIGINT || status == SIGQUIT || status == SIGKILL ){ fprintf(stderr,"\nProgram terminated by user\n\n") ; } else if( status == SIGUSR1 ){ Ypmemerror( "ERROR[memory manager]" ) ; } else { #ifndef SYS5 psignal( status, "ERROR[cleanup handler]" ) ; #endif } if( userFunction ){ (*userFunction)() ; } if( dumpFlag == MAYBEDUMP ){ fprintf(stderr,"Enter y for core dump. Default no dump\n") ; scanf( "%s", response ) ; if( *response == 'y' || *response == 'Y' ){ dumpFlag = YESDUMP ; } } if( dumpFlag == YESDUMP ){ fprintf(stderr,"Generating core dump for user traceback...\n") ; fprintf(stderr, "Use dbx to find where program core dumped...\n\n") ; fflush(stdout) ; signal(SIGILL,SIG_DFL); abort() ; exit(1) ; } else { exit(1) ; } } #endif /* CLEANUP_H */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/colors.c000066400000000000000000000111771305746555600211260ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: color.c DESCRIPTION:These routines give the standard colors for TimberWolf draw system. They can be overriden by creating a color matrix similar to below. CONTENTS: char **TWstdcolors() INT TWnumcolors() DATE: Jan 25, 1989 - major rewrite of version 1.0 REVISIONS: Jan 31, 1989 - added screen routines. Sep 25, 1990 - redid the stipple patterns for B&W. Oct 5, 1990 - rest of the gang wanted more colors. Fri Jan 18 18:38:36 PST 1991 - fixed to run on AIX. Fri Jan 25 15:41:25 PST 1991 - fixed to run on HPUX. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) colors.c version 3.8 2/26/92" ; #endif #include #define NUMCOLORS 18 static char *TWstdcolorArrayS[NUMCOLORS+1] = { "", /* through 0 element away */ "white", "black", "gray", "red", "blue", "yellow", "green", "magenta", "orange", "medium aquamarine", "cyan", "SpringGreen", "SteelBlue", "firebrick", "gold", "navy", "thistle", "khaki" } ; static char stipple_patS[30*8] = { '\210','\042','\210','\042','\210','\042','\210','\042', '\167','\335','\167','\335','\167','\335','\167','\335', '\356','\167','\273','\335','\356','\167','\273','\335', '\201','\102','\044','\030','\030','\044','\102','\201', '\003','\201','\300','\140','\060','\030','\014','\006', '\314','\210','\021','\063','\314','\210','\021','\063', '\252','\125','\252','\125','\252','\125','\252','\125', '\300','\201','\003','\006','\014','\030','\060','\140', '\034','\203','\160','\016','\301','\300','\007','\340', '\000','\000','\314','\314','\000','\000','\314','\314', '\000','\000','\000','\377','\000','\000','\000','\377', '\104','\104','\104','\104','\104','\104','\104','\104', '\125','\252','\125','\252','\125','\252','\125','\252', '\063','\063','\377','\377','\314','\314','\377','\377', '\104','\210','\042','\021','\104','\210','\042','\021', '\104','\356','\104','\000','\104','\356','\104','\000', '\300','\014','\300','\014','\300','\014','\300','\014', '\000','\000','\000','\000','\360','\360','\360','\360', '\210','\000','\000','\000','\210','\000','\000','\000', '\000','\021','\000','\104','\000','\021','\000','\104', '\000','\042','\210','\104','\000','\042','\210','\104', '\360','\360','\360','\360','\000','\000','\000','\000', '\100','\040','\020','\010','\004','\002','\001','\200', '\210','\063','\210','\146','\210','\063','\210','\146', '\314','\352','\314','\042','\314','\356','\314','\042', '\200','\000','\200','\000','\010','\000','\010','\000', '\002','\004','\010','\020','\040','\100','\200','\001', '\000','\012','\000','\000','\000','\240','\000','\000' } ; /* returns the standard color array */ char **TWstdcolors() { return( TWstdcolorArrayS ) ; } /* end TWstdcolors */ /* returns the number of colors in standard color array */ INT TWnumcolors() { return( NUMCOLORS ) ; } /* end TWnumcolors */ /* returns array of the standard stipple patterns */ char *TWstdStipple() { return( stipple_patS ) ; } /* end TWstdStipple */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/deck.c000066400000000000000000000246731305746555600205400ustar00rootroot00000000000000/* * Copyright (C) 1990-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: deck.c DESCRIPTION:This file contains the routines to handle decks CONTENTS: YDECK *Ydeck_init( ) Ydeck_push( deck, node ) YDECK *deck ; char *node ; Ydeck_enqueue( deck, node ) YDECK *deck ; char *node ; char *Ydeck_pop( deck ) char *Ydeck_dequeue( deck ) YDECKPTR Ydeck_notEmpty( deck ) YDECK *deck ; Ydeck_free ( deck , userfree ) YDECK *deck; userfree is memory deallocation routine Ydeck_empty ( deck , userfree ) YDECK *deck; userfree is memory deallocation routine Ydeck_dump( deck ) YDECK *deck ; DATE: Mar 16, 1990 Apr 30, 1990 - fixed something. Fri Feb 22 23:34:38 EST 1991 - fixed Ydeck_pop Ydeck_dequeue when queue is empty. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) deck.c (Yale) version 1.17 1/22/92" ; #endif #include static YCARD deckEndS; /*-----------------*/ /* initialize deck */ /*-----------------*/ YDECK *Ydeck_init( ) { YDECKPTR deckPtr ; deckPtr = (YDECKPTR) YMALLOC( 1, YDECK ); deckPtr->top= &deckEndS; /* init to point to sentinal */ deckPtr->bottom= &deckEndS; /* init to point to sentinal */ deckPtr->current= &deckEndS; /* init to point to sentinal */ deckPtr->size=0; return(deckPtr); } /* end Ydeck_init */ /*-------------------------------------*/ /* add a vertex to the top of the deck */ /*-------------------------------------*/ VOID Ydeck_push( deckPtr, data ) YDECK *deckPtr ; VOIDPTR data ; { YCARDPTR cardPtr; cardPtr= YMALLOC( 1, YCARD ); /* allocate a new card */ cardPtr->data=data; /* attach users data to new card */ if (deckPtr->size) { /* deck is not empty */ cardPtr->down=deckPtr->top; cardPtr->up= &deckEndS; deckPtr->top->up=cardPtr; deckPtr->top=cardPtr; } else { /* deck was empty */ deckPtr->top=cardPtr; /* the new card is the top and bottom */ deckPtr->bottom=cardPtr; cardPtr->up= &deckEndS; cardPtr->down= &deckEndS; } deckPtr->size++; } /* end Ydeck_push */ /*----------------------------------------*/ /* add a vertex to the bottom of the deck */ /*----------------------------------------*/ VOID Ydeck_enqueue( deckPtr, data ) YDECK *deckPtr ; VOIDPTR data ; { YCARDPTR cardPtr; cardPtr= YMALLOC( 1, YCARD ); /* allocate a new card */ cardPtr->data=data; /* attach users data to new card */ if (deckPtr->size) { /* deck is not empty */ cardPtr->up=deckPtr->bottom; cardPtr->down= &deckEndS; deckPtr->bottom->down=cardPtr; deckPtr->bottom=cardPtr; } else { /* deck was empty */ deckPtr->top=cardPtr; /* the new card is the top and bottom */ deckPtr->bottom=cardPtr; cardPtr->up= &deckEndS; cardPtr->down= &deckEndS; } deckPtr->size++; } /* end Yadd2Deck */ /*------------------------------*/ /* remove card from top of deck */ /*------------------------------*/ VOIDPTR Ydeck_pop(deckPtr) YDECK *deckPtr; { YCARDPTR cardPtr; VOIDPTR data; if( deckPtr->size <= 0 ){ return( NIL(VOIDPTR) ) ; } cardPtr=deckPtr->top; data=cardPtr->data; deckPtr->top=cardPtr->down; cardPtr->down->up= &deckEndS; if ( (deckPtr->current = deckPtr->top) == &deckEndS) { deckPtr->bottom= &deckEndS; } YFREE(cardPtr); deckPtr->size--; return(data); } /* end Ydeck_pop */ /*---------------------------------*/ /* remove card from bottom of deck */ /*---------------------------------*/ VOIDPTR Ydeck_dequeue(deckPtr) YDECK *deckPtr; { YCARDPTR cardPtr; VOIDPTR data; if( deckPtr->size <= 0 ){ return( NIL(VOIDPTR) ) ; } cardPtr=deckPtr->bottom; data=cardPtr->data; deckPtr->bottom=cardPtr->up; cardPtr->up->down= &deckEndS; if ( (deckPtr->current = deckPtr->bottom) == &deckEndS) { deckPtr->top= &deckEndS; } YFREE(cardPtr); deckPtr->size--; return(data); } /* end Ydeck_dequeue */ /*--------------------------*/ /* check status of the deck */ /*--------------------------*/ INT Ydeck_notEmpty( deckPtr ) YDECK *deckPtr ; { return( deckPtr->size ) ; } /*--------------------------------*/ /* remove all cards from the deck */ /*--------------------------------*/ VOID Ydeck_empty(deckPtr,userDelete) VOID (*userDelete)(); YDECK *deckPtr; { VOIDPTR deckData; if (userDelete) { for (Ydeck_top(deckPtr);Ydeck_notEnd(deckPtr);) { deckData=Ydeck_pop(deckPtr); userDelete(deckData); } } else { for (Ydeck_top(deckPtr);Ydeck_notEnd(deckPtr);) { Ydeck_pop(deckPtr); } } } /*-----------------------------------------*/ /* free the deck and all cards it contains */ /*-----------------------------------------*/ VOID Ydeck_free(deckPtr,userDelete) YDECK *deckPtr; VOID (*userDelete)(); { Ydeck_empty(deckPtr,userDelete); YFREE(deckPtr); } /*-------------------------------------------------*/ /* debug function to dump the contents of the deck */ /*-------------------------------------------------*/ VOID Ydeck_dump( deckPtr, userPrint ) YDECK *deckPtr ; VOID (*userPrint)(); { fprintf( stderr,"%d cards\n",deckPtr->size); fprintf( stderr,"Deck top to bottom:" ) ; for ( Ydeck_top(deckPtr); Ydeck_notEnd(deckPtr); Ydeck_down(deckPtr) ) { if (userPrint) { (*userPrint)(Ydeck_getData(deckPtr)); } else { fprintf( stderr,"%d ", (INT)Ydeck_getData(deckPtr) ) ; } } fprintf( stderr,"\n" ) ; fprintf( stderr,"Deck bottom to top:" ) ; for ( Ydeck_bottom(deckPtr); Ydeck_notEnd(deckPtr); Ydeck_up(deckPtr)) { if (userPrint) { (*userPrint)(Ydeck_getData(deckPtr)); } else { fprintf( stderr,"%d ", (INT) Ydeck_getData(deckPtr) ) ; } } fprintf( stderr,"\n" ) ; } /* end Ydeck_dump */ /*-----------------------------------------------------------------------------*/ /* returns address of sentinel. This makes sentinal address available to users */ /*-----------------------------------------------------------------------------*/ YCARD *Ydeck_sentinel() { return(&deckEndS); } /*----------------------- exercise deck pointer ------------------------*/ int Ydeck_verify(deck) YDECK *deck; { static char routineNameS[LRECL] = "Ydeck_verify"; YCARDPTR saveCurrent; INT count1 = 0; INT count2 = 0; int rc = TRUE; /* save the decks current position */ saveCurrent = deck->current; /* verify memory allocation of deck */ if ( YcheckDebug(deck) < sizeof(YDECK) ) { M( ERRMSG, routineNameS, "deck memory is corrupt\n"); rc = FALSE; } /* walk deck top to bottom. verify memory allocation and count cards */ for ( Ydeck_top(deck); Ydeck_notEnd(deck); Ydeck_down(deck) ) { count1 ++; if ( YcheckDebug(deck->current) < sizeof(YCARD) ) { M( ERRMSG, routineNameS, "deck has card with corrupt memory\n"); rc = FALSE; } /* check pointer above current card */ if ( deck->current->up != &deckEndS ) { if ( YcheckDebug(deck->current->up) < sizeof(YCARD) ) { M( ERRMSG, routineNameS, "card up is currupt\n"); rc = FALSE; } } /* check pointer above below card */ if ( deck->current->down != &deckEndS ) { if ( YcheckDebug(deck->current->down) < sizeof(YCARD) ) { M( ERRMSG, routineNameS, "card down is currupt\n"); rc = FALSE; } } } /* walk deck bottom to top. verify memory allocation and count cards */ for ( Ydeck_bottom(deck); Ydeck_notEnd(deck); Ydeck_up(deck) ) { count2 ++; if ( YcheckDebug(deck->current) < sizeof(YCARD) ) { M( ERRMSG, routineNameS, "deck has card with corrupt memory\n"); rc = FALSE; } /* check pointer above current card */ if ( deck->current->up != &deckEndS ) { if ( YcheckDebug(deck->current->up) < sizeof(YCARD) ) { M( ERRMSG, routineNameS, "card up is currupt\n"); rc = FALSE; } } /* check pointer above below card */ if ( deck->current->down != &deckEndS ) { if ( YcheckDebug(deck->current->down) < sizeof(YCARD) ) { M( ERRMSG, routineNameS, "card down is currupt\n"); rc = FALSE; } } } /* check card counts */ if ( count1 != count2 || count1 != Ydeck_size(deck) ) { M( ERRMSG, routineNameS, "deck size is inconsistent with card count\n"); rc = FALSE; } /* make sure top and bottom cards point to correct sentinel */ if ( deck->size >= 1 ) { /* a top card exists, card above should be sentinel */ if ( deck->top->up != &deckEndS ) { M( ERRMSG, routineNameS, "card above top card is not sentinel\n"); rc = FALSE; } /* a bottom card exists, card above should be sentinel */ if ( deck->bottom->down != &deckEndS ) { M( ERRMSG, routineNameS, "card below bottom card is not sentinel\n"); rc = FALSE; } } /* restore the decks current position */ deck->current = saveCurrent; return(rc); } graywolf-0.1.4+20170307gite1bf319/src/Ylib/dialog.c000066400000000000000000000742641305746555600210720ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: dialog.c DESCRIPTION:creates a dialog box for TimberWolf pgms. It returns information for the user. CONTENTS: TWDRETURNPTR TWdialog( fieldp ) TWDIALOGPTR fieldp ; TWDRETURNPTR TWread_dialog( filename ) char *filename ; DATE: Aug 16, 1989 - original coding. REVISIONS: Sep 16, 1989 - all debug directed to stderr. Sep 23, 1989 - rewrote data structures to handle cases Oct 2, 1989 - now user can set position of dialog box. Also fixed bug with font size. Feb 20, 1990 - tell the user data has changed. Sep 25, 1990 - added B&W mode. Dec 5, 1990 - now handle stipple correctly and added user_function to the dialog procedure. Dec 27, 1990 - eliminated multiple redraws upon startup. Mon Jan 7 18:17:44 CST 1991 - made SAFE_WAIT_TIME user programmable for slow machines. Fri Jan 18 18:36:44 PST 1991 - added event debug. Fri Jan 25 16:17:21 PST 1991 - now look for backspace or delete key when in window. Fri Feb 22 23:36:13 EST 1991 - wait for screen to appear. Thu Mar 7 01:24:55 EST 1991 - added focus requests for SUN openwindows. Also added draw screen refresh. Sun Nov 3 12:50:53 EST 1991 - fixed gcc complaints. Thu Jan 30 02:55:16 EST 1992 - added window manager hints and now allow different font for dialog box. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) dialog.c version 3.15 3/6/92" ; #endif #ifndef NOGRAPHICS #include #include #include #include #include #include /* #define TURNOFFPRINTD */ #include #include #include #include #include #include #include #include #include #include "info.h" #define WHITE 1 /* white parent gc is one in array */ #define BLACK 2 /* black parent gc is two in array */ #define CANCEL 0 /* code for cancel menu activity */ #define DELETE_CH '\177' /* delete character */ #define BACKSPACE '\010' /* backspace character */ #define RETURN '\015' /* return charachter */ #define COMMENT '#' /* comment character in first col */ #define RATIO 0.70 #define ACCEPTWIN 0 #define REJECTWIN 1 /* definitions for parsing dialog file */ #define FIELD 0 #define FIELDNUM 1 #define COLUMN 2 #define ROW 3 #define STRING 4 #define LEN 5 #define TYPE 6 #define COLOR 7 #define CASEGROUP 8 /* definitions for the fonts */ #define NEW_FONT TRUE #define REVERT_FONT 2 static TWINFOPTR infoS ; /* information about main details */ static Display *dpyS; /* the display */ static Window menuS; /* the current menu window */ static Window wS; /* the main TW display window */ static Window dialogS; /* the dialog display window */ static GC *contextArrayS ; /* array of context window */ static GC reverseGCS ; /* reverse gc for dialog */ static INT screenS ; /* the current screen */ static UNSIGNED_INT backgrdS ; static UNSIGNED_INT foregrdS ; static INT winwidthS ; /* window width */ static Window *winS ; /* contains info about menus */ static XFontStruct *fontinfoS ; /* font information */ static Font fontS ; /* current font */ static int xdS ; /* origin of dialog window */ static int ydS ; /* origin of dialog window */ static INT fwidthS ; /* font width in pixels */ static INT fheightS ; /* font height in pixels */ static INT numwinS ; /* number of window in dialog box */ static TWDRETURNPTR dataS ; /* return data array */ static TWDIALOGPTR fieldS ; /* the current dialog array */ /* function definitions */ static INT world2pix_x() ; static INT world2pix_y() ; static INT world2fonty() ; static INT pixlen() ; static set_stipple_font( P2(BOOL stippleOn, INT font_change ) ) ; static debug_dialog( P1( TWDIALOGPTR fieldp ) ) ; static check_cases( P3( TWDIALOGPTR fieldp, INT select, INT (*user_function)() )) ; static draw_fields( P1(TWDIALOGPTR fieldp) ) ; static TWfreeWindows() ; static find_font_boundary() ; static edit_field( P4( INT field, Window win, XEvent event, INT (*user_function)() ) ) ; /* build a dialog box and get info */ TWDRETURNPTR TWdialog( fieldp, dialogname, user_function ) TWDIALOGPTR fieldp ; char *dialogname ; INT (*user_function)() ; { UNSIGNED_INT white, black ; INT i ; /* counter */ long event_mask ; /* set up event catching with this mask */ INT screenwidth ; /* width of root window */ unsigned int widthd ; /* adjusted width of dialog screen */ INT screenheight ; /* height of root window */ unsigned int heightd ;/* adjusted height of dialog screen */ INT win_num ; /* window counter */ INT time ; /* current time */ TWDIALOGPTR fptr ; /* current dialog field */ TWDRETURNPTR dptr ; /* current return field */ BOOL press ; /* tells whether button has been pushed */ BOOL bw ; /* tells whether display is color or not */ BOOL foundWindow ; /* used in window search to find match */ static INT lasttimeL; /* last time of exposure event */ XEvent event ; /* describes button event */ Window win ; /* temporary for selected window */ Cursor cursor ; /* cursor for typing */ char *winstr ; /* used for get user window default */ INT m ; /* mask for determining window position */ char resource[LRECL] ;/* look for match in database */ XSizeHints hints ; /* setup hints for window manager */ char *font ; /* user font request */ BOOL font_loaded ; /* whether dialog box has its own font */ /* get static information from main draw module */ /* try to do crude object oriented programming */ infoS = TWgetDrawInfo() ; /* save display info for future use */ dpyS = infoS->dpy ; screenS = infoS->screen ; wS = infoS->rootWindow ; black = BlackPixel(dpyS,screenS); white = WhitePixel(dpyS,screenS); backgrdS = black ; foregrdS = white ; /* check whether machine is color or not */ if( (bw = XDisplayCells( dpyS, screenS )) > 2 ){ /* if color number of display cells > 0 */ bw = FALSE ; } else { bw = TRUE ; } /* calculate where to put master window */ /* we want to center the window and take 70% of */ /* the available screen */ screenwidth = XDisplayWidth(dpyS,screenS); screenheight = XDisplayHeight(dpyS,screenS); sprintf( resource, "geometry_%s", dialogname ) ; D( "dialog", fprintf( stderr, "resource:%s\n", resource ) ) ; if( winstr = XGetDefault( dpyS, GRAPHICS, resource )){ m = XParseGeometry( winstr,&xdS,&ydS,&widthd,&heightd) ; if( m & XNegative ){ xdS += screenwidth ; } if( m & YNegative ){ ydS += screenheight ; } /* these two lines insure that uses doesn't have to press */ /* button using twm window manager */ if( xdS == 0 ) xdS++ ; if( ydS == 0 ) ydS++ ; hints.flags = USPosition | USSize ; } else { widthd = (INT) (RATIO * (DOUBLE) screenwidth ) ; heightd = (INT) (RATIO * (DOUBLE) screenheight ) ; xdS = (screenwidth - widthd ) / 2 ; ydS = (screenheight - heightd ) / 2 ; hints.flags = PPosition | PSize ; } sprintf( resource, "font_%s", dialogname ) ; D( "dialog", fprintf( stderr, "font resource:%s\n", resource ) ) ; /* set font and get font info */ font_loaded = FALSE ; if(font = XGetDefault( dpyS, GRAPHICS, resource )){ if( strcmp( font, infoS->fontname ) != STRINGEQ ){ fontinfoS = TWgetfont( font, &fontS ) ; font_loaded = TRUE ; } } else { fontinfoS = infoS->fontinfo ; fontS = fontinfoS->fid ; } /* normal case - need to create menu window */ dialogS = XCreateSimpleWindow( dpyS, wS, xdS, ydS, widthd, heightd, 1L, backgrdS, foregrdS ) ; event_mask = ExposureMask | VisibilityChangeMask ; XSelectInput(dpyS,dialogS,event_mask); cursor = XCreateFontCursor( dpyS, XC_hand2 ) ; XDefineCursor( dpyS, dialogS, cursor ) ; /* set the window manager hints */ hints.x = xdS ; hints.y = ydS ; hints.width = widthd ; hints.height = heightd ; XSetStandardProperties(dpyS,dialogS,dialogname,dialogname,None,NULL,0,&hints); /* set graphic contexts */ contextArrayS = infoS->graphicContext ; reverseGCS = contextArrayS[WHITE] ; set_stipple_font( FALSE, font_loaded ) ; /* count number of windows required */ fieldS = fieldp ; numwinS = 0 ; for( i=0 ; fieldp[i].row ; i++ ){ numwinS++ ; } /* allocate an array of windows */ winS = YCALLOC( numwinS+1, Window ) ; dataS = YCALLOC( numwinS+1,TWDRETURNBOX ) ; /* find pixel bounding box */ /* we assume fixed fonts but variable fonts will be ok */ find_font_boundary() ; for( i=0 ; i < numwinS ; i++ ){ fptr = &(fieldp[i]) ; dptr = &(dataS[i]) ; if( fptr->string ){ dptr->string = Ystrclone( fptr->string ) ; } else { dptr->string = NULL ; } if( bw ){ /* on a black and white machine set color to backgrd color */ fptr->color = BLACK ; } if( fptr->type == INPUTTYPE || fptr->type == BUTTONTYPE ){ winS[i] = XCreateSimpleWindow( dpyS, dialogS, world2pix_x( fptr->column ), world2pix_y( fptr->row - 1 ), pixlen( fptr->len ), fheightS, 1L, backgrdS, foregrdS ) ; XDefineCursor( dpyS, winS[i], cursor ) ; } else if( fptr->type == CASETYPE ){ /* initial on button of a case switch */ ASSERTNCONT( fptr->group > 0 && fptr->group < numwinS, "TWdialog", "init_switch out of bounds\n" ) ; dataS[fptr->group].bool = TRUE ; } } /* now raise all the subwindows */ /* and initialize input selection*/ for( i=0; i< numwinS; i++ ){ if(!(winS[i])){ /* skip over label fields which don't have windows */ continue ; } /* now set all window masks */ fptr = &(fieldp[i]) ; if( fptr->type == BUTTONTYPE ){ event_mask = ButtonPressMask | EnterWindowMask | LeaveWindowMask ; } else if( fptr->type == INPUTTYPE ){ event_mask = KeyPressMask | EnterWindowMask | LeaveWindowMask ; } else { /* use just exposure mask here */ event_mask = ExposureMask ; } XSelectInput(dpyS,winS[i],event_mask); XMapRaised( dpyS, winS[i] ) ; } /* now raise menu window so we can see it */ XMapWindow( dpyS, dialogS ) ; /* wait for all the windows to be raised */ XSync( dpyS, FALSE ) ; /* ------------------------------------------------------------- Now wait to window to become visible. This code is necessary since some window managers (uwm) map the window as a ghost image and wait for user to resize window. Other window managers (twm) map window as requested. Need to accomodate both. -------------------------------------------------------------- */ while( TRUE ){ if( XCheckTypedWindowEvent(dpyS,dialogS,VisibilityNotify,&event)){ if( event.xvisibility.state == VisibilityUnobscured || event.xvisibility.state == VisibilityPartiallyObscured ){ break ; } } } event_mask = ExposureMask ; XSelectInput(dpyS,dialogS,event_mask); XClearWindow( dpyS, dialogS ) ; draw_fields( fieldp ) ; /* update time for slow machines */ (void) YcurTime( &lasttimeL ) ; /* now look for button press to end */ event_mask = ButtonPressMask | KeyPressMask | EnterWindowMask | LeaveWindowMask | ExposureMask ; while( TRUE ){ if( XCheckMaskEvent( dpyS, event_mask, &event ) ){ D( "TWdialog/event", fprintf( stderr, "Event:%d window:%d\n", event.type, event.xany.window ) ; ) ; switch( event.type ){ case ButtonPress: /* how we exit */ win = event.xbutton.window ; if( win == winS[ACCEPTWIN] ){ TWfreeWindows() ; set_stipple_font( TRUE, REVERT_FONT ) ; return( dataS ) ; } else if( win == winS[REJECTWIN] ){ TWfreeWindows() ; set_stipple_font( TRUE, REVERT_FONT ) ; return( NULL ) ; } else { /* BUTTON TYPE which is a case switch */ foundWindow = FALSE ; for( i = 0; i < numwinS; i++ ){ if( win == winS[i] ){ foundWindow = TRUE ; break ; } } /* end search for window */ if( foundWindow ){ check_cases( fieldp, i, user_function ) ; } } break ; case EnterNotify: /* light up window */ /* find window match */ win = event.xcrossing.window ; foundWindow = FALSE ; for( i = 0; i < numwinS; i++ ){ if( win == winS[i] ){ foundWindow = TRUE ; break ; } } /* end search for window */ if( foundWindow ){ /* a match light up window */ fptr = &(fieldp[i]) ; dptr = &(dataS[i]) ; XFillRectangle( dpyS,win, contextArrayS[fptr->color], 0,0, pixlen( fptr->len ), fheightS ) ; if( dptr->string ){ XDrawString( dpyS, win, reverseGCS, 0L, world2fonty( 0L ), dptr->string, strlen(dptr->string)) ; } XSetInputFocus( dpyS, win, RevertToPointerRoot, CurrentTime ) ; } break ; case LeaveNotify: /* turn off window */ /* find window match */ win = event.xcrossing.window ; foundWindow = FALSE ; for( i = 0; i < numwinS; i++ ){ if( win == winS[i] ){ foundWindow = TRUE ; break ; } } /* end search for window */ if( foundWindow ){ /* turn off window */ dptr = &(dataS[i]) ; XClearWindow( dpyS, win ) ; if( dptr->string ){ if( fieldp[i].type != BUTTONTYPE ){ /* normal case */ XDrawString( dpyS, winS[i], contextArrayS[fptr->color], 0L, world2fonty( 0L ), dptr->string, strlen(dptr->string)) ; } else if( dptr->bool ){ /* a case switch that is on */ XFillRectangle( dpyS,win, contextArrayS[fptr->color], 0,0, pixlen( fptr->len ), fheightS ) ; XDrawString( dpyS, win, reverseGCS, 0L, world2fonty( 0L ), dptr->string, strlen(dptr->string)) ; } else { /* a case switch that is off */ XDrawString( dpyS, winS[i], contextArrayS[fptr->color], 0L, world2fonty( 0L ), dptr->string, strlen(dptr->string)) ; } } XSetInputFocus( dpyS, PointerRoot, RevertToParent, CurrentTime ); } break ; case KeyPress: win = event.xkey.window ; foundWindow = FALSE ; for( i = 0; i < numwinS; i++ ){ if( win == winS[i] ){ foundWindow = TRUE ; break ; } } /* end search for window */ if( foundWindow ){ /* turn off window */ edit_field( i, win, event, user_function ) ; } break ; case Expose: win = event.xexpose.window ; if( win == infoS->drawWindow ){ (*infoS->refresh_func)() ; } else { /* window managers sometimes send us too many */ /* exposure events therefore check time and */ /* make multiple exposures invalid */ if( event.xexpose.count == 0 ){ (void) YcurTime( &time ) ; if( time - lasttimeL < TWsafe_wait_timeG ){ D( "TWdialog/exposure", fprintf( stderr, "Dialog Exposure:0 @time = %d\n", time); ) ; break ; } D( "TWdialog/exposure", fprintf( stderr, "Dialog Exposure:1 @time = %d\n", time); ) ; draw_fields( fieldp ) ; /* update time for slow machines */ (void) YcurTime( &time ) ; lasttimeL = time ; } } break ; } /* end event switch */ } /* end check on event */ } /* end wait loop */ } /* end TWdialog */ static set_stipple_font( stippleOn, font_change ) BOOL stippleOn ; INT font_change ; { INT i ; /* counter */ if( infoS->stipple ){ if( stippleOn ){ for( i = 3; i <= infoS->numColors; i++ ){ XSetFillStyle( dpyS, contextArrayS[i], FillTiled ) ; } } else { for( i = 3; i <= infoS->numColors; i++ ){ XSetFillStyle( dpyS, contextArrayS[i], FillSolid ) ; } } } if( font_change ){ if( font_change == NEW_FONT ){ for( i=0; i <= infoS->numColors; i++ ){ XSetFont( dpyS, contextArrayS[i], fontS ) ; } } else if( font_change = REVERT_FONT ){ for( i=0; i <= infoS->numColors; i++ ){ XSetFont( dpyS, contextArrayS[i], infoS->fontinfo->fid ) ; } } } } /* end set_stipple_font */ /* check the case fields and set all member of group to false */ static check_cases( fieldp, select, user_function ) TWDIALOGPTR fieldp ; INT select ; INT (*user_function)() ; { INT i ; /* counter */ INT group ; /* case group */ TWDIALOGPTR fptr ; /* current dialog field */ TWDRETURNPTR dptr ; /* current return field */ group = fieldp[select].group ; for( i=0 ; i < numwinS ; i++ ){ fptr = &(fieldp[i]) ; dptr = &(dataS[i]) ; if( fptr->group == group ){ if( i == select ){ dptr->bool = TRUE ; } else { dptr->bool = FALSE ; } } } if( user_function ){ (*user_function)( dataS, select ) ; } /* redraw fields so user can see change */ draw_fields( fieldp ) ; XFlush( dpyS ) ; } /* end check_cases */ static draw_fields( fieldp ) TWDIALOGPTR fieldp ; { INT i ; /* counter */ TWDIALOGPTR fptr ; /* current dialog field */ TWDRETURNPTR dptr ; /* current return field */ /* now draw all the strings to dialog window */ XClearWindow( dpyS, dialogS ) ; for( i=0 ; i < numwinS ; i++ ){ fptr = &(fieldp[i]) ; dptr = &(dataS[i]) ; if(!(dptr->string)){ /* avoid null strings */ continue ; } if( fptr->type == LABELTYPE || fptr->type == CASETYPE ){ XDrawString( dpyS, dialogS, contextArrayS[fptr->color], world2pix_x( fptr->column ), world2fonty( fptr->row - 1 ), dptr->string, strlen(dptr->string)) ; } else if( fptr->type == INPUTTYPE ){ /* input case */ XClearWindow( dpyS, winS[i] ) ; XDrawString( dpyS, winS[i], contextArrayS[fptr->color], 0L, world2fonty( 0L ), dptr->string, strlen(dptr->string)) ; } else if( fptr->type == BUTTONTYPE ){ XClearWindow( dpyS, winS[i] ) ; if( dptr->bool ){ /* true initially */ XFillRectangle( dpyS,winS[i], contextArrayS[fptr->color], 0,0, pixlen( fptr->len ), fheightS ) ; XDrawString( dpyS, winS[i], reverseGCS, 0L, world2fonty( 0L ), dptr->string, strlen(dptr->string)) ; } else { /* off */ XDrawString( dpyS, winS[i], contextArrayS[fptr->color], 0L, world2fonty( 0L ), dptr->string, strlen(dptr->string)) ; } } } } /* end draw_fields */ static TWfreeWindows() { INT i, j ; /* counters */ for( i = 0; winS[i] ; i++ ){ /* we must free window this way */ XDestroyWindow( dpyS, winS[i] ) ; } YFREE( winS ) ; XDestroyWindow( dpyS, dialogS ) ; } /* end TWfreeWindows */ static find_font_boundary() { fwidthS = fontinfoS->max_bounds.rbearing - fontinfoS->min_bounds.lbearing ; fheightS = fontinfoS->ascent + fontinfoS->descent ; } /* end find_font_boundary */ /* tranforms the world coordinate character column format */ /* to pixel coordinates */ static INT world2pix_x( x ) { return( x * fwidthS ) ; } /* end world2pix_x */ static INT world2pix_y( y ) { return( y * fheightS ) ; } /* end world2pix_y */ static INT world2fonty( y ) { return( (++y) * fheightS - fontinfoS->max_bounds.descent ) ; } /* end world2pix_y */ /* change length of string to pixel length */ static INT pixlen( length ) INT length ; { return( fwidthS * length ) ; } /* end pixlen */ static edit_field( field, win, event, user_function ) INT field ; Window win ; XEvent event ; /* describes the button event */ INT (*user_function)() ; { TWDIALOGPTR fptr; /* current field of dialog */ TWDRETURNPTR dptr; /* return field of dialog */ BOOL press ; /* tells whether keyboard has been pushed */ BOOL finish ; /* tells whether we have received a return */ long event_mask ; /* setup menus */ char buffer[LRECL] ; /* used for keyboard translation */ char curMsg[LRECL] ; /* current value of message window */ char data[LRECL]; /* current value of users input */ KeySym keysym ; /* return of keysym from user */ XComposeStatus status ; /* where a compose key was pressed */ INT strwidth ; /* width of string in pixels */ INT dataCount ; /* number of characters in user input */ fptr = &( fieldS[field] ) ; dptr = &( dataS[field] ) ; if( dptr->string ){ /* initialize string buffers */ dataCount = strlen( dptr->string ) ; strcpy( data, dptr->string ) ; /* now move pointer to end of current data */ strwidth = XTextWidth( fontinfoS, dptr->string, dataCount) ; /* now warp pointer to message window */ XWarpPointer( dpyS, None, win, 0, 0, 0, 0, strwidth + fwidthS/3, fheightS/2 ) ; } else { /* initialize string buffers */ data[0] = EOS ; dataCount = 0 ; } /* now look for keyboard action */ finish = FALSE ; press = TRUE ; /* initially we got a keyboard event */ /* tell user data has changed */ dptr->bool = TRUE ; do { if( press ){ /* initialize buffer */ buffer[0] = EOS ; /* find what the user entered */ XLookupString( &(event.xkey), buffer,LRECL,&keysym, &status ); buffer[1] = EOS ; /* only get one character at a time */ D( "Yedit_field",fprintf( stderr, "char:%c\n", buffer[0] ) ) ; /* look to see if we got a return */ if( buffer[0] == RETURN ){ finish = TRUE ; if( dptr->string ){ YFREE( dptr->string ) ; } /* return answer in dptr field */ dptr->string = Ystrclone( data ) ; } else { /* look for more data */ /* but first copy the data we have */ if( buffer[0] == BACKSPACE || buffer[0] == DELETE_CH ){ /* look for backspace or delete */ if( dataCount > 0 ){ dataCount-- ; } data[dataCount] = EOS ; } else { /* save data */ strcat( data, buffer ) ; dataCount += strlen( buffer ) ; } /* now echo to screen */ XFillRectangle( dpyS,win, contextArrayS[fptr->color], 0,0, pixlen( fptr->len ), fheightS ) ; XDrawString( dpyS, win, reverseGCS, 0L, world2fonty( 0L ), data, dataCount) ; D( "Yedit_field",fprintf( stderr, "data:%s\n", data ) ) ; D( "Yedit_field",fprintf( stderr,"datacount:%d\n", dataCount ) ) ; /* now move pointer to end of current data */ strwidth = XTextWidth( fontinfoS, data,dataCount) ; /* now warp pointer to message window */ XWarpPointer( dpyS, None, win, 0, 0, 0, 0, strwidth + fwidthS/3, fheightS/2 ) ; } } /* get next keyboard stroke */ press = XCheckTypedWindowEvent( dpyS,win,KeyPress,&event ); } while(!finish) ; /* end wait loop */ if( user_function ){ (*user_function)( dataS, field ) ; /* redraw fields so user can see change */ draw_fields( fieldS ) ; } } /* end edit_field */ #ifdef DEBUG TWDIALOGPTR TWread_dialog( filename ) char *filename ; { #define KEYWORD "numfields" #define FIELDKEYWORD "field" FILE *fp ; char buffer[LRECL], *bufferptr ; char group[LRECL] ; /* for parsing case groups */ char **tokens ; /* for parsing menu file */ char **colors ; /* the standard color array */ INT numtokens ; /* number of tokens on line */ INT group_num ; /* number of case fields given */ INT i ; /* counter */ INT line ; /* line number of TWmenu file */ INT length ; /* length of string */ INT numfields ; /* number of dialog fields */ INT curfield ; /* current dialog field */ INT case_label ; /* current case field */ INT numcolors ; /* the number of colors in color array */ BOOL found ; /* whether color was found */ TWDIALOGPTR fields; /* dialog array information */ TWDIALOGPTR fptr; /* current field of dialog */ /* get colors for dialog window */ infoS = TWgetDrawInfo() ; colors = infoS->colors ; numcolors = infoS->numColors ; /* parse dialog file */ line = 0 ; curfield = -1 ; group_num = 0 ; fields = NULL ; fp = TWOPEN( filename, "r", ABORT ) ; while( bufferptr=fgets(buffer,LRECL,fp )){ /* parse file */ line++ ; /* increment line number */ /* skip comments */ if( *bufferptr == COMMENT ){ continue ; } tokens = Ystrparser( bufferptr, ";\t\n", &numtokens ); if( numtokens == 0 ){ /* skip over empty lines */ continue ; } else if( strcmp( tokens[0], KEYWORD ) == STRINGEQ){ /* look at first field for menu keyword */ /* there better be only two tokens on this line */ if( numtokens != 2 ){ sprintf( YmsgG, "Syntax error on line:%d\n", line ) ; M(ERRMSG, "TWread_dialog", YmsgG ) ; break ; } numfields = atoi( tokens[1] ) ; ASSERTNBREAK( numfields > 0,"TWread_dialog","numfields must be >0\n" ) ; fields = YCALLOC( numfields+1, TWDIALOGBOX ) ; } else if( strcmp( tokens[FIELD], FIELDKEYWORD ) == STRINGEQ){ if( ++curfield >= numfields ){ M( ERRMSG,"TWread_dialog","number of fields mismatch\n" ) ; return( NULL ) ; } fptr = &(fields[curfield]) ; if( numtokens != 8 && numtokens != 9 ){ sprintf( YmsgG, "Problem parsing line:%d in dialog file\n", line ) ; M( ERRMSG,"TWread_dialog", YmsgG ) ; continue ; } fptr->column = atoi( tokens[COLUMN] ) ; fptr->row = atoi( tokens[ROW] ) ; fptr->len = atoi( tokens[LEN] ) ; /* check color to make sure it is valid */ found = FALSE ; for( i=1; i <= numcolors; i++ ){ if( strcmp( tokens[COLOR], colors[i] ) == STRINGEQ ){ fptr->color = i ; found = TRUE ; break ; } } if(!(found)){ sprintf( YmsgG, "Color:%s has not been allocated\n", tokens[COLOR] ) ; M( ERRMSG, "TWread_dialog", YmsgG ) ; return( NULL ) ; } if( strcmp( tokens[STRING], "NULL") == STRINGEQ ){ fptr->string = NULL ; } else { fptr->string = Ystrclone( tokens[STRING] ) ; } /* look at types */ if( strcmp( tokens[TYPE], "input") == STRINGEQ ){ fptr->type = INPUTTYPE ; } else if( strcmp( tokens[TYPE], "label") == STRINGEQ ){ fptr->type = LABELTYPE ; } else if( strcmp( tokens[TYPE], "accept") == STRINGEQ ){ fptr->type = BUTTONTYPE ; if( curfield != 0 ){ M( ERRMSG, "TWread_dialog", "accept must be 1st field\n" ) ; return( NULL ) ; } } else if( strcmp( tokens[TYPE], "reject") == STRINGEQ ){ fptr->type = BUTTONTYPE ; if( curfield != 1 ){ M( ERRMSG, "TWread_dialog", "reject must be 2nd field\n" ) ; return( NULL ) ; } } else if( strcmp( tokens[TYPE], "clabel") == STRINGEQ ){ fptr->type = BUTTONTYPE ; } else if( strcmp( tokens[TYPE], "case") == STRINGEQ ){ fptr->type = CASETYPE ; group_num++ ; if( numtokens == 9 ){ strcpy( group, tokens[CASEGROUP] ) ; tokens = Ystrparser( group, ",\t\n", &numtokens ); ASSERTNRETURN( numtokens>0,"TWread_dialog", "no cases found\n" ) ; for( i = numtokens-1; i >= 0;i-- ){ case_label = atoi( tokens[i] ) ; ASSERTNCONT( case_label > 0 && case_label <=numfields, "TWdialog", "case_label out of bounds\n" ) ; fields[case_label].group = group_num ; } /* first one in list is default on switch */ fptr->group = case_label ; } else { M( ERRMSG, "TWread_dialog", "wrong number of tokens for case type field\n" ); return( NULL ) ; } } else { sprintf( YmsgG, "Problem parsing line:%d in dialog file\n", line ) ; M( ERRMSG,"TWread_dialog", YmsgG ) ; } } } /* end parsing loop */ TWCLOSE( fp ) ; if( fields[0].type != BUTTONTYPE || fields[1].type != BUTTONTYPE ){ M( ERRMSG, "TWread_dialog", "accept and reject fields not setup correctly\n" ) ; return( NULL ) ; } if( fields ){ debug_dialog( fields ) ; return( fields ) ; } else { return( NULL ) ; } } /* end TWread_dialog */ static debug_dialog( fieldp ) TWDIALOGPTR fieldp ; { INT i ; /* counter */ INT count ; /* number of fields */ FILE *fp ; /* file pointer */ TWDIALOGPTR fptr ; /* temporary pointer */ fp = TWOPEN( "dialog.h", "w", ABORT ) ; count = 0 ; for( i=0 ; fieldp[i].row ; i++ ){ count++ ; } fprintf( fp, "static TWDIALOGBOX dialogS[%d] = {\n", count+1 ) ; for( i=0 ; fieldp[i].row; i++ ){ fptr = &(fieldp[i]) ; fprintf( fp, " %d,%d,%d,",fptr->row,fptr->column,fptr->len ) ; fprintf( fp, "\"%s\",%d,%d,%d,\n", fptr->string,fptr->type, fptr->color, fptr->group ) ; } fprintf( fp, " 0,0,0,0,0,0,0\n" ) ; fprintf( fp, "} ;\n\n" ) ; TWCLOSE(fp) ; } /* end debug_dialog() */ #endif /* DEBUG */ #endif /* no graphics */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/draw.c000066400000000000000000002136501305746555600205620ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: draw.c DESCRIPTION:graphic drawing routine both screen and file. ******************************************************** THERE ARE TWO FAMILIES OF ROUTINES IN THIS MODULE 1) Graphic routines that write to the CRT screen 2) Routines which write to a set of binary file later to be drawn by an independent program. The user can select whether he wants either of the routines or both. ******************************************************** DATE: Jan 25, 1989 - major rewrite of version 1.0 CONTENTS: BOOL TWcheckServer() TWsetMode( mode ) INT mode ; BOOL TWinitGraphics(argc,argv,numC,colors,dumpOnly,menu,refresh_func) INT argc, numC, (*refresh_func)() ; char *argv[], **colors ; BOOL dumpOnly ; TWMENUPTR menu ; BOOL TWinitParasite(argc,argv,numC,colors,dumpOnly,menu,refresh_func,w) INT argc, numC, (*refresh_func)() ; char *argv[], **colors ; BOOL dumpOnly ; TWMENUPTR menu ; Window w ; static BOOL TWinit(argc,argv,numC,desiredColors,dumpOnly, menu,refresh_func) INT argc, numC, (*refresh_func)() ; char *argv[], **colors ; BOOL dumpOnly ; TWMENUPTR menu ; TWINFOPTR TWgetDrawInfo() TWsetDrawInfo( winheight, winwidth ) INT winheight, winwidth ; TWcloseGraphics() TWzoom() TWfullView() TWsetwindow( left, bottom, right, top ) INT left, bottom, right, top ; TWtranslate() TWflushFrame() TWsync() static void initcolors( desiredColorArray, numC ) char **desiredColorArray ; INT numC ; static startDFrame() static VOID drawDLine(ref,x1,y1,x2,y2,color,label) INT ref, color ; register INT x1,y1,x2,y2 ; char *label ; static VOID drawDRect(ref,x1,y1,x2,y2,color,label) INT ref, color ; register INT x1,y1,x2,y2 ; char *label ; TWarb_init() TWarb_addpt( xpos, ypos ) INT xpos, ypos ; static VOID drawDArb( ref, color, label ) INT ref, color ; char *label ; TWhighLightRect( x1,y1,x2,y2 ) register INT x1,y1,x2,y2 ; TWmoveRect( x1, y1, x2, y2, ptx, pty ) INT *x1, *y1, *x2, *y2, ptx, pty ; static XFontStruct *TWgetfont( fname, font ) Font *font ; TWstartFrame() static closeFrame() TWsetFrame( number ) INT number ; static drawWLine( ref_num,x1,y1,x2,y2,color,label) INT ref_num ; INT x1,y1,x2,y2,color ; char *label; static drawWRect( ref_num, x1,y1,x2,y2,color,label) INT ref_num ; INT x1,y1,x2,y2, color; char *label; static drawWArb( ref, color, label ) INT ref, color ; char *label ; REVISIONS: Jan 31, 1989 - added screen routines. Feb 21, 1989 - initial graphic routines. Feb 27, 1989 - added no graphics conditional compile. Mar 22, 1989 - made TWdrawCell and TWdrawRect separate routines. Added info.h TWinitGraphics now returns a BOOLEAN value on whether it was successful. Mar 23, 1989 - made program exit if problem. Also fixed pointer problem on foreign machines. Apr 1, 1989 - fixed black/white stipple pattern problem. Added parasite mechanism which allows another program to access main window. Apr 9, 1989 - handle change of mode correctly now. Apr 16, 1989 - added XGetDefaults to get user defined screen position. Apr 27, 1989 - update for Y routines. May 11, 1989 - fixed parasite problem. Sep 23, 1989 - added color switch for TWtoggleColor() Oct 2, 1989 - menus now can be compiled into program. Nov 15, 1989 - TWsetFrame now can reset to last frame. Mar 3, 1990 - added zoom out and removed clear screen in parasite mode. Aug 1, 1990 - rewrote to be MOTIF compatible. Sep 25, 1990 - fixed B&W mode. Made 9x15 default font. Oct 5, 1990 - rewrote using prototypes. Added TWcolorXOR. Fixed problem with TWfullview. Also added dumpOnly mode. Added arbitrary rectangle drawing. Oct 12, 1990 - rewrote draw routines to use 4 windows and added pixmap for fast redraws. Also added TWforceRedraw. Oct 14, 1990 - fixed parasite and dump arbitrary figures. Oct 21, 1990 - fixed parasite resizing. Nov 4, 1990 - added Xdefault bw. Dec 5, 1990 - added stipple to info record. Mon Jan 7 18:17:44 CST 1991 - made SAFE_WAIT_TIME user programmable for slow machines. Sun Feb 17 17:12:39 EST 1991 - added 3D graphics functions. Fri Feb 22 23:38:02 EST 1991 - fixed sensitivity of 3D camera. Sat Feb 23 04:57:21 EST 1991 - fixed a very pesky bug with the pixmap. Thu Mar 7 01:26:04 EST 1991 - now store the refresh function. Thu Apr 18 00:36:25 EDT 1991 - fixed argument to refresh function and fixed sun XOR. Sun Apr 28 22:06:15 EDT 1991 - set colors right for reverse video. Wed May 1 18:55:13 EDT 1991 - added TWget_arb_fill. Mon Aug 12 15:52:55 CDT 1991 - added rectangular fill switch. Sun Nov 3 12:51:46 EST 1991 - fixed gcc complaints. Sun Jan 26 03:38:49 EST 1992 - fixed window manager hint problem. Thu Mar 5 17:01:09 EST 1992 - added clipping for faster draw during zoom. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) draw.c (Yale) version 3.41 3/10/92" ; #endif #ifndef NOGRAPHICS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define YDRAW_VARS #include "info.h" #define EXPECTEDCOLORS 201 /* expected number of colors in table */ #define NODIRECTORY 1 #define NOINIT 2 #define OBSCURED (1) #define UNOBSCURED (0) /* the place where these graphic contexts are stored */ #define HIGHLITE (0) #define WHITE (1) #define BLACK (2) #define DIV_2 >> 1 /**** THE MODES AND CHOICES *******/ static INT modeS ; /* determines which mode we are in */ /* the global routines - seen by outside world */ VOID (*_TWdrawRect)(P7( INT ref_num, INT x1, INT y1, INT x2, INT y2, INT color, char *label )) ; VOID (*_TWdrawLine)(P7( INT ref_num, INT x1, INT y1, INT x2, INT y2, INT color, char *label )) ; VOID (*_TWdrawArb)(P3( INT ref_num, INT color, char *label )) ; /* the local routines seen by the routines in this file only */ static VOID drawDRect() ; static VOID drawWRect() ; static VOID drawDArb() ; static VOID drawWArb() ; static VOID drawDLine() ; static VOID drawWLine() ; static VOID initcolors( P2(char **desiredColorArray,INT numC ) ) ; static closeFrame(P1(void)) ; static VOID set_viewing_transformation() ; extern VOID TW3Dperspective( P5(DOUBLE x, DOUBLE y, DOUBLE z, DOUBLE *pX, DOUBLE *pY ) ) ; static BOOL TWinit( P7(INT argc,char *argv[],INT numC,char **desiredColors, BOOL dumpOnly, TWMENUPTR menu, INT (*refresh_func)() ) ) ; static VOID set_clip_window( P4(INT l, INT r, INT b, INT t) ) ; /********** THE CRT ROUTINE STATIC DEFINITIONS *************/ static TWINFO infoBoxS ; /* information for other modules*/ static XColor *colorArrayS ; /* array of color available */ static GC *graphicContextS ; /* array of color contexts */ static INT numColorS; /* the number of colors in table */ static INT borderColorS=BLACK; /* the default border color */ static Display *dpyS; /* the display connection */ static Window backS; /* the back window */ static Window drawS; /* the current window */ static Window parentS; /* the parent window */ static Colormap cmapS ; /* default color map */ static Pixmap pixmapS ; /* offscreen copy of data */ static INT screenS; /* the current screen */ static Font fontS ; /* selected font */ static XFontStruct *fontinfoS ; /* font information */ static BOOL fullViewS ; /* used for zoom window */ static BOOL dumpOnlyS ; /* if TRUE only dump to file */ static BOOL reverseS = FALSE; /* reverse video */ static BOOL parasiteS ; /* this process is a parasite? */ static BOOL colorS ; /* color display ??? */ static BOOL stippleS = FALSE ; /* stipple pattern on */ static BOOL displayOpenS=FALSE; /* display has been opened ??? */ static BOOL *colorOnS ; /* is color turned on ??? */ static BOOL fillArbS = TRUE ; /* whether to fill arbitrary figures */ static BOOL rect_fillS = TRUE ; /* whether to fill rectangle */ static char **userColorS ; /* colors user gave us */ /* FOR 3D perspective routines */ static BOOL perspectiveS; /* perspective toggle flag */ static DOUBLE phiS, thetaS, rhoS; /* 3D view point parameters */ static DOUBLE radiansPerDegreeS; static DOUBLE v11S, v12S, v13S, v21S, v22S, v23S, v32S, v33S, v43S; /* * Initial Window Postion & Dimensions for half screen. */ #define INT_WIDTH (500) #define INT_HEIGHT (500) #define INT_X (1) #define INT_Y (1) static DOUBLE scaleFactorS = 1.0 ;/* scale data to screen dim.*/ static INT xoffsetS ; /* data offset to x screen dim.*/ static INT yoffsetS ; /* data offset to y screen dim.*/ static DOUBLE oldscaleFactorS ; /* remember old for zoom */ static INT oldxoffsetS ; /* remember x for zoom return */ static INT oldyoffsetS ; /* remember y for zoom return */ static unsigned int winwidthS ; /* draw window width in pixels */ static unsigned int winheightS ; /* draw window height in pixels */ static int winxS ; /* window origin x from ul */ static int winyS ; /* window origin y from ul */ static INT leftS ; /* left of user data */ static INT rightS ; /* right of user data */ static INT topS ; /* top of user data */ static INT bottomS ; /* bottom of user data */ static INT lS, rS, bS, tS ; /* current user data */ static INT arblS, arbrS, arbbS, arbtS ;/* current user data */ /* used to draw arbitrary rectilinear shapes */ #define EXPECTEDPTS 12 static INT numptS ; /* current number of points */ static INT ptAllocS = 0 ; /* size of point array */ static XPoint *ptS = NIL(XPoint *) ; /* array of pts for arb figure */ /********** STATIC DEFINITIONS FOR MIXED FUNCTIONS *************/ static char *dirNameS ; /* pathname including DATA directory */ static BOOL initS = FALSE ; /* tells whether initialization performed */ static INT frameCountS ; /* current number of display frames */ static BOOL frameOpenS ; /* tells whether frame files are open */ BOOL TWcheckServer() { char *hostmon ; char *Ygetenv() ; /* get host name from environment variable */ if(!(hostmon = Ygetenv("DISPLAY"))) { M( WARNMSG,"TWcheckServer","Cannot get DISPLAY environment variable\n"); return( FALSE ) ; } /* open display */ if(!(dpyS = XOpenDisplay(hostmon))) { M( WARNMSG,"TWcheckServer","Cannot connect to X server\n"); return( FALSE ) ; } else { XCloseDisplay( dpyS ) ; } return( TRUE ) ; } /* end TWcheckServer */ TWsetMode( mode ) INT mode ; { if( dumpOnlyS && mode != TWWRITEONLY ){ D( "TWsetMode", fprintf( stderr, "Drawing mode should not be changed in dumpOnly operation\n"); ) ; return ; } modeS = mode ; /* select routines */ /* ------------------------------------------------------ NOTE THAT WRITE ROUTINES ALL CHECK MODE FOR TWWRITENDRAW CASE AND CALL THE DRAW ROUTINES. It is done this way since write routines take alot of time anyway. ALSO note that TWinitGraphic and TWcloseGraphics are implemented as mixed families, since they are only called once each during a run. ------------------------------------------------------ */ switch( mode ){ case TWDRAWONLY: /* pick from the D routines */ _TWdrawRect = drawDRect ; _TWdrawLine = drawDLine ; _TWdrawArb = drawDArb ; break ; case TWWRITEONLY: case TWWRITENDRAW: /* pick from the W routines */ _TWdrawRect = drawWRect ; _TWdrawLine = drawWLine ; _TWdrawArb = drawWArb ; break ; } } /* end TWsetMode */ /* start a new window system */ BOOL TWinitGraphics(argc,argv,numC,colors,dumpOnly,menu,refresh_func) INT argc; char *argv[]; char **colors ; BOOL dumpOnly ; INT numC ; TWMENUPTR menu ; INT (*refresh_func)() ; { parasiteS = FALSE ; radiansPerDegreeS = acos( (double) 0.0 ) / (double) 90.0 ; return(TWinit(argc,argv,numC,colors,dumpOnly,menu,refresh_func)); } /* end TWinitGraphics */ /* TWinitParasite takes over windows that were already opened */ BOOL TWinitParasite(argc,argv,numC,colors,dumpOnly,menu,refresh_func,w) INT argc; char *argv[]; INT numC ; char **colors ; BOOL dumpOnly ; TWMENUPTR menu ; INT (*refresh_func)() ; INT w ; { parasiteS = TRUE ; backS = (Window) w ; return(TWinit(argc,argv,numC,colors,dumpOnly,menu,refresh_func)); } /* end TWinitParasite */ static BOOL TWinit(argc,argv,numC,desiredColors,dumpOnly,menu,refresh_func) INT argc; char *argv[]; INT numC ; char **desiredColors ; BOOL dumpOnly ; TWMENUPTR menu ; INT (*refresh_func)() ; { XSetWindowAttributes attr; XWindowAttributes wattr; XEvent event ; /* describes event */ char *font ; /* user font request */ char *hostmon ; /* the host name of display */ char *Ygetenv() ; /* get the environment variables */ char *reply ; /* get xdefaults */ INT depth; BOOL saveflag ; Window root; XSizeHints hints ; /* setup hints for window manager */ char *Yfixpath() ; char *winstr ; /* position of Xdefault window */ long event_mask ; /* used to set input selection to window */ INT m ; /* mask for determining window position*/ dumpOnlyS = dumpOnly ; /* save for rest of execution */ if(!(dirNameS = Ygetenv( "DATADIR" ))){ /* find fullpathname of data directory */ /* dirNameS = Yfixpath( "./DATA", FALSE ) ; */ /* Continue with no data dumps; this is okay! */ dirNameS = NULL; } /* first look for data directory */ if((dirNameS != NULL) && !(YdirectoryExists(dirNameS)) ){ /* always send this message to the screen */ saveflag = Ymessage_get_mode() ; Ymessage_mode( M_VERBOSE ) ; M(MSG, NULL,"\n\n" ) ; sprintf( YmsgG,"Not Fatal:can't find data directory:%s\n", dirNameS ); M(ERRMSG,"TWinitGraphics",YmsgG ) ; M(MSG,NULL, "\tKill program and use \"setenv DATADIR \" "); M(MSG,NULL, "to set data directory\n"); M(MSG,NULL, "\tor allow program to continue with the inability to " ) ; M(MSG,NULL, "perform screen dumps\n"); Ymessage_mode( saveflag ) ; dirNameS = NULL ; } /* set count to zero */ frameCountS = 0 ; frameOpenS = FALSE ; /* ------------------------------------------------------- Set the mode of the graphic routines. mode Function 0 TWDRAWONLY Draw graphics to screen. 1 TWWRITEONLY Write graphics to draw program binary files. 2 TWWRITENDRAW Draw graphics to screen and write draw files. For mode 0 hostmon must be valid. For mode 1 dataDir (path of data directory) must be valid. For all modes desiredColors must be valid. --------------------------------------------------------- */ if( dumpOnlyS ){ /* we are done for the dump_graphics mode */ initS = TRUE ; TWsetMode( TWWRITEONLY ) ; /* always enable both modes */ return ; } else { /* OTHERWISE INITIALIZE BOTH MODES */ TWsetMode( TWWRITENDRAW ) ; /* always enable both modes */ } /***** BEGIN SCREEN GRAPHICS IN THIS ROUTINE **** */ /* get host name from environment variable */ if(!(hostmon = Ygetenv("DISPLAY"))) { M(ERRMSG,"TWinitGraphics","Could not get DISPLAY environment variable.\n"); YexitPgm(NOINIT) ; } /* open display */ if(!(dpyS = XOpenDisplay(hostmon))) { M(ERRMSG,"TWinitGraphics","Could not connect to X server.\n"); YexitPgm(NOINIT) ; } /* get various information about display */ screenS = DefaultScreen(dpyS); cmapS = DefaultColormap(dpyS,screenS); parentS = root = RootWindow(dpyS,screenS); depth = DefaultDepth(dpyS,screenS); /* check whether machine is color or not */ if( (colorS = XDisplayCells( dpyS, screenS )) > 2 ){ /* if color number of display cells > 0 */ colorS = TRUE ; if( reply = XGetDefault( dpyS, GRAPHICS, "bw" )){ if( strcmp( reply, "on" ) == STRINGEQ ){ colorS = FALSE ; } } } else { colorS = FALSE ; } /* set font and get font info */ if(font = XGetDefault( dpyS, GRAPHICS, "font" )){ fontinfoS = TWgetfont( font, &fontS ) ; infoBoxS.fontname = font ; } else { /* we perfer our default to be 9x15 */ fontinfoS = TWgetfont( "9x15", &fontS ) ; if(!(fontinfoS )){ fontinfoS = TWgetfont( "fixed", &fontS ) ; infoBoxS.fontname = "fixed" ; } else { infoBoxS.fontname = "9x15" ; } } /* see if we should turn on the stipple pattern */ if( reply = XGetDefault( dpyS, GRAPHICS, "stipple" )){ if( strcmp( reply, "on" ) == STRINGEQ ){ stippleS = TRUE ; } } /* see if we should turn on/off the rectangular fill */ if( reply = XGetDefault( dpyS, GRAPHICS, "rectangle_fill" )){ if( strcmp( reply, "off" ) == STRINGEQ ){ rect_fillS = FALSE ; /* dont fill rectangles - default on */ } } /* see if we should turn on/off the arbitrary fill */ if( reply = XGetDefault( dpyS, GRAPHICS, "arbitrary_fill" )){ if( strcmp( reply, "off" ) == STRINGEQ ){ fillArbS = FALSE ; /* dont fill arbs - default on */ } } /* see if we should turn off the reverse video */ if( reply = XGetDefault( dpyS, GRAPHICS, "reverse" )){ if( strcmp( reply, "on" ) == STRINGEQ ){ reverseS = TRUE ; } } /* see if we need to reset the wait time to redraw */ if( reply = XGetDefault( dpyS, GRAPHICS, "wait_time" )){ TWsafe_wait_timeG = atoi( reply ) ; } else { TWsafe_wait_timeG = 2 ; } /* initialize position */ if( winstr = XGetDefault( dpyS, GRAPHICS, "geometry" )){ m = XParseGeometry( winstr,&winxS,&winyS,&winwidthS,&winheightS) ; if( m & XNegative ){ winxS = XDisplayWidth( dpyS, screenS ) + winxS ; } if( m & YNegative ){ winyS = XDisplayHeight( dpyS, screenS ) + winyS ; } /* these two lines insure that uses doesn't have to press */ /* button using twm window manager */ if( winxS == 0 ) winxS++ ; if( winyS == 0 ) winyS++ ; hints.flags = USPosition | USSize ; } else { winwidthS = INT_WIDTH; winheightS = INT_HEIGHT; winxS = INT_X; winyS = INT_Y; hints.flags = PPosition | PSize ; } /* end initializing position of window */ XSelectInput(dpyS,root,SubstructureNotifyMask ); attr.event_mask = StructureNotifyMask | SubstructureNotifyMask | VisibilityChangeMask | ExposureMask; attr.override_redirect = FALSE ; attr.save_under = FALSE ; attr.backing_store = NotUseful ; if(reverseS == TRUE){ attr.background_pixel = BlackPixel(dpyS,screenS); } else { attr.background_pixel = WhitePixel(dpyS,screenS); } if(!(parasiteS)){ backS = XCreateWindow(dpyS,root,winxS,winyS,winwidthS, winheightS, 0,depth,InputOutput,DefaultVisual(dpyS,screenS), CWEventMask|CWBackPixel|CWOverrideRedirect| CWSaveUnder | CWBackingStore,&attr); drawS = XCreateSimpleWindow( dpyS, backS, 0, MENUHEIGHT, winwidthS, winheightS - 2*MENUHEIGHT, 0L, BlackPixel(dpyS,screenS), attr.background_pixel ) ; event_mask = ExposureMask | ButtonPressMask ; XSelectInput(dpyS,drawS,event_mask); /* initialize colors and/or stipple patterns */ initcolors( desiredColors, numC ) ; /* set the window manager hints */ hints.x = winxS ; hints.y = winyS ; hints.width = winwidthS ; hints.height = winheightS ; XSetStandardProperties( dpyS,backS,GRAPHICS,GRAPHICS,None,argv,argc,&hints); XMapWindow(dpyS,backS); XMapRaised(dpyS,drawS); /* wait to get window */ XSync(dpyS, FALSE ); /* ------------------------------------------------------------- Now wait to window to become visible. This code is necessary since some window managers (uwm) map the window as a ghost image and wait for user to resize window. Other window managers (twm) map window as requested. Need to accomodate both. -------------------------------------------------------------- */ while( TRUE ){ if( XCheckTypedWindowEvent(dpyS,backS,VisibilityNotify,&event)){ if( event.xvisibility.state == VisibilityUnobscured ){ break ; } } } } else { /* for a parasite case */ /* retrieve the window information */ drawS = TWgetWindowId( dpyS, backS ) ; /* set the event mask for the windows */ event_mask = StructureNotifyMask | SubstructureNotifyMask | VisibilityChangeMask ; XSelectInput(dpyS,backS,event_mask); event_mask = ExposureMask | ButtonPressMask ; XSelectInput(dpyS,drawS,event_mask); /* initialize colors and/or stipple patterns */ initcolors( desiredColors, numC ) ; } /* if the window manager added border around window we */ /* need to save new origin of window */ /* also if user changed size we need to get it */ XGetWindowAttributes( dpyS, backS, &wattr ) ; winxS = infoBoxS.winx = wattr.x ; winyS = infoBoxS.winy = wattr.y ; winwidthS = infoBoxS.winwidth = wattr.width ; winheightS = infoBoxS.winheight = wattr.height - 2 * MENUHEIGHT ; /* default user data boarder to size of window */ leftS = 0 ; bottomS = MENUHEIGHT ; rightS = winwidthS ; topS = winheightS ; fullViewS = TRUE ; /* save the refresh function */ infoBoxS.refresh_func = refresh_func ; TW3Dnormal_view() ; if(!(parasiteS)){ XClearWindow(dpyS,drawS); } /* off screen copy of the data */ pixmapS = XCreatePixmap( dpyS, drawS, (unsigned)winwidthS, (unsigned)winheightS, XDefaultDepth(dpyS,screenS) ) ; if(!(TWinitMenuWindow( menu ))){ initS = TRUE ; /* fake out TWcloseGraphics */ TWcloseGraphics() ; YexitPgm(NOINIT) ; } TWdrawMenus() ; XFlush( dpyS ) ; /* initialization has been done sucessfully */ displayOpenS = TRUE; /* display is open for business */ initS = TRUE ; TWsetMode( TWDRAWONLY ) ; return( initS ) ; } /* end function TWinitGraphics */ TWINFOPTR TWgetDrawInfo() { TWINFOPTR info ; /* put all information in record for other modules use */ /* a inefficient attempt at object orient programming */ info = &infoBoxS ; info->graphicContext = graphicContextS ; info->dpy = dpyS ; info->drawWindow = drawS ; info->backWindow = backS ; info->rootWindow = parentS ; info->screen = screenS ; info->fontinfo = fontinfoS ; info->scaleFactor = scaleFactorS ; info->xoffset = xoffsetS ; info->yoffset = yoffsetS ; info->winwidth = winwidthS ; info->winheight = winheightS ; info->winx = winxS ; info->winy = winyS ; info->colorOn = colorOnS ; info->numColors = numColorS ; info->colors = userColorS ; info->pixmap = pixmapS ; info->stipple = stippleS ; return( info ) ; } /* end TWgetDrawInfo */ TWsetDrawInfo( winheight, winwidth, pixmap ) INT winheight, winwidth ; Pixmap pixmap ; { infoBoxS.winwidth = winwidthS = winwidth ; infoBoxS.winheight = winheightS = winheight ; infoBoxS.pixmap = pixmapS = pixmap ; fullViewS = TRUE ; TWsetwindow( leftS, bottomS, rightS, topS ) ; } /* end TWsetDrawInfo */ TWforceRedraw() { XEvent event ; /* describes configuration event */ /* set a redraw command for a zoom */ event.xexpose.type = Expose ; event.xexpose.display = dpyS ; event.xexpose.window = drawS ; event.xexpose.x = 0 ; event.xexpose.y = 0 ; event.xexpose.count = 0 ; XSendEvent( dpyS, drawS, TRUE, ExposureMask, &event ) ; } /* end TWforceRedraw */ TWcloseGraphics() { if(!(initS )){ fprintf(stderr,"ERROR[closeGraphics]:initialization was not" ) ; fprintf(stderr,"performed\n before calling closeGraphics\n" ) ; YexitPgm( NOINIT ) ; } /* check to see if other files are open */ if( frameOpenS ){ closeFrame() ; } if( displayOpenS ){ TWfreeMenuWindows() ; XCloseDisplay( dpyS ) ; displayOpenS = FALSE ; } } /* end TWcloseGraphics */ /*********** BEGIN STRICT GRAPHICS ROUTINES ************* */ /* perform a zoom in main graphics window */ TWzoom() { INT x1, y1 ; /* first point of user zoom */ INT x2, y2 ; /* second point of user zoom */ INT left, right, bottom, top ; /* for calculating window */ INT span ; /* span of design */ TWmessage( "[ZOOM]:Pick or enter first point of bounding box:" ) ; TWgetPt2( &x1, &y1 ) ; TWmessage( "[ZOOM]:Pick or enter second point of bounding box:" ) ; TWgetPt2( &x2, &y2 ) ; if( fullViewS ){ /* only save full view window size */ oldxoffsetS = xoffsetS ; oldyoffsetS = yoffsetS ; oldscaleFactorS = scaleFactorS ; fullViewS = FALSE ; } if( x1 >= x2 && y1 >= y2 ){ /* zoom out */ span = rightS - leftS ; span *= 2 ; left = leftS = ( (x1 + x2 ) / 2 ) - span / 2 ; right = rightS = ( (x1 + x2 ) / 2 ) + span / 2 ; span = topS - bottomS ; span *= 2 ; bottom = bottomS = ( (y1 + y2 ) / 2 ) - span / 2 ; top = topS = ( (y1 + y2 ) / 2 ) + span / 2 ; } else { /* zoom in */ left = MIN( x1, x2 ) ; right = MAX( x1, x2 ) ; bottom = MIN( y1, y2 ) ; top = MAX( y1, y2 ) ; } /* set new window */ TWsetwindow( left, bottom, right, top ) ; /* important that we reset full view to FALSE at this point */ /* since TWsetwindow always sets it to TRUE */ fullViewS = FALSE ; TWmessage( " " ) ; TWforceRedraw() ; } /* returns to full screen after zoom */ TWfullView() { if( fullViewS ){ return ; } TWmessage( "[FULLSCREEN]: Returning to original size" ) ; fullViewS = TRUE ; infoBoxS.xoffset = xoffsetS = oldxoffsetS ; infoBoxS.yoffset = yoffsetS = oldyoffsetS ; infoBoxS.scaleFactor = scaleFactorS = oldscaleFactorS ; TWforceRedraw() ; } /* end TWfullScreen */ /* set the window area for bar */ TWsetwindow( left, bottom, right, top ) INT left, bottom, right, top ; { INT xspan, yspan ; /* span of data */ DOUBLE xscaleF, yscaleF ; /* scale data to window span */ if( modeS == TWWRITEONLY ){ return ; } /* save what the user gave us in case we need to use it */ /* for a reconfiguration request - ie, resize window */ if( fullViewS ){ leftS = left ; rightS = right ; bottomS = bottom ; topS = top ; } xspan = ABS( right - left ) ; if( xspan == 0 ){ if( initS ){ TWmessage( "ERROR: xspan is zero. Aborting zoom..." ) ; return ; } else { M(ERRMSG,"TWsetwindow", "xspan is zero" ) ; return ; } } yspan = ABS( top - bottom ) ; if( yspan == 0 ){ if( initS ){ TWmessage( "ERROR: yspan is zero. Aborting zoom..." ) ; return ; } else { M(ERRMSG,"TWsetwindow", "yspan is zero" ) ; return ; } } /* scale data to fit to window */ xscaleF = (DOUBLE) winwidthS / (DOUBLE) xspan ; yscaleF = (DOUBLE) winheightS / (DOUBLE) yspan ; /* pick smallest of factors for scale factor */ scaleFactorS = MIN( xscaleF, yscaleF) ; /* offset from beginning of data */ xoffsetS = - left ; yoffsetS = - bottom ; if(!(fullViewS)){ set_clip_window( left, right, bottom, top ) ; lS = left ; bS = bottom ; if( xspan > yspan ){ rS = right ; tS = bottom + xspan ; } else if( xspan < yspan ){ rS = left + yspan ; tS = top ; } else { rS = right ; tS = top ; } } TWinforMenus() ; fullViewS = TRUE ; } /* end TWsetwindow */ static VOID set_clip_window( left, right, bottom, top ) INT left, right, bottom, top ; { INT xspan, yspan ; lS = left ; bS = bottom ; xspan = ABS( right - left ) ; yspan = ABS( top - bottom ) ; if( xspan > yspan ){ rS = right ; tS = bottom + xspan ; } else if( xspan < yspan ){ rS = left + yspan ; tS = top ; } else { rS = right ; tS = top ; } } /* end set_clip_window() */ TWtranslate() { INT x1, y1 ; INT last_xoff, last_yoff ; if( fullViewS ){ /* only save full view window size */ oldxoffsetS = xoffsetS ; oldyoffsetS = yoffsetS ; oldscaleFactorS = scaleFactorS ; fullViewS = FALSE ; set_clip_window( leftS, rightS, bottomS, topS ) ; } last_xoff = xoffsetS ; last_yoff = yoffsetS ; TWmessage( "[TRANSLATE]:Pick or enter center of view:" ) ; TWgetPt2( &x1, &y1 ) ; sprintf( YmsgG, "new center - %d,%d", x1, y1 ) ; TWmessage( YmsgG ) ; /* translate to origin first */ xoffsetS = - x1 ; yoffsetS = - y1 ; /* now center in screen - half of xspan */ xoffsetS += (INT) ( (DOUBLE) winwidthS / scaleFactorS / 2.0 ) ; yoffsetS += (INT) ( (DOUBLE) winheightS / scaleFactorS / 2.0 ); TWinforMenus() ; /* tell other module about info */ TWforceRedraw() ; /* update clipping window */ lS -= (xoffsetS - last_xoff) ; rS -= (xoffsetS - last_xoff) ; bS -= (yoffsetS - last_yoff) ; tS -= (yoffsetS - last_yoff) ; D( "TWtranslate", fprintf( stderr, "l:%d r:%d b:%d t:%d\n", lS, rS, bS, tS ) ; ) ; } /* end TWtranslate */ /* copy pixmap to screen and flush screen output buffer */ /* flush screen output buffer */ TWflushFrame() { if( modeS == TWWRITEONLY ){ return ; } XFlush( dpyS ) ; TWcheckExposure() ; } /* end TWflushFrame */ /* process everything in buffer */ TWsync() { if( modeS == TWWRITEONLY ){ return ; } XFlush( dpyS ) ; XSync( dpyS, 0 ) ; } /* end TWsync */ static VOID initcolors( desiredColorArray, numC ) char **desiredColorArray ; INT numC ; { unsigned long backgrd; unsigned long foregrd; unsigned long whitepix ; unsigned long blackpix ; GC gc ; /* temp for graphics context */ char *color ; XColor ecolor ; /* exact color - do need to use it */ INT i, j, k ; INT pattern ; char *stipple ; char *TWstdStipple() ; char row, bit ; Pixmap *stipplePix ; /* array of pixmaps for stipple */ /* make copy of the users colors */ userColorS = YMALLOC( numC+1, char * ) ; for( i=0; i <= numC; i++ ){ if( desiredColorArray[i] ){ userColorS[i] = Ystrclone( desiredColorArray[i] ) ; } else { userColorS[i] = NULL ; } } /* get default backgrounds white and black */ whitepix = WhitePixel(dpyS,screenS); blackpix = BlackPixel(dpyS,screenS); if( reverseS == TRUE ){ backgrd = blackpix ; foregrd = whitepix ; } else { backgrd = whitepix ; foregrd = blackpix ; } if( !(colorS) || stippleS ){ stippleS = TRUE ; stipple = TWstdStipple() ; stipplePix = YMALLOC( numC+1, Pixmap ) ; { unsigned int x, y, xret, yret ; x = 8 ; y = 8 ; XQueryBestSize( dpyS, StippleShape, drawS, x,y, &xret, &yret ) ; } } /* allocate size of colorArrayS */ colorArrayS = YMALLOC( numC+1, XColor ) ; /* allocate array for whether color is turned on or off */ colorOnS = YMALLOC( numC+1, BOOL ) ; /* allocate initial size of graphic context one for each color */ graphicContextS = YMALLOC( numC+1, GC ) ; /* initialize color on array */ for( i = 0; i <= numC; i++ ){ colorOnS[i] = TRUE ; } /**** now create GRAPHIC CONTEXT for highlighting data **** */ gc = graphicContextS[0] = XCreateGC( dpyS,drawS,0L,NULL ) ; XSetFont( dpyS, gc, fontS ) ; XSetFunction( dpyS, gc, GXxor ) ; #ifdef sun XSetForeground( dpyS, gc, foregrd ) ; XSetBackground( dpyS, gc, backgrd ) ; #else XSetForeground( dpyS, gc, backgrd ) ; XSetBackground( dpyS, gc, foregrd ) ; #endif XSetFillStyle( dpyS, gc, FillSolid ) ; XSetLineAttributes( dpyS,gc,1,LineSolid,CapButt,JoinBevel ) ; /**** end create GRAPHIC CONTEXT for highlighting data **** */ /* lookup color in color table */ for( i=1; i<= numC; i++ ){ /* take user given colors and look them up in color table */ if( !(color = desiredColorArray[i] ) ){ fprintf( stderr, "ERROR:Color is NULL\n" ) ; break ; /* avoid nulls */ } /* check to make sure first two entries are */ if( i == 1 ){ /* user must give white */ if( strcmp( desiredColorArray[i], "white" ) != STRINGEQ ){ fprintf( stderr, "ERROR:Element 1 must be white in color array.\n") ; } } else if( i == 2 ){ /* user must give black */ if( strcmp( desiredColorArray[i], "black" ) != STRINGEQ ){ fprintf( stderr, "ERROR:Element 2 must be black in color array.\n") ; } } if( colorS ){ /* now fill up this element of the color array */ if( XAllocNamedColor(dpyS,cmapS,color,&(colorArrayS[i]), &ecolor) <= 0){ /* default to white if call is unsucessful <= 0 */ fprintf( stderr,"Can't find color:%s ", color ) ; fprintf( stderr,"in color table. Defaulting to white.\n"); colorArrayS[i].pixel = whitepix ; } } /* now create GRAPHIC CONTEXT */ graphicContextS[i] =XCreateGC( dpyS,drawS,0L,NULL ) ; /* set font */ XSetFont( dpyS, graphicContextS[i], fontS ) ; XSetFunction( dpyS, graphicContextS[i], GXcopy ) ; XSetBackground( dpyS, graphicContextS[i], backgrd ) ; if( i == 1 ){ XSetForeground( dpyS, graphicContextS[i], whitepix ) ; XSetBackground( dpyS, graphicContextS[i], blackpix ) ; } else if( i == 2 ){ XSetForeground( dpyS, graphicContextS[i], blackpix ) ; XSetBackground( dpyS, graphicContextS[i], whitepix ) ; } else if( colorS ){ XSetForeground( dpyS, graphicContextS[i], colorArrayS[i].pixel ) ; } if( colorS || i <= 2 ){ XSetFillStyle( dpyS, graphicContextS[i], FillSolid ) ; XSetLineAttributes( dpyS,graphicContextS[i],1,LineSolid, CapRound, JoinBevel ) ; } if( i >= 3 && stippleS ){ /* i > 2 and black and white */ if( !(colorS)){ if( reverseS ){ XSetForeground( dpyS, graphicContextS[i], backgrd ) ; } else { XSetForeground( dpyS, graphicContextS[i], foregrd ) ; } } XSetLineAttributes( dpyS,graphicContextS[i],1,LineSolid, CapRound, JoinBevel ) ; /* set stipple patterns for black and white */ XSetFillStyle( dpyS, graphicContextS[i], FillTiled ); /* now create an 8 x 8 pixmap for the stipple pattern */ stipplePix[i] = XCreatePixmap( dpyS,drawS, (unsigned)8, (unsigned)8, XDefaultDepth(dpyS,screenS) ) ; /* Clear the pixmap - this is very subtle. Use */ /* XFillRectangle to insure pixmap doesn't have junk in it */ if( reverseS ){ XFillRectangle( dpyS, stipplePix[i], graphicContextS[BLACK], 0, 0, 8, 8 ) ; } else { XFillRectangle( dpyS, stipplePix[i], graphicContextS[WHITE], 0, 0, 8, 8 ) ; } /* pick ith stipple pattern fill in TWstdStipple array */ /* pattern is offset into array */ pattern = 8 * (i - 3) ; for( j = 0; j < 8 ; j++ ){ row = stipple[pattern+j] ; for( k = 0; k < 8 ; k++ ){ bit = row >> k ; /* now get low order bit */ bit &= 0x01 ; if( bit ){ if( reverseS ){ XDrawPoint( dpyS, stipplePix[i], graphicContextS[WHITE], j, k ) ; } else { if( colorS ){ XDrawPoint( dpyS, stipplePix[i], graphicContextS[i], j, k ) ; } else { XDrawPoint( dpyS, stipplePix[i], graphicContextS[BLACK], j, k ) ; } } } } } /* at this point we are done building pixmap */ /* apply stipple to graphic context */ XSetTile( dpyS, graphicContextS[i], stipplePix[i] ) ; XSetFillRule( dpyS, graphicContextS[i], WindingRule ) ; XSetTSOrigin( dpyS, graphicContextS[i], 0, 0 ) ; } /* end building stipple pattern */ } numColorS = numC ; ASSERT( numC != 0, "initcolor", "User didn't give any color data" ) ; } /* end initcolor */ TWcolorXOR( color, exorFlag ) INT color ; BOOL exorFlag ; { /* check to make sure color is valid */ if( color <= 0 || color > numColorS ){ if( initS ){ /* graphics are available */ sprintf( YmsgG, "Color number:%d is out of range", color ) ; TWmessage( YmsgG ) ; } else { fprintf( stderr,"Color number:%d is out of range", color ) ; } return ; } if( exorFlag ){ XSetFunction( dpyS, graphicContextS[color], GXxor ) ; } else { XSetFunction( dpyS, graphicContextS[color], GXcopy ) ; } } /* end TWcolorXOR */ /* start a new slate */ static startDFrame() { XClearWindow( dpyS, drawS ) ; if( reverseS ){ XFillRectangle( dpyS, pixmapS, graphicContextS[BLACK], 0, 0, winwidthS, winheightS ) ; } else { XFillRectangle( dpyS, pixmapS, graphicContextS[WHITE], 0, 0, winwidthS, winheightS ) ; } TWdrawMenus() ; XFlush( dpyS ) ; } /* end startDFrame */ static VOID drawDLine(ref,x1,y1,x2,y2,color,label) /* draw a one pixel tall line segment from x1,y1 to x2,y2 */ INT ref, color ; register INT x1,y1,x2,y2 ; char *label ; { /* check to make sure color is valid */ if( color <= 0 || color > numColorS ){ if( initS ){ /* graphics are available */ sprintf( YmsgG, "Color number:%d is out of range", color ) ; TWmessage( YmsgG ) ; } else { fprintf( stderr,"Color number:%d is out of range", color ) ; } return ; } else if(!(colorOnS[color])){ return ; } if(!(colorS )){ /* set all lines to black in B&W mode */ color = BLACK ; } /* see if we need to clip line. We use to let Xserver do this */ /* but we can avoid an interprocess communication if we do it ourself */ if(!(fullViewS)){ if(!(Yproject_intersect( x1, x2, y1, y2, lS, rS, bS, tS ) )){ return ; } } /* add users data offset */ /* next scale coordinates to window */ /* account for inversion of y axis */ x1 = (INT) ( (DOUBLE) (x1 + xoffsetS) * scaleFactorS ) ; x2 = (INT) ( (DOUBLE) (x2 + xoffsetS) * scaleFactorS ) ; y1 = winheightS - (INT) ( (DOUBLE) (y1 + yoffsetS) * scaleFactorS ) ; y2 = winheightS - (INT) ( (DOUBLE) (y2 + yoffsetS) * scaleFactorS ) ; /* now draw line */ XDrawLine( dpyS,drawS,graphicContextS[color], x1,y1,x2,y2 ) ; XDrawLine( dpyS,pixmapS,graphicContextS[color], x1,y1,x2,y2 ) ; if( label ){ if( *label != EOS ){ XDrawImageString( dpyS, drawS, graphicContextS[color], (x1+x2)/2, (y1+y2)/2, label, strlen(label) ) ; XDrawImageString( dpyS, pixmapS, graphicContextS[color], (x1+x2)/2, (y1+y2)/2, label, strlen(label) ) ; } } } /* end drawDLine */ static VOID drawDRect(ref,x1,y1,x2,y2,color,label) /* draw a rectangle whose diagonals are (x1,y1) and (x2,y2) */ /* if the specified color is default or invalid, use default color */ /* A border will be draw around the cell if specified black (default). */ INT ref, color ; register INT x1,y1,x2,y2 ; char *label ; { UNSIGNED_INT width, height ; INT len ; /* check to make sure color is valid */ if( color <= 0 || color > numColorS ){ if( initS ){ /* graphics are available */ sprintf( YmsgG, "Color number:%d is out of range", color ) ; TWmessage( YmsgG ) ; } else { fprintf( stderr,"Color number:%d is out of range", color ) ; } return ; } else if(!(colorOnS[color])){ return ; } if(!(fullViewS)){ /* clip if necessary for speed. Avoid interprocess communication */ if(!(Yproject_intersect( x1, x2, y1, y2, lS, rS, bS, tS ) )){ return ; } } /* first add data offset to move to relative to 0,0 */ x1 += xoffsetS ; x2 += xoffsetS ; y1 += yoffsetS ; y2 += yoffsetS ; /* next scale coordinates to window */ x1 = (INT) ( (DOUBLE) x1 * scaleFactorS ) ; x2 = (INT) ( (DOUBLE) x2 * scaleFactorS ) ; y1 = (INT) ( (DOUBLE) y1 * scaleFactorS ) ; y2 = (INT) ( (DOUBLE) y2 * scaleFactorS ) ; width = x2 - x1 ; height = y2 - y1 ; /* account for inversion of y axis */ y1 = winheightS - y1 ; y2 = winheightS - y2 ; if( rect_fillS ){ XFillRectangle( dpyS,drawS,graphicContextS[color], x1,y2,width,height ) ; XFillRectangle( dpyS,pixmapS,graphicContextS[color], x1,y2,width,height ) ; if( borderColorS ){ XDrawRectangle( dpyS,drawS,graphicContextS[borderColorS], x1,y2,width,height ) ; XDrawRectangle( dpyS,pixmapS,graphicContextS[borderColorS], x1,y2,width,height ) ; } } else { XDrawRectangle( dpyS,drawS,graphicContextS[color], x1,y2,width,height ) ; XDrawRectangle( dpyS,pixmapS,graphicContextS[color], x1,y2,width,height ) ; } if( label ){ if( *label != EOS ){ len = strlen(label) ; /* now find width of string as offset */ width = XTextWidth( fontinfoS, label, len ) ; /* need image string so you can write on top of fill */ XDrawImageString( dpyS, drawS, graphicContextS[color], (x1+x2-width)/2, (y1+y2)/2, label, strlen(label) ) ; XDrawImageString( dpyS, pixmapS, graphicContextS[color], (x1+x2-width)/2, (y1+y2)/2, label, strlen(label) ) ; } } } /* end drawDCell */ TWarb_init() { /* allocate memory if needed */ if(!(ptS)){ ptAllocS = EXPECTEDPTS ; ptS = YMALLOC( ptAllocS, XPoint ); } if( modeS == TWWRITEONLY || modeS == TWWRITENDRAW ){ Ybuster_init() ; } /* make sure we cannot match the 0 record in the redundancy */ #if 0 /* Yikes! XPoint x and y records are defined as type short. . . */ ptS[0].x = INT_MIN ; ptS[0].y = INT_MIN ; #else ptS[0].x = SHRT_MIN ; ptS[0].y = SHRT_MIN ; #endif numptS = 0 ; if( !(fullViewS)){ arblS = INT_MAX ; arbrS = INT_MIN ; arbbS = INT_MAX ; arbtS = INT_MIN ; } } /* end TWarb_init */ /* ***************************************************************** */ TWarb_addpt( xpos, ypos ) INT xpos, ypos ; { if( modeS == TWWRITEONLY || modeS == TWWRITENDRAW ){ Ybuster_addpt( xpos, ypos ) ; } if(!(fullViewS)){ arblS = MIN( arblS, xpos ) ; arbbS = MIN( arbbS, ypos ) ; arbrS = MAX( arbrS, xpos ) ; arbtS = MAX( arbtS, ypos ) ; } /* first add data offset to move to relative to 0,0 */ xpos += xoffsetS ; ypos += yoffsetS ; /* next scale coordinates to window */ xpos = (INT) ( (DOUBLE) xpos * scaleFactorS ) ; ypos = (INT) ( (DOUBLE) ypos * scaleFactorS ) ; /* account for inversion of y axis */ ypos = winheightS - ypos ; /* now points are in X coordinates */ if( xpos == (INT) ptS[numptS].x && ypos == (INT) ptS[numptS].y ){ /* avoid redundant points */ return ; } /* increase the space if necessary */ if( ++numptS >= ptAllocS ){ ptAllocS += EXPECTEDPTS ; ptS = YREALLOC( ptS, ptAllocS, XPoint ) ; } ptS[numptS].x = (SHORT) xpos ; ptS[numptS].y = (SHORT) ypos ; } /* end TWarb_addpt */ /* ***************************************************************** */ static VOID drawDArb( ref, color, label ) INT ref, color ; char *label ; { INT i ; /* counter */ INT len ; /* length of string if given */ INT x1, y1, x2, y2 ; /* bounding box of figure */ UNSIGNED_INT width ; /* width of font */ XPoint *points ; /* array starts from 1 not zero */ if( color <= 0 || color > numColorS ){ if( initS ){ /* graphics are available */ sprintf( YmsgG, "Color number:%d is out of range", color ) ; TWmessage( YmsgG ) ; } else { fprintf( stderr,"Color number:%d is out of range", color ) ; } return ; } else if(!(colorOnS[color])){ return ; } points = &(ptS[1]) ; /* close the figure if it is not already closed */ if( ptS[numptS].x != ptS[1].x || ptS[numptS].y != ptS[1].y ){ /* increase the space if necessary */ if( ++numptS >= ptAllocS ){ ptAllocS += EXPECTEDPTS ; ptS = YREALLOC( ptS, ptAllocS, XPoint ) ; } ptS[numptS].x = ptS[1].x ; ptS[numptS].y = ptS[1].y ; } x1 = x2 = (INT) ptS[1].x ; y1 = y2 = (INT) ptS[1].y ; for( i = 2; i <= numptS; i++ ){ x1 = MIN( x1, (INT) ptS[i].x ) ; x2 = MAX( x2, (INT) ptS[i].x ) ; y1 = MIN( y1, (INT) ptS[i].y ) ; y2 = MAX( y2, (INT) ptS[i].y ) ; } if(!(fullViewS)){ /* clip if necessary for speed. Avoid interprocess communication */ if(!(Yproject_intersect( arblS, arbrS, arbbS, arbtS, lS, rS, bS, tS ) )){ return ; } } if( fillArbS ){ /* the fill automatically closed the region. if we don't */ /* let it close the region, we have problems - bug in XFillPolygon */ XFillPolygon( dpyS, drawS, graphicContextS[color], points, numptS, Complex, CoordModeOrigin ) ; XFillPolygon( dpyS, pixmapS, graphicContextS[color], points, numptS, Complex, CoordModeOrigin ) ; } if( label ){ if( *label != EOS ){ len = strlen(label) ; /* now find width of string as offset */ width = XTextWidth( fontinfoS, label, len ) ; /* need image string so you can write on top of fill */ /* calculate where we need to put the label */ x1 = x2 = (INT) ptS[1].x ; y1 = y2 = (INT) ptS[1].y ; for( i = 2; i <= numptS; i++ ){ x1 = MIN( x1, (INT) ptS[i].x ) ; x2 = MAX( x2, (INT) ptS[i].x ) ; y1 = MIN( y1, (INT) ptS[i].y ) ; y2 = MAX( y2, (INT) ptS[i].y ) ; } XDrawImageString( dpyS, drawS, graphicContextS[color], (x1+x2-width)/2, (y1+y2)/2, label, strlen(label) ) ; XDrawImageString( dpyS, pixmapS, graphicContextS[color], (x1+x2-width)/2, (y1+y2)/2, label, strlen(label) ) ; } } if( fillArbS ){ if( borderColorS ){ XDrawLines( dpyS, drawS, graphicContextS[borderColorS], points, numptS, CoordModeOrigin ) ; XDrawLines( dpyS, pixmapS, graphicContextS[borderColorS], points, numptS, CoordModeOrigin ) ; } } else { XDrawLines( dpyS, drawS, graphicContextS[color], points, numptS, CoordModeOrigin ) ; XDrawLines( dpyS, pixmapS, graphicContextS[color], points, numptS, CoordModeOrigin ) ; } } /* end drawDArb */ TWarb_fill( flag ) BOOL flag ; { fillArbS = flag ; } /* end TWarb_fill */ BOOL TWget_arb_fill() { return( fillArbS ) ; } /* end TWget_arb_fill */ TWrect_fill( flag ) BOOL flag ; { rect_fillS = flag ; } /* end TWrect_fill */ BOOL TWget_rect_fill() { return( rect_fillS ) ; } /* end TWget_rect_fill */ TWhighLightRect( x1,y1,x2,y2 ) /* draw a rectangle whose diagonals are (x1,y1) and (x2,y2) */ register INT x1,y1,x2,y2 ; { UNSIGNED_INT width, height ; /* first add data offset to move to relative to 0,0 */ x1 += xoffsetS ; x2 += xoffsetS ; y1 += yoffsetS ; y2 += yoffsetS ; /* next scale coordinates to window */ x1 = (INT) ( (DOUBLE) x1 * scaleFactorS ) ; x2 = (INT) ( (DOUBLE) x2 * scaleFactorS ) ; y1 = (INT) ( (DOUBLE) y1 * scaleFactorS ) ; y2 = (INT) ( (DOUBLE) y2 * scaleFactorS ) ; width = x2 - x1 ; height = y2 - y1 ; /* account for inversion of y axis */ y2 = winheightS - y2 ; XFillRectangle( dpyS,drawS,graphicContextS[HIGHLITE], x1,y2,width,height ) ; XFillRectangle( dpyS,pixmapS,graphicContextS[HIGHLITE], x1,y2,width,height ) ; } /* end TWhighLightRect */ TWmoveRect( x1, y1, x2, y2, ptx, pty ) INT *x1, *y1, *x2, *y2, ptx, pty ; /* x1, y1, x2, y2 are all user data absolute coordinates */ /* ptx and pty are the value of the pointer from TWgetPt */ { BOOL press ; /* tells whether button has been released */ XEvent event ; /* describes event */ long event_mask ; /* set events */ INT x, y ; /* current position of pointer */ INT last_time ; /* last time rectangle was moved */ INT dx_user, dy_user ; /* rect pos rel to pointer in user scale */ INT dx_pix, dy_pix ; /* rect pos rel to pointer in pixels */ INT oldx, oldy ; /* rect pos rel to pointer in pixels */ UNSIGNED_INT width_user ; /* width of rectangle user coordinates */ UNSIGNED_INT height_user; /* height of rectangle user coordinates */ UNSIGNED_INT width_pix ; /* width of rectangle pixel coordinates */ UNSIGNED_INT height_pix; /* height of rectangle pixel coordinates */ width_user = *x2 - *x1 ; dx_user = *x1 - ptx ; height_user = *y2 - *y1 ; dy_user = pty - *y2 ; /* note that y - axis is inverted */ ptx += xoffsetS ; pty += yoffsetS ; /* next scale coordinates to window */ ptx = (INT) ( (DOUBLE) ptx * scaleFactorS ) ; pty = (INT) ( (DOUBLE) pty * scaleFactorS ) ; width_pix = (INT) ( (DOUBLE) width_user * scaleFactorS ) ; height_pix = (INT) ( (DOUBLE) height_user * scaleFactorS ) ; dx_pix = (INT) ( (DOUBLE) dx_user * scaleFactorS ) ; dy_pix = (INT) ( (DOUBLE) dy_user * scaleFactorS ) ; /* account for inversion of y axis */ pty = winheightS - pty ; /* turn on event mask for main drawing window - known as wS */ event_mask = StructureNotifyMask | SubstructureNotifyMask | VisibilityChangeMask | ExposureMask | ButtonPressMask | PointerMotionMask ; XSelectInput(dpyS,drawS,event_mask); oldx = ptx ; oldy = pty ; /* draw rectangle at absolute coordinates */ XDrawRectangle( dpyS,drawS,graphicContextS[HIGHLITE], ptx+dx_pix,pty+dy_pix,width_pix,height_pix ) ; /* now look for either event - button press or keyboard */ press = FALSE ; last_time = 0 ; while(!(press )){ /* check for user input from mouse */ if( press = XCheckTypedWindowEvent( dpyS,drawS, ButtonPress,&event ) ){ /* we have an event from the pointer */ /* put event back on queue and call TWgetPt */ XPutBackEvent( dpyS, &event ) ; TWgetPt( &x, &y ) ; *x1 = x + dx_user ; *x2 = *x1 + width_user ; *y2 = y - dy_user ; /* - because of y axis inversion */ *y1 = *y2 - height_user ; } /* otherwise continue to loop */ /* move rectangle */ if( XCheckTypedWindowEvent( dpyS,drawS, MotionNotify,&event ) ){ /* avoid to many events to screen wait 50 msec.*/ if( event.xmotion.time - last_time < 50 ){ continue ; } last_time = event.xmotion.time ; x = event.xmotion.x ; y = event.xmotion.y ; /* draw rectangle at old position absolute coordinates */ XDrawRectangle( dpyS,drawS,graphicContextS[HIGHLITE], oldx+dx_pix,oldy+dy_pix,width_pix,height_pix ) ; XFillRectangle( dpyS,drawS,graphicContextS[HIGHLITE], oldx+dx_pix,oldy+dy_pix,width_pix,height_pix ) ; XDrawRectangle( dpyS,drawS,graphicContextS[HIGHLITE], x+dx_pix,y+dy_pix,width_pix,height_pix ) ; XFillRectangle( dpyS,drawS,graphicContextS[HIGHLITE], x+dx_pix,y+dy_pix,width_pix,height_pix ) ; oldx = x ; oldy = y ; XFlush( dpyS ) ; } } /* end while loop */ } /* end TWmoveRect */ XFontStruct *TWgetfont( fname, font ) char *fname ; Font *font ; { XFontStruct *fontinfo ; /* set font and get font info */ /* this is a safe test to see if font exists */ if(!(fontinfo = XLoadQueryFont( dpyS, fname ))){ sprintf( YmsgG, "font:%s not available - using default:fixed\n", fname ) ; M( ERRMSG,"TWgetfont", YmsgG ) ; fontinfo = XLoadQueryFont( dpyS, "fixed" ) ; } *font = fontinfo->fid ; return( fontinfo ) ; } /* end TWgetfont */ _TW3DdrawAxis( drawNotErase ) BOOL drawNotErase ; { INT xspan, yspan, zspan ; INT c ; /* string color */ INT xstring, ystring ; DOUBLE X0, Y0, X, Y ; xspan = rightS - leftS ; yspan = topS - bottomS ; zspan = MAX( xspan, yspan ) ; if( reverseS ){ if( drawNotErase ){ c = 1 ; /* white characters */ } else { /* erase */ c = 2 ; /* black background */ } } else { if( drawNotErase ){ c = 2 ; /* black characters */ } else { /* erase */ c = 1 ; /* white background */ } } /* there are 4 points of interest */ /* (0,0,0), (xspan,0,0), (0,yspan,0), (0,0,zspan) */ /* first (0,0,0) */ TW3Dperspective( (DOUBLE)0, (DOUBLE)0, (DOUBLE)0, &X0, &Y0 ); /* next (xspan,0,0) */ TW3Dperspective( (DOUBLE)xspan, (DOUBLE)0, (DOUBLE)0, &X, &Y ); /* draw X axis */ TWdrawLine(0, (INT)X0, (INT)Y0, (INT)X, (INT)Y, 3, NIL(char *) ) ; /* draw label - find label coordinates */ xstring = ( (INT) X0 + (INT) X ) DIV_2 ; ystring = ( (INT) Y0 + (INT) Y ) DIV_2 ; TWdrawString( xstring, ystring, c, "x" ) ; /* next (0,yspan,0) */ TW3Dperspective( (DOUBLE)0, (DOUBLE)yspan, (DOUBLE)0, &X, &Y ); /* draw X axis */ TWdrawLine(0, (INT)X0, (INT)Y0, (INT)X, (INT)Y, 3, NIL(char *) ) ; /* draw label - find label coordinates */ xstring = ( (INT) X0 + (INT) X ) DIV_2 ; ystring = ( (INT) Y0 + (INT) Y ) DIV_2 ; TWdrawString( xstring, ystring, c, "y" ) ; /* next (0,0,zspan) */ TW3Dperspective( (DOUBLE)0, (DOUBLE)0, (DOUBLE)zspan, &X, &Y ); /* draw X axis */ TWdrawLine(0, (INT)X0, (INT)Y0, (INT)X, (INT)Y, 3, NIL(char *) ) ; /* draw label - find label coordinates */ xstring = ( (INT) X0 + (INT) X ) DIV_2 ; ystring = ( (INT) Y0 + (INT) Y ) DIV_2 ; TWdrawString( xstring, ystring, c, "z" ) ; } /* end _TW3DdrawAxis */ VOID TW3DsetCamera() { INT x, y ; INT oldx, oldy ; BOOL first_time = TRUE ; DOUBLE FOURPI = 720; DOUBLE mouseScaleX ; DOUBLE mouseScaleY ; TWmouse_tracking_start() ; TWcolorXOR( 3, TRUE ) ; _TW3DdrawAxis( TRUE ) ; /* once across window scales to four pi radians */ mouseScaleX = FOURPI / (DOUBLE) (rightS - leftS) ; mouseScaleY = FOURPI / (DOUBLE) (topS - bottomS) ; while( !(TWmouse_tracking_end() )){ if( TWmouse_tracking_pt( &x, &y ) ){ /* draw the old one first */ _TW3DdrawAxis( FALSE ) ; if( first_time ){ oldx = x ; oldy = x ; first_time = FALSE ; continue ; } thetaS += ( x - oldx ) * radiansPerDegreeS * mouseScaleX; phiS += ( y - oldy ) * radiansPerDegreeS *mouseScaleY; /* sprintf(YmsgG, "Current settings: theta:%3d phi:%3d", (INT) (thetaS / radiansPerDegreeS), (INT) (phiS / radiansPerDegreeS) ) ; TWmessage(YmsgG) ; */ oldx = x ; oldy = y ; set_viewing_transformation(); /* now draw the new one */ _TW3DdrawAxis( TRUE ) ; } /* end check on whether coordinate changed */ } /* end mouse tracking loop */ TWcolorXOR( 3, FALSE ) ; /* translate to origin */ xoffsetS = 0 ; yoffsetS = 0 ; /* now center in screen - half of xspan */ xoffsetS += (INT) ( (DOUBLE) winwidthS / scaleFactorS / 2.0 ) ; yoffsetS += (INT) ( (DOUBLE) winheightS / scaleFactorS / 2.0 ); TWinforMenus() ; /* tell other module about info */ TWforceRedraw() ; _TW3DdrawAxis( TRUE ) ; } /* end TW3DsetCamera */ /*-------------------- --------------------*/ VOID TW3DperspectiveOn() { perspectiveS = TRUE; } /* end TW3DperspectiveOn */ /*-------------------- --------------------*/ VOID TW3DperspectiveOff() { perspectiveS = FALSE; } /* end TW3DperspectiveOff */ /*------------------ Initialize the transformation matrices ------------------*/ static VOID set_viewing_transformation() { DOUBLE cosine_of_theta; DOUBLE sine_of_theta; DOUBLE cosine_of_phi; DOUBLE sine_of_phi; if ( thetaS == acos( (double)0.0 ) && phiS == 0.0 ) { cosine_of_theta = 0.0; cosine_of_phi = 1.0; sine_of_theta = 1.0; sine_of_phi = 0.0; } else { cosine_of_theta = cos (thetaS); cosine_of_phi = cos (phiS); sine_of_theta = sin (thetaS); sine_of_phi = sin (phiS); } v11S = -sine_of_theta; v12S = -cosine_of_phi * cosine_of_theta; v13S = -sine_of_phi * cosine_of_theta; v21S = cosine_of_theta; v22S = -cosine_of_phi * sine_of_theta; v23S = -sine_of_phi * sine_of_theta; v32S = sine_of_phi; v33S = -cosine_of_phi; v43S = rhoS; } /* end set_viewing_transformation */ /*------------------ Perform a 3D transformation. ------------------*/ VOID TW3Dperspective(x, y, z, pX, pY) DOUBLE x, y, z; DOUBLE *pX, *pY; { DOUBLE x_eye, y_eye, z_eye; x = -x; y = -y; z = -z; x_eye = v11S * x + v21S * y; y_eye = v12S * x + v22S * y + v32S * z; z_eye = v13S * x + v23S * y + v33S * z + v43S; /* screen coordinates */ if (perspectiveS) { *pX = x_eye/z_eye; *pY = y_eye/z_eye; } else { *pX = x_eye / v43S; *pY = y_eye / v43S; } D("perspective", fprintf(stderr, "IN x:%-9.1f y:%-9.1f z:%-9.1f OUT x:%-9.1f y:%-9.1f\n", x,y,z,*pX,*pY ) ; ); } /* end perspective */ /* set the 3D translations to normal view */ VOID TW3Dnormal_view() { /* Sperical coordinates ? */ /* rho = distance to point */ /* theta = angle from x-axis on xy plane */ /* phi = angle from z-axis to line from point to origin */ /* the normal way to look at things from top */ thetaS = acos( (double) 0.0 ); phiS = 0.0 ; rhoS = 1.0 ; perspectiveS = FALSE; /* draw in perspective */ set_viewing_transformation() ; if( initS ){ TWforceRedraw() ; } /* done 3D initialization */ } /* end TW3Dnormal_view */ /*------------------------- Draws a 3 dimensional cube. -------------------------*/ INT TW3DdrawCube(ref_num, x1, y1, z1, x2, y2, z2, color, label) INT ref_num, x1, y1, z1, x2, y2, z2 ; INT color; char *label; { /* try it as a solid */ /* side face 1 */ TW3Darb_init() ; TW3Darb_addpt( x1, y1, z1 ) ; TW3Darb_addpt( x1, y1, z2 ) ; TW3Darb_addpt( x1, y2, z2 ) ; TW3Darb_addpt( x1, y2, z1 ) ; TW3DdrawArb( ref_num, color, NIL(char *) ) ; /* side face 2 */ TW3Darb_init() ; TW3Darb_addpt( x2, y1, z1 ) ; TW3Darb_addpt( x2, y1, z2 ) ; TW3Darb_addpt( x2, y2, z2 ) ; TW3Darb_addpt( x2, y2, z1 ) ; TW3DdrawArb( ref_num, color, NIL(char *) ) ; /* front face 3 */ TW3Darb_init() ; TW3Darb_addpt( x1, y1, z1 ) ; TW3Darb_addpt( x1, y1, z2 ) ; TW3Darb_addpt( x2, y1, z2 ) ; TW3Darb_addpt( x2, y1, z1 ) ; TW3DdrawArb( ref_num, color, NIL(char *) ) ; /* front face 4 */ TW3Darb_init() ; TW3Darb_addpt( x1, y2, z1 ) ; TW3Darb_addpt( x1, y2, z2 ) ; TW3Darb_addpt( x2, y2, z2 ) ; TW3Darb_addpt( x2, y2, z1 ) ; TW3DdrawArb( ref_num, color, NIL(char *) ) ; /* bottom face */ TW3Darb_init() ; TW3Darb_addpt( x1, y1, z1 ) ; TW3Darb_addpt( x1, y2, z1 ) ; TW3Darb_addpt( x2, y2, z1 ) ; TW3Darb_addpt( x2, y1, z1 ) ; TW3DdrawArb( ref_num, color, NIL(char *) ) ; /* top face */ TW3Darb_init() ; TW3Darb_addpt( x1, y1, z2 ) ; TW3Darb_addpt( x1, y2, z2 ) ; TW3Darb_addpt( x2, y2, z2 ) ; TW3Darb_addpt( x2, y1, z2 ) ; TW3DdrawArb( ref_num, color, label ) ; if( fillArbS ){ TW3DdrawLine(ref_num, x1, y1, z1, x2, y1, z1, 2, NIL(char *)); TW3DdrawLine(ref_num, x1, y1, z1, x1, y2, z1, 2, NIL(char *)); TW3DdrawLine(ref_num, x1, y1, z1, x1, y1, z2, 2, NIL(char *)); TW3DdrawLine(ref_num, x2, y2, z2, x1, y2, z2, 2, NIL(char *)); TW3DdrawLine(ref_num, x2, y2, z2, x2, y1, z2, 2, NIL(char *)); TW3DdrawLine(ref_num, x2, y2, z2, x2, y2, z1, 2, NIL(char *)); TW3DdrawLine(ref_num, x1, y2, z2, x1, y1, z2, 2, NIL(char *)); TW3DdrawLine(ref_num, x1, y2, z2, x1, y2, z1, 2, NIL(char *)); TW3DdrawLine(ref_num, x2, y2, z1, x1, y2, z1, 2, NIL(char *)); TW3DdrawLine(ref_num, x2, y1, z1, x2, y2, z1, 2, NIL(char *)); TW3DdrawLine(ref_num, x2, y1, z1, x2, y1, z2, 2, NIL(char *)); TW3DdrawLine(ref_num, x1, y1, z2, x2, y1, z2, 2, NIL(char *)); } } /* end TW3DdrawCube */ /* returns string size in user coordinate system */ TWstringSize( string, width, height ) char *string ; INT *width, *height ; { INT len ; /* length of string in characters */ INT pix_width ; /* width of string in pixels */ INT pix_height ; /* height of string in pixels */ len = strlen( string ) ; pix_width = XTextWidth( fontinfoS, string, len ) ; pix_height = fontinfoS->ascent + fontinfoS->descent ; /* now reverse scale of coordinates */ *width = (INT) ( (DOUBLE) pix_width / scaleFactorS ) ; *height = (INT) ( (DOUBLE) pix_height / scaleFactorS ) ; } TWdrawString( x, y, color, label ) INT x, y, color ; char *label ; { if( color <= 0 || color > numColorS ){ if( initS ){ /* graphics are available */ sprintf( YmsgG, "Color number:%d is out of range", color ) ; TWmessage( YmsgG ) ; } else { fprintf( stderr,"Color number:%d is out of range", color ) ; } return ; } else if(!(colorOnS[color])){ return ; } if(!(fullViewS)){ if(!(Yproject_intersect( x, x, y, y, lS, rS, bS, tS ) )){ return ; } } /* add users data offset */ /* next scale coordinates to window */ /* account for inversion of y axis */ x = (INT) ( (DOUBLE) (x + xoffsetS) * scaleFactorS ) ; y = winheightS - (INT) ( (DOUBLE) (y + yoffsetS) * scaleFactorS ) ; if( label ){ if( *label != EOS ){ XDrawImageString( dpyS, drawS, graphicContextS[color], x, y, label, strlen(label) ) ; XDrawImageString( dpyS, pixmapS, graphicContextS[color], x, y, label, strlen(label) ) ; } } } /* end TWdrawString */ /****************************************************************** END SCREEN GRAPHIC ROUTINES ******************************************************************* */ /*** STATIC DEFINIONS FOR WRITE ROUTINES ONLY ****/ static FILE *cellFileS = NULL ; /* cellfile pointer */ static FILE *netFileS = NULL ; /* net file pointer */ static FILE *symbFileS = NULL ; /* symbfile pointer */ static INT numCellS = 0 ; /* cell counter */ static INT numNetS = 0 ; /* net counter */ static INT numPinS = 0 ; /* pin counter */ static INT numCharS = 0 ; /* symbol table counter */ TWstartFrame() { char filename[LRECL] ; char dummy[5] ; UNSIGNED_INT nitems ; if(!(initS )){ fprintf(stderr,"ERROR[startNewFrame]:initialization was not" ) ; fprintf(stderr,"performed\n before calling startNewFrame\n" ) ; YexitPgm( NOINIT ) ; } switch( modeS ){ case TWDRAWONLY: startDFrame() ; return ; case TWWRITEONLY: break ; case TWWRITENDRAW: startDFrame() ; break ; } if(!dirNameS){ return ; } if( frameOpenS ){ closeFrame() ; } /* signal that frame is now open */ frameOpenS = TRUE ; /* now open next frame files */ /* increment frame count */ frameCountS++ ; /* first cell file */ sprintf( filename, "%s/cell.bin.%d", dirNameS, frameCountS ) ; cellFileS = TWOPEN( filename, "w", ABORT ) ; numCellS = 0 ; /* reset cell counter */ /* next net file */ sprintf( filename, "%s/net.bin.%d", dirNameS, frameCountS ) ; netFileS = TWOPEN( filename, "w", ABORT ) ; numNetS = 0 ; /* reset net counter */ /* next symb file */ sprintf( filename, "%s/symb.bin.%d", dirNameS, frameCountS ) ; symbFileS = TWOPEN( filename, "w", ABORT ) ; /* write a dummy character at start file makes test for label */ /* index easier since symbtable[0] is meaningless now. */ /* All indexes into symbol table which are valid must be positive */ dummy[0] = EOS ; nitems = (UNSIGNED_INT) 1 ; fwrite( dummy, sizeof(char), nitems, symbFileS ) ; numCharS = 1 ; /* reset symbol table counter */ } /* end startNewFrame */ /* write size of data at end of files and close them if frames are open */ static closeFrame() { char dummy[5] ; UNSIGNED_INT nitems ; INT numw ; INT excess ; if(!dirNameS){ return ; } /* check to see if other files are open */ if( frameOpenS ){ nitems = (UNSIGNED_INT) 1 ; /* terminate the file with number of records in each file */ numw = fwrite( &numCellS,sizeof(UNSIGNED_INT),nitems,cellFileS ) ; ASSERT( numw == 1, "startNewFrame", "Number written zero" ) ; numw = fwrite( &numNetS, sizeof(UNSIGNED_INT),nitems,netFileS ) ; ASSERT( numw == 1, "startNewFrame", "Number written zero" ) ; /* need to put on integer boundary */ if( excess = numCharS % 4 ){ /* pad the remainder with dummy */ nitems = (UNSIGNED_INT) (4 - excess ) ; numw = fwrite( dummy, sizeof(char), nitems, symbFileS ) ; ASSERT( numw == nitems,"startNewFrame","Number written zero"); } nitems = (UNSIGNED_INT) 1 ; numw = fwrite( &numCharS,sizeof(UNSIGNED_INT),nitems,symbFileS ) ; ASSERT( numw == 1, "startNewFrame", "Number written zero" ) ; /* files are open close them */ ASSERT( cellFileS, "startNewFrame", "cell file should be open" ) ; TWCLOSE( cellFileS ) ; ASSERT( netFileS, "startNewFrame", "net file should be open" ) ; TWCLOSE( netFileS ) ; ASSERT( symbFileS, "startNewFrame", "symb file should be open" ) ; TWCLOSE( symbFileS ) ; /* signal that frame has been closed */ frameOpenS = FALSE ; } } /* closeFrame */ TWsetFrame( number ) INT number ; { char fileName[LRECL] ; if(!dirNameS){ return ; } if( number <= 0 ){ /* search for the first valid file */ /* find max number of frames of data */ for( frameCountS=1;;frameCountS++ ){ sprintf( fileName,"%s/cell.bin.%d",dirNameS,frameCountS ) ; if(! (YfileExists(fileName) )){ /* last file successfully read is one less */ frameCountS-- ; break ; } } } else { frameCountS = number ; } } /* THE SPECIALIZED ROUTINES */ /* ********* GENERIC WRITE ROUTINES ************** */ /* draw a one pixel tall line segment from x1,y1 to x2,y2 */ static VOID drawWLine( ref_num,x1,y1,x2,y2,color,label) INT ref_num ; /* reference number */ INT x1,y1,x2,y2,color ; char *label; { DATABOX record ; UNSIGNED_INT nitems ; INT numw ; /* number written */ if(!(colorOnS[color]) || !dirNameS ){ return ; } /* check modes call draw functions if necessary */ switch( modeS ){ case TWDRAWONLY: /* this is an error should never call this */ fprintf( stderr,"ERROR[drawWPin]:problem with mode\n" ) ; return ; case TWWRITEONLY: break ; case TWWRITENDRAW: drawDLine( ref_num,x1,y1,x2,y2,color,label) ; break ; } /* fill up data record file destination net file */ record.ref = (UNSIGNED_INT) ref_num ; record.x1 = x1 ; record.x2 = x2 ; record.y1 = y1 ; record.y2 = y2 ; /* now take care of color */ record.color = color ; /* now store string in symbol table if given */ if( label ){ /* write string to symbol table file */ nitems = (UNSIGNED_INT) ( strlen( label ) + 1 ) ; numw = fwrite( label, sizeof(char), nitems, symbFileS ) ; ASSERT( numw == nitems, "drawLine", "Couldnt write to string table" ); /* now store in net file offset in table */ record.label = numCharS ; /* now update offset to include this string */ numCharS += (INT) nitems ; } else { record.label = 0 ; } /* now write record */ nitems = (UNSIGNED_INT) 1 ; numw = fwrite( &record, sizeof(DATABOX),nitems,netFileS ) ; ASSERT( numw == 1, "drawLine", "Record not written..." ) ; numNetS++ ; } /* end drawWLine */ /* draw a rectangle whose diagonals are (x1,y1) and (x2,y2) */ /* if the specified color is default or invalid, use default color */ static VOID drawWRect( ref_num, x1,y1,x2,y2,color,label) INT ref_num ; /* reference number */ INT x1,y1,x2,y2, color; char *label; { DATABOX record ; UNSIGNED_INT nitems ; INT numw ; /* number of records written */ if(!(colorOnS[color]) || !dirNameS ){ return ; } /* check modes call draw functions if necessary */ switch( modeS ){ case TWDRAWONLY: /* this is an error should never call this */ fprintf( stderr,"ERROR[drawWRect]:problem with mode\n" ) ; return ; case TWWRITEONLY: break ; case TWWRITENDRAW: drawDRect( ref_num,x1,y1,x2,y2,color,label) ; break ; } /* fill up data record file destination net file */ record.ref = (UNSIGNED_INT) ref_num ; record.x1 = x1 ; record.x2 = x2 ; record.y1 = y1 ; record.y2 = y2 ; record.color = color ; /* now store string in symbol table if given */ if( label ){ /* write string to symbol table file */ nitems = (UNSIGNED_INT) ( strlen( label ) + 1 ) ; numw = fwrite( label, sizeof(char), nitems, symbFileS ) ; ASSERT( numw == nitems, "drawWRect", "Couldn't write to string table" ); /* now store in net file offset in table */ record.label = numCharS ; /* now update offset to include this string */ numCharS += (INT) nitems ; } else { record.label = 0 ; } /* now write record */ nitems = (UNSIGNED_INT) 1 ; numw = fwrite( &record, sizeof(DATABOX),nitems,cellFileS ) ; numCellS++ ; ASSERT( numw == 1, "drawWRect", "Record not written..." ) ; } /* end drawWRect */ static VOID drawWArb( ref, color, label ) INT ref, color ; char *label ; { YBUSTBOXPTR bustptr ; if(!(colorOnS[color]) || !dirNameS ){ return ; } /* check modes call draw functions if necessary */ switch( modeS ){ case TWDRAWONLY: /* this is an error should never call this */ fprintf( stderr,"ERROR[drawWArb]:problem with mode\n" ) ; return ; case TWWRITEONLY: break ; case TWWRITENDRAW: drawDArb( ref, color, label ) ; break ; } while( bustptr = Ybuster() ){ /* l = bustptr[1].x ; */ /* r = bustptr[4].x ; */ /* b = bustptr[1].y ; */ /* t = bustptr[2].y ; */ TWdrawCell( ref, bustptr[1].x, bustptr[1].y, bustptr[4].x, bustptr[2].y, color, label ) ; } } /* end drawDArb */ #endif /* NOGRAPHICS */ /* ************************************************************** */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/dset.c000066400000000000000000000573761305746555600205770ustar00rootroot00000000000000/* * Copyright (C) 1991-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /*----------------------------------------------------------------- FILE: dset.c DESCRIPTION:disjoint set utility functions CONTENTS: DATE: Apr 26, 1991 REVISIONS: Original Version -WS Jun 91 - Hide one level of indirection from user -RAW Oct 91 - Changed type for stricter gcc -RAW Sun Dec 8 23:28:03 EST 1991 - removed indirection needed in comparison functions. Mon Dec 9 15:30:38 EST 1991 - added back the useful function - Ydset_enumerate_parents. Also now free all memory correctly. Tue Dec 10 01:46:21 EST 1991 added Ydset_interval and fixed problem with Ydset_enumerate_parents. Sun Dec 15 02:28:14 EST 1991 - added dset_dump_tree. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) dset.c version 1.13 2/3/92"; #endif #define YDSET_DEFS #include #include #include #include #include /* ********************** STRUCTURE DEFINITIONS ******************* */ typedef struct dset_element { VOIDPTR data ; INT rank ; INT size; struct dset_element *parent ; } ELEMENT, *ELEMENTPTR ; /* ***************** STATIC VARIABLE DEFINITIONS ******************* */ static YDSETPTR dsetS ; /* current dset info */ /* ***************** STATIC FUNCTION DEFINITIONS ******************* */ /*------------------------------------------------------------------------- This comparision function is used to eliminate the extra level of indirection in the users comparison function. --------------------------------------------------------------------------*/ static INT compare_dset( data1_p, data2_p ) ELEMENT *data1_p, *data2_p ; { return (*dsetS->compare_func)( data1_p->data, data2_p->data ) ; } /* end compare_dset() */ /*----------------------- -----------------------*/ static VOID dset_free_element( ptr ) ELEMENTPTR ptr; { /* first free the users data */ if( dsetS->user_delete) { (*dsetS->user_delete)(ptr->data); } /* then free the set element */ YFREE(ptr); } /* end dset_free_element() */ /* delete all the trees associated with set */ static dset_free_trees( dset ) YDSETPTR dset ; { if ( dset->superset_tree ) { Yrbtree_free(dset->superset_tree,NULL); dset->superset_tree = NIL(YTREEPTR) ; } if ( dset->subset_tree ) { Yrbtree_free(dset->subset_tree,NULL); dset->subset_tree = NIL(YTREEPTR) ; } if ( dset->parent_tree ) { Yrbtree_free(dset->parent_tree,NULL); dset->parent_tree = NIL(YTREEPTR) ; } } /* end dset_free_trees() */ /*--------------------------------------------------- compare parents ----------------------------------------------------*/ static INT compare_parents(p1,p2) ELEMENTPTR p1, p2 ; { return ( p1->parent - p2->parent ); } /*----------------------- -----------------------*/ static ELEMENTPTR path_compression( ptr ) ELEMENTPTR ptr ; { if( ptr != ptr->parent ){ ptr->parent = path_compression( ptr->parent ) ; } return( ptr->parent ) ; } /* end path_compression */ /*----------------------- -----------------------*/ static ELEMENTPTR link( x, y ) ELEMENTPTR x, y ; { if( x->rank > y->rank ){ y->parent = x ; x->size += y->size; } else { x->parent = y ; if( x->rank == y->rank ){ if (x!=y) { y->size += x->size; } y->rank++ ; } else { y->size += x->size; } } return(x->parent); } /* end link */ /*----------------------- -----------------------*/ static ELEMENTPTR find( dset, data ) YDSETPTR dset ; VOIDPTR data ; { ELEMENT test ; /* dummy record for comparison */ ELEMENTPTR ptr ; /* the found/new node in rbtree */ dsetS = dset ; test.data = data ; /* This section finds the dset data structure for the given data. If it doesn't exist it creates a new dset record. */ if( ! (ptr = (ELEMENTPTR) Yrbtree_search( dset->dtree, &test ) ) ) { /* create a new element */ ptr = YMALLOC( 1, ELEMENT ) ; ptr->data = data ; ptr->parent = ptr ; /* self index initially */ ptr->rank = 0 ; ptr->size = 1 ; Yrbtree_insert( dset->dtree, ptr ) ; return( ptr ) ; } /* Now that we have the dset data structure, compress the path */ ptr = path_compression( ptr ) ; return( ptr ) ; } /* end find */ /*---------------------------------------------- dset_find_set Same as dset_find except avoid call to make set ----------------------------------------------*/ static ELEMENTPTR dset_find_set( dset, data ) YDSETPTR dset ; VOIDPTR data ; { ELEMENT dummy ; ELEMENTPTR ptr ; dsetS = dset ; dummy.data = data; if( ptr = (ELEMENTPTR) Yrbtree_search( dset->dtree, &dummy )){ ptr = path_compression(ptr); } return( ptr ) ; } /* dset_find_set */ /* ***************** end STATIC functions ******************* */ /* ***************** USER functions ******************* */ /*--------------------------------------------------------------------- Ydset_init() NOTE that the users comparison function will be passed handles rather then pointers. Thus, the user comparison function must do an added level of indirection ---------------------------------------------------------------------*/ YDSETPTR Ydset_init( compare_func ) INT (*compare_func)() ; { YDSETPTR dset ; /* in reality this is a YTREEPTR not anymore! */ dset = YMALLOC( 1, YDSETBOX ) ; dset->dtree = Yrbtree_init( compare_dset ); dset->compare_func = compare_func ; dset->superset_tree = NIL(YTREEPTR) ; dset->subset_tree = NIL(YTREEPTR) ; dset->parent_tree = NIL(YTREEPTR) ; return( dset ) ; } /* end Ydset_init */ /*----------------------------------- Ydset_enumerate enumerate all elements in all sets -----------------------------------*/ VOIDPTR Ydset_enumerate( dset , startFlag ) YDSETPTR dset; BOOL startFlag; { ELEMENTPTR ptr ; D("Ydset_enumerate", fprintf(stderr,"start Ydset_enumerate\n"); ); dsetS = dset ; ptr = (ELEMENTPTR) Yrbtree_enumerate( dset->dtree, startFlag ); D("Ydset_enumerate", fprintf(stderr,"end Ydset_enumerate\n"); ); if( ptr ) { return( ptr->data ) ; } else { return ( NIL(VOIDPTR) ); } } /* end Ydset_enumerate() */ /*----------------------- Ydset_enumerate_superset Enumerates all the elements of all subsets . Items are sorted by set, so all elements of each set will be returned together. -----------------------*/ /*** Enumerates all the elements of the whole superset ***/ VOIDPTR Ydset_enumerate_superset( dset , startFlag ) YDSETPTR dset ; BOOL startFlag; { ELEMENTPTR ptr ; YTREEPTR dtree ; D("Ydset_enumerate_superset", fprintf(stderr,"start Ydset_enumerate_superset\n"); ); dtree = dset->dtree ; if ( startFlag ) { if ( dset->superset_tree ) { Yrbtree_free(dset->superset_tree,NULL); } dset->superset_tree = Yrbtree_init(compare_parents); /* sort elements by set */ Yrbtree_enumeratePush(dtree); for ( ptr = (ELEMENTPTR)Yrbtree_enumerate( dtree, TRUE); ptr; ptr = (ELEMENTPTR)Yrbtree_enumerate( dtree, FALSE) ) { /* compress path so everyone will point to same parent */ path_compression( ptr ) ; /* compress the path */ Yrbtree_insert(dset->superset_tree,ptr); } Yrbtree_enumeratePop(dtree); ASSERTNFAULT(Yrbtree_size(dset->superset_tree) == Yrbtree_size(dtree), "Ydset_enumerate_superset","bogus superset sizes"); } /* end if start flag */ ptr = (ELEMENTPTR)Yrbtree_enumerate( dset->superset_tree, startFlag); D("Ydset_enumerate_superset", fprintf(stderr,"end Ydset_enumerate_superset\n"); ); if (ptr) { return ( ptr->data ); } return ( NIL(VOIDPTR) ); } /* end Ydset_enumerate_superset() */ /*---------------------------------- Returns the parents of each subset ----------------------------------*/ /*** Enumerates the parents of each subset ***/ VOIDPTR Ydset_enumerate_parents( dset , startFlag ) YDSETPTR dset ; BOOL startFlag; { ELEMENTPTR ptr ; YTREEPTR dtree ; D("Ydset_enumerate_parents", fprintf(stderr,"start Ydset_enumerate_parents\n"); ); dtree = dset->dtree ; if ( startFlag ) { if ( dset->parent_tree ) { Yrbtree_free(dset->parent_tree,NULL); } dset->parent_tree = Yrbtree_init(compare_parents); /* sort elements by set */ Yrbtree_enumeratePush(dtree); for ( ptr = (ELEMENTPTR)Yrbtree_enumerate( dtree, TRUE); ptr; ptr = (ELEMENTPTR)Yrbtree_enumerate( dtree, FALSE) ) { /* compress path so everyone will point to same parent */ ptr = path_compression( ptr ) ; /* compress the path */ /* only add to tree if it is a unique parent */ if(!(Yrbtree_search( dset->parent_tree, ptr ))){ Yrbtree_insert(dset->parent_tree,ptr); } } Yrbtree_enumeratePop(dtree); } /* end if start flag */ ptr = (ELEMENTPTR)Yrbtree_enumerate( dset->parent_tree, startFlag); D("Ydset_enumerate_parents", fprintf(stderr,"end Ydset_enumerate_parents\n"); ); if (ptr) { return ( ptr->data ); } return ( NIL(VOIDPTR) ); } /* end Ydset_enumerate_parents() */ /*----------------------------------------------------- Ydset_enumerate_subset Enumerates all the elements of a subset. Items are sorted by set, so all elements of each set will be returned together. ------------------------------------------------------*/ VOIDPTR Ydset_enumerate_subset( dset , subsetData, startFlag ) YDSETPTR dset ; VOIDPTR subsetData; BOOL startFlag; { ELEMENTPTR parent ; ELEMENTPTR ptr ; YTREEPTR dtree ; D("Ydset_enumerate_subset", fprintf(stderr,"start Ydset_enumerate_subset\n"); ); if ( startFlag ) { if ( dset->subset_tree ) { Yrbtree_free(dset->subset_tree,NULL); } dset->subset_tree = Yrbtree_init(compare_parents); Ydset_find(dset,subsetData); /* compress the path */ parent = dset_find_set(dset,subsetData); /* find parent of subset */ /* build a tree of all elements in the same set as subsetData */ /* this means they have the same parent */ dtree = dset->dtree ; Yrbtree_enumeratePush(dtree); for ( ptr = (ELEMENTPTR)Yrbtree_enumerate( dtree, TRUE); ptr; ptr = (ELEMENTPTR)Yrbtree_enumerate( dtree, FALSE) ) { path_compression( ptr ) ; /* compress the path */ if ( ptr->parent == parent ) { Yrbtree_insert(dset->subset_tree,ptr); } } Yrbtree_enumeratePop(dtree); } /* end if start flag */ ptr = (ELEMENTPTR)Yrbtree_enumerate( dset->subset_tree, startFlag); D("Ydset_enumerate_subset", fprintf(stderr,"end Ydset_enumerate_subset\n"); ); if (ptr) { return ( ptr->data ); } return ( NIL(VOIDPTR) ); } /* end Ydset_enumerate_subset */ /*----------------------- Ydset_search -----------------------*/ /* Searches for an item in the set basically like rbtree_search works ; avoids makeset of the item which Ydset_find does by default. Does not do path compression. Good if no unions have been performed (during initialization) and interested in making all elements of the set unique. */ VOIDPTR Ydset_search( dset, data ) YDSETPTR dset ; VOIDPTR data ; { ELEMENT dummy ; ELEMENTPTR ptr ; dsetS = dset ; dummy.data = data; if( ptr = (ELEMENTPTR) Yrbtree_search( dset->dtree, &dummy )){ return( ptr->data ) ; } return( NIL(VOIDPTR) ) ; } /* Ydset_search */ /*------------------------------------------------------------- Ydset_free Free all elements in the set and the set. This can now be used recursively. --------------------------------------------------------------*/ VOID Ydset_free( dset , userDelete) YDSETPTR dset ; VOID (*userDelete)(); { dsetS = dset ; dsetS->user_delete = userDelete ; Yrbtree_free(dset->dtree,dset_free_element); dset_free_trees( dset ) ; YFREE( dset ) ; } /* end Ydset_free */ /*------------------------------------------------------------ Ydset_empty Free all elements in the set but leaves the set intact -------------------------------------------------------------*/ VOID Ydset_empty( dset , userDelete) YDSETPTR dset ; VOID (*userDelete)(); { dsetS = dset ; dsetS->user_delete = userDelete ; Yrbtree_empty(dset->dtree,dset_free_element); dset_free_trees( dset ) ; if ( dset->superset_tree ) { Yrbtree_free(dset->superset_tree,NULL); dset->superset_tree = NIL(YTREEPTR) ; } if ( dset->subset_tree ) { Yrbtree_free(dset->subset_tree,NULL); dset->subset_tree = NIL(YTREEPTR) ; } if ( dset->parent_tree ) { Yrbtree_free(dset->parent_tree,NULL); dset->parent_tree = NIL(YTREEPTR) ; } } /* end Ydset_empty */ /*----------------------- -----------------------*/ VOIDPTR Ydset_union( dset, x, y ) YDSETPTR dset ; VOIDPTR x, y ; { ELEMENTPTR p1, p2, p3 ; D("Ydset_union", fprintf(stderr,"start Ydset_union size = %d\n",Yrbtree_size(dset->dtree)); ); p1 = find( dset, x ) ; ASSERT( p1, "Ydset_union", "Problem with finding x\n" ) ; p2 = find( dset, y ) ; ASSERT( p2, "Ydset_union", "Problem with finding y\n" ) ; /* if p1 == p2 then we are already done */ if ( p1 != p2 ) { p3 = link( p1, p2 ); } else { p3 = p1; } D("Ydset_union", fprintf(stderr,"end Ydset_union size = %d\n",Yrbtree_size(dset->dtree)); ); return( p3->data ); } /* end Ydset_union */ /*------------------------------------------------- Ydset_find_set() Searches for the set an item belongs to. This routine avoids makeset of the item which Ydset_find does by default -------------------------------------------------*/ VOIDPTR Ydset_find_set( dset, data ) YDSETPTR dset ; VOIDPTR data ; { ELEMENTPTR ptr ; if (ptr = dset_find_set(dset, data) ) { return( ptr->data ) ; } return( NIL(VOIDPTR) ) ; } /* Ydset_find */ /*------------------------------------------------- Ydset_find Returns the set to which data is an element If the element is any set, a set is created --------------------------------------------------*/ VOIDPTR Ydset_find( dset, data ) YDSETPTR dset ; VOIDPTR data ; { ELEMENTPTR ptr ; if( ptr = find( dset, data )){ return( ptr->data ) ; } return( NIL(VOIDPTR) ) ; } /* end Ydset_find */ /*----------------------- -----------------------*/ INT Ydset_superset_size(dset) YDSETPTR dset ; { return(Yrbtree_size(dset->dtree)); } /* end Ydset_superset_size */ /*----------------------- -----------------------*/ INT Ydset_subset_size( dset, data ) YDSETPTR dset ; VOIDPTR data ; { ELEMENT dummy ; ELEMENTPTR ptr ; if (dset){ dsetS = dset ; dummy.data = data; if( ptr = (ELEMENTPTR)Yrbtree_search( dset->dtree, &dummy )){ return( ptr->parent->size ) ; } else { M(ERRMSG,"Ydset_subset_size","Problem with finding data sent\n"); } } else { M(ERRMSG,"Ydset_subset_size","NULL dset pointer (super set)\n"); } return (-1); } /* end Ydset_subset_size */ /*----------------------- Ydset_verify -----------------------*/ INT Ydset_verify( dset ) YDSETPTR dset ; { ELEMENTPTR ptr ; INT sizeIn; INT sizeOut; INT rc = TRUE; YTREEPTR dtree ; dsetS = dset ; dtree = dset->dtree ; sizeIn = Ydset_superset_size(dset); /* exercise the dset tree */ if ( !Yrbtree_verify(dtree) ) { M(ERRMSG,"Ydset_verify","dset tree verify failed\n"); rc = FALSE; } Yrbtree_enumeratePush(dtree); /* walk through all elements user find routines to recover itself */ for ( ptr = (ELEMENTPTR)Yrbtree_enumerate( dtree, TRUE); ptr; ptr = (ELEMENTPTR)Yrbtree_enumerate( dtree, FALSE) ) { if ( YcheckDebug(ptr) < sizeof(ELEMENT) ) { M(ERRMSG,"Ydset_verify","corrupt element memory\n"); rc = FALSE; } } Yrbtree_enumeratePop(dtree); sizeOut = Ydset_superset_size(dset); /* make sure the size has not changed, this tell us if makeset is called */ if ( sizeIn != sizeOut ) { fprintf(stderr,"sizeIn:%d sizeOut:%d\n",sizeIn,sizeOut); M(ERRMSG,"Ydset_verify","dset size changed during verification\n"); rc = FALSE; } return( rc ); } /* end Ydset_verify() */ /*------------------------ Ydset_dump ------------------------*/ Ydset_dump(dset,printFunc) YDSETPTR dset; VOID (*printFunc)(); { VOIDPTR ptr ; INT count = 1; ELEMENTPTR lastParent; ELEMENTPTR parent; ELEMENT dummy; D("Ydset_dump", fprintf(stderr,"start Ydset_dump\n"); ); if ( !printFunc ) { M(WARNMSG,"Ydset_dump","NULL print function\n"); } lastParent = &dummy; /* dump elements by set */ fprintf(stderr,"set contains %d items\n",Yrbtree_size(dset->dtree)); for ( ptr = (VOIDPTR)Ydset_enumerate_superset( dset, TRUE); ptr; ptr = (VOIDPTR)Ydset_enumerate_superset( dset, FALSE) ) { parent = dset_find_set( dset,ptr ); if ( parent != lastParent ) { fprintf(stderr,"\n%d items in set #%d [parent ",parent->size,count++); if ( printFunc ) { (*printFunc)(parent); } else { fprintf(stderr,"%ld ",parent); } fprintf(stderr,"]:\n" ) ; } if ( printFunc ) { (*printFunc)(ptr); } else { fprintf(stderr,"%ld ",ptr); } lastParent = parent; } fprintf(stderr,"\n"); D("Ydset_dump", fprintf(stderr,"end Ydset_dump\n"); ); } /* end Ydset_dump() */ /*----------------------------------- Ydset_interval enumerate all elements in the superset within an interval. -----------------------------------*/ VOIDPTR Ydset_interval( dset, low_key, high_key, startFlag ) YDSETPTR dset; VOIDPTR low_key, high_key ; BOOL startFlag; { ELEMENTPTR ptr ; D("Ydset_interval", fprintf(stderr,"start Ydset_interval\n"); ); dsetS = dset ; /* note we have to take address here because we will do dereferencing later */ ptr = (ELEMENTPTR) Yrbtree_interval( dset->dtree, &low_key, &high_key, startFlag ); D("Ydset_interval", fprintf(stderr,"end Ydset_interval\n"); ); if( ptr ) { return( ptr->data ) ; } else { return ( NIL(VOIDPTR) ); } } /* end Ydset_interval() */ /*------------------------ Ydset_dump_tree ------------------------*/ Ydset_dump_tree(dset,print_key) YDSETPTR dset; VOID (*print_key)(); { VOIDPTR ptr ; INT count = 1; ELEMENTPTR lastParent; ELEMENTPTR parent; ELEMENT dummy; D("Ydset_dump_tree", fprintf(stderr,"start Ydset_dump_tree\n"); ); if ( !print_key ) { M(WARNMSG,"Ydset_dump_tree","NULL print function\n"); } dsetS = dset ; Yrbtree_dump( dset->dtree, print_key ) ; D("Ydset_dump_tree", fprintf(stderr,"end Ydset_dump_tree\n"); ); } /* end Ydset_dump_tree() */ /* Ydset_interval push and pop are also possible... Implement when we need them....Just call Yrbtree push and pop. */ /* ********************* TEST PROGRAM ************************ */ #ifdef TEST static INT Ydset_compare_set( num1, num2 ) INT num1, num2 ; { if( num1 == num2 ){ return( 0 ) ; } else if( num1 < num2 ){ return( -1 ) ; } else { return( 1 ) ; } } /* end Ydset_compare_set */ static VOID print_data( num ) INT num ; { fprintf( stderr, " %d", num ) ; } /* end print_data() */ static VOID my_delete( num ) INT num ; { fprintf( stderr, "deleting %d\n", num ) ; } /* my_delete() */ main() { YDSETPTR set , new; INT i, j, q ; YdebugMemory( TRUE ) ; /* initialize master set */ set = Ydset_init( Ydset_compare_set ) ; /* first make 10 nodes */ for( i = 1; i <= 10; i++ ){ q = (INT) Ydset_find( set, (VOIDPTR) i ) ; fprintf( stderr, "find:%d = %d ...\n", i, q ) ; } Ydset_union( set, (VOIDPTR) 1, (VOIDPTR) 2 ) ; fprintf( stderr, "1 belongs to %d\n", Ydset_find( set, (VOIDPTR) 1 )) ; printf("%d\n",Ydset_superset_size( set )); Ydset_union( set, (VOIDPTR) 3, (VOIDPTR) 1 ) ; Ydset_union( set, (VOIDPTR) 2, (VOIDPTR) 3 ) ; Ydset_union( set, (VOIDPTR) 5, (VOIDPTR) 6 ) ; Ydset_union( set, (VOIDPTR) 7, (VOIDPTR) 6 ) ; printf("%d\n",Ydset_superset_size( set )); q = (INT) Ydset_find( set, (VOIDPTR) 6 ) ; /* lets look at everyone in 6's set */ fprintf( stderr, "\nThe members in 6's set are:\n" ) ; for( q = (INT) Ydset_enumerate_subset( set, (VOIDPTR) 6, TRUE ) ; q ; q = (INT) Ydset_enumerate_subset( set, (VOIDPTR) 6, FALSE ) ){ fprintf( stderr, "%d ", q ) ; } /* end */ fprintf( stderr, "\n" ) ; fprintf( stderr, "Six's parent is:%d\n", (INT) Ydset_find_set( set, (VOIDPTR) 6 ) ) ; fprintf( stderr, "The size of the set 6 is in is:%d\n", Ydset_subset_size( set, (VOIDPTR) 6 ) ) ; printf("%d\n",Ydset_superset_size( set )); printf("%d\n",Ydset_enumerate( set , TRUE)); printf("%d\n",Ydset_enumerate( set , FALSE)); printf("%d\n",Ydset_enumerate( set , FALSE)); printf("%d\n",Ydset_enumerate( set , FALSE)); printf("%d\n",Ydset_enumerate( set , FALSE)); printf("%d\n",Ydset_enumerate( set , FALSE)); i = 1 ; q = (INT) Ydset_find( set, (VOIDPTR) i ) ; fprintf( stderr, "find_after union:%d = %d ...\n", i, q ) ; i = 2 ; q = (INT) Ydset_find( set, (VOIDPTR) i ) ; fprintf( stderr, "find_after union:%d = %d ...\n", i, q ) ; i = 3 ; q = (INT) Ydset_find( set, (VOIDPTR) i ) ; fprintf( stderr, "find_after union:%d = %d ...\n", i, q ) ; i = 11 ; Ydset_union( set, (VOIDPTR) 11, (VOIDPTR) 1 ) ; q = (INT) Ydset_find( set, (VOIDPTR) i ) ; fprintf( stderr, "find_after union:%d = %d ...\n", i, q ) ; /* now lets look at the parents of all the sets */ fprintf( stderr, "\nThe parents of the sets are:\n" ) ; for( q = (INT) Ydset_enumerate_parents( set, TRUE ) ; q ; q = (INT) Ydset_enumerate_parents( set, FALSE ) ){ fprintf( stderr, "%d ", q ) ; } /* end */ fprintf( stderr, "\n" ) ; fprintf( stderr, "\nThe enumeration using superset:\n" ) ; for( q = (INT) Ydset_enumerate_superset( set, TRUE ) ; q ; q = (INT) Ydset_enumerate_superset( set, FALSE ) ){ fprintf( stderr, "%d ", q ) ; } /* end */ fprintf( stderr, "\n" ) ; fprintf( stderr, "\nUse enumerate parents and subset to mimic a dump\n" ) ; for( q = (INT) Ydset_enumerate_parents( set, TRUE ) ; q ; q = (INT) Ydset_enumerate_parents( set, FALSE ) ){ for( j = (INT) Ydset_enumerate_subset( set, (VOIDPTR) q, TRUE ) ; j ; j = (INT) Ydset_enumerate_subset( set, (VOIDPTR) q, FALSE ) ){ fprintf( stderr, "%d ", j ) ; } /* end */ fprintf( stderr, "\n" ) ; } /* end */ fprintf( stderr, "Memory use:%d\n", YgetCurMemUse() ) ; Ydset_dump(set,print_data) ; Ydset_empty( set , my_delete ) ; fprintf( stderr, "Memory use:%d\n", YgetCurMemUse() ) ; Ydset_dump(set,print_data) ; Ydset_free( set , my_delete ) ; fprintf( stderr, "Memory use:%d\n", YgetCurMemUse() ) ; Ydump_mem() ; } /* end main */ #endif /* TEST */ /* ******************** END TEST PROGRAM ************************ */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/edcolors.c000066400000000000000000000132351305746555600214340ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: edcolors.c DESCRIPTION:These routines allow user to toggle colors of the display. CONTENTS: TWtoggleColors() DATE: Sep 23, 1989 - added TWtoggleColors() REVISIONS: Dec 7, 1990 - updated for new dialog procedure. Wed May 1 18:56:14 EDT 1991 - added toggle for arb fill. Sun Nov 3 12:52:21 EST 1991 - fixed gcc complaints. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) edcolors.c (Yale) version 1.8 12/15/91" ; #endif #ifndef NOGRAPHICS #include #include #include #include #include #include #include #include #include #include "info.h" static TWDIALOGPTR fieldS ; static init_field( P8(INT field, INT row, INT column, INT str_len, char *string, INT type, INT color, INT group ) ) ; /* be able to turn off individual colors */ TWtoggleColors() { char **colors ; /* the standard color array */ INT i ; /* counter */ INT numfields ; /* number of dialog fields */ INT numcolors ; /* the number of colors in color array */ INT row ; /* current row of dialog */ INT group ; /* current case group of dialog */ INT color ; /* current color processed */ INT field ; /* current field of dialog */ BOOL *colorOn ; /* whether each color is on */ TWDIALOGPTR fptr; /* current field of dialog */ TWDRETURNPTR answer ; /* return from user */ TWINFOPTR info ; /* get information from main draw routine */ /* get colors for dialog window */ info = TWgetDrawInfo() ; colors = info->colors ; numcolors = info->numColors ; colorOn = info->colorOn ; numfields = 3 * numcolors + 7 ; fieldS = YCALLOC( numfields, TWDIALOGBOX ) ; /* set the accept and reject fields */ /* field, row, column, strlen, string, type, color, group */ init_field( 0, 1, 5, 8, " ACCEPT ", BUTTONTYPE, TWGREEN, 0 ) ; init_field( 1, 1,30, 8, " REJECT ", BUTTONTYPE, TWRED, 0 ) ; if( TWget_arb_fill() ){ init_field( 2, 3, 5, 9, "Arb Fill:" , CASETYPE, TWBLACK, 3 ) ; } else { init_field( 2, 3, 5, 9, "Arb Fill:" , CASETYPE, TWBLACK, 4 ) ; } init_field( 3, 3, 30, 3, "on", BUTTONTYPE, TWGREEN, 1 ) ; init_field( 4, 3, 35, 3, "off", BUTTONTYPE, TWRED, 1 ) ; init_field( 5, 4, 1, 7, "Colors:" , LABELTYPE, TWBLACK, 0 ) ; row = 5 ; group = 1 ; for( i = 1, field = 5; i <= numcolors; i++ ){ field++ ; if( i == 1 ){ /* white - change to black 2 */ color = 2 ; } else { color = i ; } /* set current initial switch position */ if( colorOn[i] ){ init_field( field, ++row, 5, 5, colors[i], CASETYPE, color, field+1 ) ; } else { init_field( field, ++row, 5, 5, colors[i], CASETYPE, color, field+2 ) ; } init_field( ++field, row, 30, 3, "on", BUTTONTYPE, color, ++group ) ; init_field( ++field, row, 35, 3, "off", BUTTONTYPE, color, group ) ; } /* terminate list with zeros */ init_field( ++field, 0, 0, 0, 0, 0, 0, 0 ) ; /* initialization complete */ if( answer = TWdialog( fieldS, "colors", NULL ) ){ if( answer[3].bool ){ TWarb_fill( TRUE ) ; } else { TWarb_fill( FALSE ) ; } for( i = 7, color = 0; i < numfields; i +=3 ){ if( answer[i].bool ){ colorOn[++color] = TRUE ; } else { colorOn[++color] = FALSE ; } } } /* cleanup memory */ for( i = 0; i < numfields; i++ ){ if( fieldS[i].string ){ YFREE( fieldS[i].string ) ; } } YFREE( fieldS ) ; } /* end TWtoggleColors */ static init_field( field, row, column, str_len, string, type, color, group ) INT field, row, column, str_len, type, color, group ; char *string ; { TWDIALOGPTR fptr; /* current field of dialog */ fptr = &(fieldS[field]) ; fptr->row = row ; fptr->column = column ; fptr->len = str_len ; fptr->type = type ; fptr->color = color ; fptr->group = group ; fptr->string = Ystrclone( string ) ; } /* end init_field */ #endif /* NOGRAPHICS */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/file.c000066400000000000000000000200021305746555600205270ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: file.c DESCRIPTION:miscellaneous file utility functions CONTENTS: FILE *YopenFile(char *,char *,int) BOOL YfileExists(char *) BOOL YdirectoryExists(pathname) char *pathname ; DATE: Jan 29, 1988 REVISIONS: May 04, 1988 - updated initProgram to include introTextFunction. Added remove_lblanks, directoryExists functions. Sep 26, 1988 - split utils.c into three pieces for archive. Jan 26, 1989 - changed directoryExists from macro to routine. Apr 27, 1989 - changed to Y prefix. Aug 28, 1989 - changed YfileExists to use stat functions instead of kludge fopen call. Fri Feb 22 23:38:59 EST 1991 - added locking functions. Tue Mar 12 16:57:30 CST 1991 - modified lock function to work on apollo - now a level 2 function. Thu Apr 18 00:37:52 EDT 1991 - fixed file descriptor. Sun Apr 21 21:21:21 EDT 1991 - added Yfile_slink. Sat May 11 22:53:09 EDT 1991 - added a conditional compile for HPUX. Oct 07, 1991 - fix #include sys/dir.h for SYS5 A/UX (RAWeier) Oct 18, 1991 - change INT to BOOL in YopenFile (RAWeier) ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) file.c version 3.11 10/20/91" ; #endif #include #include #include #include #define SERROR 0 /* ----------------------------------------------------------------- File routines */ FILE *YopenFile(filename,readwrite,abort) char *filename ; char *readwrite ; BOOL abort ; { FILE *fileptr ; fileptr = fopen( filename, readwrite ); if( !(fileptr) && abort ){ sprintf( YmsgG,"could not open file %s\n",filename ) ; M(ERRMSG,"openFile",YmsgG ) ; YexitPgm(PGMFAIL) ; } return( fileptr ) ; } /* end openFile */ #include #include /* check if a file exists */ BOOL YfileExists(pathname) char *pathname ; { struct stat buf; if( pathname ){ if( stat(pathname, &buf) == 0 ){ return(TRUE) ; } } return(FALSE) ; } char *Yfile_slink( pathname ) char *pathname ; { INT len ; static char buf[BUFSIZ] ; len = readlink( pathname, buf, BUFSIZ ) ; if( len <= SERROR ){ sprintf( YmsgG, "ERROR[Yfile_slink]:%s", pathname ) ; perror( YmsgG ) ; Ymessage_error_count() ; return(NIL(char *)) ; } else { /* null terminate string */ buf[len] = EOS ; return( buf ) ; } } /* end Yfile_slink */ #include /* check if a directory exists */ BOOL YdirectoryExists(pathname) char *pathname ; { DIR *dp ; if( pathname ){ if( dp = opendir(pathname) ){ closedir(dp) ; return(TRUE) ; } } return(FALSE) ; } #ifndef HPUX #include FILE *Yfile_create_lock( filename, readNotWrite ) char *filename ; BOOL readNotWrite ; { INT fd ; /* file descriptor */ INT status ; /* return status */ FILE *fp ; /* file stream descriptor */ if(!(YfileExists(filename))){ /* short cut to avoid having to chmod file */ fp = YopenFile( filename, "w", ABORT ) ; fclose( fp ) ; } if( readNotWrite ){ fd = creat( filename, O_RDONLY ) ; } else { fd = creat( filename, O_WRONLY ) ; } if( fd <= 0 ){ perror( "Yfile_create_lock" ) ; sprintf( YmsgG,"could not open file %s\n",filename ) ; M(ERRMSG,"Yfile_create_lock",YmsgG ) ; YexitPgm(PGMFAIL) ; } status = flock( fd, LOCK_EX | LOCK_NB ) ; if( status != 0 ){ sprintf( YmsgG,"could not lock file %s\n",filename ) ; M(ERRMSG,"Yfile_create_lock",YmsgG ) ; YexitPgm(PGMFAIL) ; } /* now if we get this far find file descriptor */ if( readNotWrite ){ fp = fdopen( fd, "r" ) ; } else { fp = fdopen( fd, "w" ) ; } if(!(fp)){ perror( "Yfile_create_lock" ) ; sprintf( YmsgG,"could not get file descriptor %s\n",filename ) ; M(ERRMSG,"Yfile_create_lock",YmsgG ) ; YexitPgm(PGMFAIL) ; } return( fp ) ; } /* end Yfile_create_lock */ /* see a file is locked */ BOOL Yfile_test_lock( filename ) char *filename ; { INT fd ; /* file descriptor */ INT status ; /* return status */ if(!(YfileExists(filename))){ /* file does not exist */ return( FALSE ) ; } fd = open( filename, O_RDONLY, 0 ) ; if( fd <= 0 ){ sprintf( YmsgG,"could not open file %s\n",filename ) ; M(ERRMSG,"Yfile_test_lock",YmsgG ) ; YexitPgm(PGMFAIL) ; } status = flock( fd, LOCK_EX | LOCK_NB ) ; if( status != 0 ){ return( TRUE ) ; } else { return( FALSE ) ; } } /* end Yfile_test_lock */ #else /* HPUX */ #include #include FILE *Yfile_create_lock( filename, readNotWrite ) char *filename ; BOOL readNotWrite ; { INT fd ; /* file descriptor */ INT status ; /* return status */ FILE *fp ; /* file stream descriptor */ if(!(YfileExists(filename))){ /* short cut to avoid having to chmod file */ fp = YopenFile( filename, "w", ABORT ) ; fclose( fp ) ; } if( readNotWrite ){ fd = creat( filename, O_RDONLY ) ; } else { fd = creat( filename, O_WRONLY ) ; } if( fd <= 0 ){ perror( "Yfile_create_lock" ) ; sprintf( YmsgG,"could not open file %s\n",filename ) ; M(ERRMSG,"Yfile_create_lock",YmsgG ) ; YexitPgm(PGMFAIL) ; } status = lockf( fd, F_LOCK, 0 ) ; if( status != 0 ){ sprintf( YmsgG,"could not lock file %s\n",filename ) ; M(ERRMSG,"Yfile_create_lock",YmsgG ) ; YexitPgm(PGMFAIL) ; } /* now if we get this far find file descriptor */ if( readNotWrite ){ fp = fdopen( fd, "r" ) ; } else { fp = fdopen( fd, "w" ) ; } if(!(fp)){ sprintf( YmsgG,"could not get file descriptor %s\n",filename ) ; M(ERRMSG,"Yfile_create_lock",YmsgG ) ; YexitPgm(PGMFAIL) ; } return( fp ) ; } /* end Yfile_create_lock */ /* see a file is locked */ BOOL Yfile_test_lock( filename ) char *filename ; { INT fd ; /* file descriptor */ INT status ; /* return status */ if(!(YfileExists(filename))){ /* file does not exist */ return( FALSE ) ; } fd = open( filename, O_RDONLY, 0 ) ; if( fd <= 0 ){ sprintf( YmsgG,"could not open file %s\n",filename ) ; M(ERRMSG,"Yfile_test_lock",YmsgG ) ; YexitPgm(PGMFAIL) ; } status = lockf( fd, F_TEST, 0 ) ; if( status != 0 ){ return( TRUE ) ; } else { return( FALSE ) ; } } /* end Yfile_test_lock */ #endif /* HPUX */ /* --------------end file routines ------------------------------- */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/getftime.c000066400000000000000000000047751305746555600214370ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: getftime.c DESCRIPTION:This file contains a routine which returns the last time a file was modified. CONTENTS: DATE: May 8, 1989 - original coding. REVISIONS: Apr 29, 1990 - added message.h ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) getftime.c version 1.3 8/28/90" ; #endif #include #include #include #include #include #define ERROR -1 /* return code for error */ INT YgetFileTime( filename ) char *filename ; { struct stat info ; /* info record */ INT status ; /* return code from stat */ if( filename ){ status = stat( filename, &info ) ; if( status == ERROR ){ sprintf( YmsgG, "ERROR[YgetFileTime] - %s", filename ) ; perror( YmsgG ) ; return( ERROR ) ; } return( info.st_mtime ) ; } return( ERROR ) ; } /* end YgetFileTime */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/graph.c000066400000000000000000002770331305746555600207330ustar00rootroot00000000000000/* * Copyright (C) 1991-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /*------------------------------------------------------------------- FILE: graph.c DESCRIPTION:generic graph algorithms. See Cormen, Leiserson, and Rivest Intorduction to Algorithms Chapters 23,24 CONTENTS: DATE: Jun 03,1991 REVISIONS:Sun Dec 15 02:41:01 EST 1991 - rewrote for new dset routines. NOTES: In case the need for speed arises: 1) instead of rebuilding priority heaps all the time, keep them around as part of graph structures. -----------------------------------------------------------------*/ #ifndef lint static char SccsId[] = "@(#) graph.c version 1.35 4/2/92" ; #endif #include #include #include #include #include #include #include #include #include /* numbers are TWcolors to ease debugging */ #define BLACK TWBLACK #define GRAY TWLIGHTBLUE #define WHITE TWLIGHTBROWN /* defines for VECTOR array */ #define LO -1 #define MAXSIZE -1 #define SIZE 0 #define START 1 /* step size for realloc */ #define STEPSIZE 5 typedef struct graph { YTREEPTR nodeTree; /* all nodes in the graph */ YTREEPTR edgeTree; /* all nodes in the graph */ YDECKPTR topSortDeck; /* results of topological sort */ YDECKPTR strongConnectDeck; /* strongly connected nodes */ YDECKPTR mstDeck; /* minimum spanning tree over enitre graph */ YDECKPTR cycleDecks; /* edges which if add to steiner tree=cycle */ YDECKPTR cyclePrimeDecks; /* edges used to prime multiple steiner trees */ YTREEPTR steinerTrees; /* Tree of graphs which spans some nodes */ YDSETPTR sourceSet; /* Nodes which must be part of steiner tree */ YDECKPTR primeDeck; /* Edges with which to prime steiner tree */ int flags; INT size; /* any metric by which the graph is measured */ INT (*userEdgeWeight)(); /* user routine to get an edge's weight */ VOID (*userDrawEdge)(); /* user routine to draw edges */ VOID (*userDrawNode)(); /* user routine to draw edges */ } YGRAPH, *YGRAPHPTR ; typedef struct graph_node { VOIDPTR data ; /* optional user data associated with node */ struct graph_edge **adjEdge; /* adjacent edge array */ struct graph_edge **backEdge; /* back edge array */ struct graph_node *predecessor; /* predecesor */ int color; int start; int finish; INT distance; } YNODE, *YNODEPTR; typedef struct graph_edge { YNODEPTR node1; YNODEPTR node2; VOIDPTR data; /* user data associated with edge */ int weight; short color; short type; } YEDGE, *YEDGEPTR ; #define GRAPH_DEFINED #include /*--------------------------------------------------------- Macros ---------------------------------------------------------*/ /* if a dynamic edge weight function exists, use it */ /* otherwise, use the edge's static weight */ #define EDGEWEIGHT(graph,edge) ( (graph)->userEdgeWeight ? \ (edge)->weight = (*(graph)->userEdgeWeight)(edge) : (edge)->weight ) /*--------------------------------------------------------- static variables ---------------------------------------------------------*/ static INT dfs_timeS; /* time variable used by depth first search */ static YGRAPHPTR graphS; static INT bestSpanDistanceS; /* span of last required path found */ static VOID (*userNodeFreeS)(); static VOID (*userEdgeFreeS)(); /*--------------------------------------------------------- static prototypes ---------------------------------------------------------*/ static VOID graph_adjedge_free(P2(YEDGEPTR *a_p,YEDGEPTR edge)); static YEDGEPTR *graph_adjedge_insert(P2(YEDGEPTR *a_p,YEDGEPTR edge)); static VOID graph_edge_free(P1(YEDGEPTR edge)); /*-------------------------------------------------- set_compare_node_ptr: compare node pointers --------------------------------------------------*/ static INT set_compare_node_ptr(p1,p2) YNODEPTR p1; YNODEPTR p2; { return ( (INT)(p1) - (INT)(p2) ); } /*-------------------------------------------------- compare_node_distance: compare node distance fields --------------------------------------------------*/ static INT compare_node_distance(p1,p2) YNODEPTR p1; YNODEPTR p2; { return ( p1->distance - p2->distance ); } /*-------------------------------------------------- compare_edges: compare edges based on their weight --------------------------------------------------*/ static INT compare_edge_weight(p1,p2) YEDGEPTR p1; YEDGEPTR p2; { return ( p1->weight - p2->weight ); } /*-------------------------------------------------- compare_edges: compare edges based on their weight --------------------------------------------------*/ static INT compare_edge(p1,p2) YEDGEPTR p1; YEDGEPTR p2; { return ( p1 - p2 ); } /*------------------------------------------------------- compare_graph_size: compare graphs based on size field -------------------------------------------------------*/ static INT compare_graph_size(p1,p2) YGRAPHPTR p1; YGRAPHPTR p2; { return ( p1->size - p2->size ); } /*---------------------------------------------------------------- graph_adjedge_insert: insert edges into an array. ----------------------------------------------------------------*/ static YEDGEPTR *graph_adjedge_insert(a_p,edge) YEDGEPTR *a_p; /* the array pointer */ YEDGEPTR edge; { INT newSize; INT max; newSize = (INT) a_p[SIZE] + 1; max = (INT) a_p[MAXSIZE]; /* do we need to allocate another chunk of memory */ if ( newSize > max ) { /* rellocate the array to a new size */ max += STEPSIZE; a_p = YVECTOR_REALLOC ( a_p, LO, max, YEDGEPTR ); /* update the maximum size */ a_p[MAXSIZE] = (YEDGEPTR) max; /* this is really an INT */ } /* add the new edge to the array */ a_p[newSize] = edge; /* update the size of the array */ a_p[SIZE] = (YEDGEPTR) newSize; /* This is an INT */ return(a_p); } /*------------------------------------------------------------- graph_adjedge_free: free edge from adj edge data structure ------------------------------------------------------------*/ static VOID graph_adjedge_free(a_p,edge) YEDGEPTR *a_p; YEDGEPTR edge; { YEDGEPTR *s_p; /* size pointer */ YEDGEPTR *c_p; /* current edge pointer */ YEDGEPTR *l_p; /* last edge pointer */ INT size; INT newSize; s_p = a_p + SIZE; size = (INT) *s_p; c_p = a_p + START; l_p = a_p + size; /* search list for edge until edge found or end of list */ for ( ; *c_p != edge && c_p <= l_p; c_p++ ); if ( *c_p == edge && c_p <= l_p ) { /* set new size */ newSize = size -1; *s_p = (YEDGEPTR) newSize; /* this is really an int */ /* copy last edge in list to current position */ *c_p = *l_p; } } /*-------------------------------------------------- edge_free: free edges from data structure --------------------------------------------------*/ static VOID graph_edge_free(edgePtr) YEDGEPTR edgePtr; { /* now delete users edge data */ if (userEdgeFreeS) { if (edgePtr->data) { (*userEdgeFreeS)(edgePtr->data); } else { M( ERRMSG, "edge_free","no user edge data to free\n" ) ; } } /* finally free the edge */ YFREE(edgePtr); } /*-------------------------------------------------- free_node: free node from data structure --------------------------------------------------*/ static VOID graph_node_free(nodePtr) YNODEPTR nodePtr; { /* free node adjacency edge tree */ YVECTOR_FREE(nodePtr->adjEdge,LO); YVECTOR_FREE(nodePtr->backEdge,LO); /* now delete users node data */ if (userNodeFreeS) { if (nodePtr->data) { (*userNodeFreeS)(nodePtr->data); } else { M( ERRMSG, "free_node","no user node data to free\n" ) ; } } /* and free the node */ YFREE(nodePtr); } /*------------------------------------------------------------- Ygraph_init: Initialize a graph. User must make either make the compare_edge function unique or set compare_edge equal to NULL The user can set an edge's weight statically. Or, the use can set an edge's weight dynamicallly. Thus, the user edge weight function is optional and only should be used if the user need dynamic edge weights. -------------------------------------------------------------*/ YGRAPHPTR Ygraph_init( user_compare_node, user_compare_edge, user_edge_weight, flags ) INT (*user_compare_node)(); INT (*user_compare_edge)(); INT (*user_edge_weight)(); INT flags ; /* Directed edges, redundant edges, etc. */ { YGRAPHPTR graph ; /* the current tree being built */ graph = YMALLOC( 1, YGRAPH ) ; graph->nodeTree = Yrbtree_init( user_compare_node ); if ( user_compare_edge ) { graph->edgeTree = Yrbtree_init( user_compare_edge ); } else { graph->edgeTree = Yrbtree_init( compare_edge ); } graph->userEdgeWeight = user_edge_weight; graph->flags = flags; graph->sourceSet = Ydset_init( set_compare_node_ptr ); graph->primeDeck = Ydeck_init(); graph->cyclePrimeDecks = Ydeck_init(); graph->topSortDeck = NULL; graph->strongConnectDeck = NULL; graph->mstDeck = NULL; graph->cycleDecks = NULL; graph->steinerTrees = NULL; graph->userDrawEdge = NULL; graph->userDrawNode = NULL; D( "Ygraph_init", ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_init","bogus"); ); return (graph); } /* end Ygraph_init */ /*-------------------------------------------------- empty all nodes and edge from the graph; --------------------------------------------------*/ VOID Ygraph_empty(graph,userNodeDelete,userEdgeDelete) YGRAPHPTR graph; VOID (*userNodeDelete)(); /* user function to free node data */ VOID (*userEdgeDelete)(); /* user function to free edge data */ { userEdgeFreeS = userEdgeDelete; userNodeFreeS = userNodeDelete; Yrbtree_empty( graph->edgeTree, graph_edge_free ); Yrbtree_empty( graph->nodeTree, graph_node_free ); } /*-------------------------------------------------- free and empty the graph --------------------------------------------------*/ VOID Ygraph_free(graph,userNodeDelete,userEdgeDelete) YGRAPHPTR graph; VOID (*userNodeDelete)(); /* user function to free node data */ VOID (*userEdgeDelete)(); /* user function to free edge data */ { Ydset_free(graph->sourceSet,NULL); Ydeck_free(graph->primeDeck,NULL); Ydeck_free(graph->cyclePrimeDecks,NULL); if( graph->topSortDeck ){ Ydeck_free( graph->topSortDeck, NULL ) ; } if( graph->strongConnectDeck ){ Ydeck_free( graph->strongConnectDeck, NULL ) ; } if( graph->mstDeck ){ Ydeck_free( graph->mstDeck, NULL ) ; } if( graph->cycleDecks ){ Ydeck_free( graph->cycleDecks, NULL ) ; } Ygraph_empty(graph,userNodeDelete,userEdgeDelete); Yrbtree_free( graph->nodeTree, NULL ) ; Yrbtree_free( graph->edgeTree, NULL ) ; YFREE(graph); } /*------------------------------------------------- Ygraph_nodeDegree -------------------------------------------------*/ INT Ygraph_nodeDegree( node ) YNODEPTR node; { return ( (INT) node->adjEdge[SIZE] + (INT) node->backEdge[SIZE] ); } /*------------------------------------------------- Ygraph_nodeCount -------------------------------------------------*/ INT Ygraph_nodeCount( graph ) YGRAPHPTR graph; { return (Yrbtree_size(graph->nodeTree)); } /*------------------------------------------------- Ygraph_edgeCount -------------------------------------------------*/ INT Ygraph_edgeCount( graph ) YGRAPHPTR graph; { return (Yrbtree_size(graph->edgeTree)); } /*------------------------------------------------- Ygraph_nodeData -------------------------------------------------*/ VOIDPTR Ygraph_nodeData( node ) YNODEPTR node; { return(node->data); } /*------------------------------------------------- Ygraph_nodeFind -------------------------------------------------*/ YNODEPTR Ygraph_nodeFind( graph, nodeData ) YGRAPHPTR graph; VOIDPTR nodeData; { YNODE nodeDummy; nodeDummy.data = nodeData; return ((YNODEPTR) Yrbtree_search(graph->nodeTree,&nodeDummy) ); } /*------------------------------------------------- Ygraph_nodeFindClosest -------------------------------------------------*/ YNODEPTR Ygraph_nodeFindClosest( graph, nodeData, func ) YGRAPHPTR graph; VOIDPTR nodeData; INT func ; { YNODE nodeDummy; nodeDummy.data = nodeData; return ((YNODEPTR) Yrbtree_search_closest(graph->nodeTree,&nodeDummy,func) ); } /*------------------------------------------------- Ygraph_nodeSuc - find successor to one previously searched. -------------------------------------------------*/ YNODEPTR Ygraph_nodeSuc( graph ) YGRAPHPTR graph; { return ((YNODEPTR) Yrbtree_search_suc(graph->nodeTree)); } /*------------------------------------------------- Ygraph_nodePred - find predecessor to one previously searched. -------------------------------------------------*/ YNODEPTR Ygraph_nodePred( graph ) YGRAPHPTR graph; { return ((YNODEPTR) Yrbtree_search_pred(graph->nodeTree)); } /*------------------------------------------------- Ygraph_enumerateNodes -------------------------------------------------*/ YNODEPTR Ygraph_nodeEnumerate( graph, startFlag ) YGRAPHPTR graph; BOOL startFlag; { return ((YNODEPTR) Yrbtree_enumerate(graph->nodeTree, startFlag) ); } /*------------------------------------------------- Ygraph_nodeEnumeratePush -------------------------------------------------*/ VOID Ygraph_nodeEnumeratePush(graph) YGRAPHPTR graph; { Yrbtree_enumeratePush(graph->nodeTree); } /*------------------------------------------------- Ygraph_nodeEnumeratePop -------------------------------------------------*/ VOID Ygraph_nodeEnumeratePop(graph) YGRAPHPTR graph; { Yrbtree_enumeratePop(graph->nodeTree); } /*------------------------------------------------- Ygraph_nodeMin -------------------------------------------------*/ YNODEPTR Ygraph_nodeMin(graph) YGRAPHPTR graph; { return ( (YNODEPTR) Yrbtree_min(graph->nodeTree) ); } /*------------------------------------------------- Ygraph_nodeMax -------------------------------------------------*/ YNODEPTR Ygraph_nodeMax(graph) YGRAPHPTR graph; { return ( (YNODEPTR) Yrbtree_max(graph->nodeTree) ); } /*------------------------------------------------- Ygraph_listAdjNodes -------------------------------------------------*/ YNODEPTR Ygraph_listAdjNodes( node, listNum ) YNODEPTR node; INT listNum; { YEDGEPTR edge; YNODEPTR adjNode; adjNode = NIL(YNODEPTR); if ( listNum < 1 ) { M( ERRMSG, "Ygraph_listAdjNode","adj list numbered 1-n\n" ) ; } if ( listNum <= (INT) node->adjEdge[SIZE] ) { edge = node->adjEdge[listNum]; if (edge->node1 == node) { adjNode = edge->node2; } else { adjNode = edge->node1; } } return ( adjNode ); } /*------------------------------------------------- Ygraph_listAdjNodes -------------------------------------------------*/ YNODEPTR Ygraph_listBackNodes( node, listNum ) YNODEPTR node; INT listNum; { YEDGEPTR edge; YNODEPTR backNode; backNode = NIL(YNODEPTR); if ( listNum < 1 ) { M( ERRMSG, "Ygraph_listBackNode","back list numbered 1-n\n" ) ; } if ( listNum <= (INT) node->backEdge[SIZE] ) { edge = node->backEdge[listNum]; if (edge->node1 == node) { backNode = edge->node2; } else { backNode = edge->node1; } } return ( backNode ); } /*------------------------------------------------- Ygraph_nodeInterval -------------------------------------------------*/ YNODEPTR Ygraph_nodeInterval( graph, loData, hiData, startFlag ) YGRAPHPTR graph; VOIDPTR loData; VOIDPTR hiData; BOOL startFlag; { YNODE lo; YNODE hi; lo.data = loData; hi.data = hiData; return ((YNODEPTR) Yrbtree_interval(graph->nodeTree, &lo, &hi, startFlag) ); } /*------------------------------------------------- Ygraph_nodeIntervalPush -------------------------------------------------*/ VOID Ygraph_nodeIntervalPush(graph) YGRAPHPTR graph; { Yrbtree_intervalPush(graph->nodeTree); } /*------------------------------------------------- Ygraph_nodeIntervalPop -------------------------------------------------*/ VOID Ygraph_nodeIntervalPop(graph) YGRAPHPTR graph; { Yrbtree_intervalPop(graph->nodeTree); } /*------------------------------------------------- Ygraph_nodeInsert: insert a node into the graph -------------------------------------------------*/ YNODEPTR Ygraph_nodeInsert( graph, nodeData) YGRAPHPTR graph; VOIDPTR nodeData; /* users optional node Data */ { YNODE nodeDummy; YNODEPTR nodePtr; /* does node already exist? */ nodeDummy.data = nodeData; if ( nodePtr = (YNODEPTR)Yrbtree_search (graph->nodeTree,&nodeDummy) ) { return(nodePtr); /* node already exists */ } /* create the new node */ nodePtr = YMALLOC( 1, YNODE ); nodePtr->adjEdge = YVECTOR_MALLOC ( LO, STEPSIZE, YEDGEPTR ); nodePtr->backEdge = YVECTOR_MALLOC ( LO, STEPSIZE, YEDGEPTR ); nodePtr->adjEdge[MAXSIZE] = nodePtr->backEdge[MAXSIZE] = (YEDGEPTR) STEPSIZE; nodePtr->adjEdge[SIZE] = nodePtr->backEdge[SIZE] = (YEDGEPTR) 0; nodePtr->data = nodeData; nodePtr->color = BLACK; /* add node to the graph data structure */ Yrbtree_insert(graph->nodeTree,nodePtr); D("Ygraph_nodeInsert", ASSERTNFAULT(Ygraph_nodeVerify(nodePtr),"Ygraph_nodeInsert","bogus node"); ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_nodeInsert","bogus graph"); ); return(nodePtr); } /*-------------------------------------------------- free_node: free node from data structure --------------------------------------------------*/ VOID Ygraph_nodeDelete(graph,node,userNodeFree,userEdgeFree) YGRAPHPTR graph; YNODEPTR node; VOID (*userNodeFree)(); VOID (*userEdgeFree)(); { YEDGEPTR edge; YNODEPTR node2; YEDGEPTR *a_p; /* array pointer */ YEDGEPTR *c_p; /* current edge pointer */ YEDGEPTR *l_p; /* last edge pointer */ userNodeFreeS = userNodeFree; userEdgeFreeS = userEdgeFree; /* we need to remove all edges which contain this node */ /* do this by searching the adjEdge and backEdge lists */ for ( a_p = node->adjEdge; a_p; a_p = ( a_p == node->adjEdge ? node->backEdge:0 ) ) { c_p = a_p + START; l_p = c_p + (INT) a_p[SIZE]; /* node adj list for edges */ for ( ; c_p < l_p; c_p++ ) { edge = *c_p; /* any edges found must be removed from other nodes adj list */ if ( a_p == node->adjEdge ) { /* for adjEdge tree get other node */ if ( node == edge->node1 ) { node2 = edge->node2; } else { node2 = edge->node1; } } else { /* for backEdge tree get node1 */ node2 = edge->node1; } /* delete the edge from node2 adj edge lists */ graph_adjedge_free(node2->adjEdge,edge); graph_adjedge_free(node2->backEdge,edge); /* delete the edge from the global edge tree */ Yrbtree_delete(graph->edgeTree,edge,NULL); /* free the edge */ graph_edge_free(edge); } } /* remove node from global graph node tree */ Yrbtree_delete(graph->nodeTree,node,NULL); /* free the node and user data */ graph_node_free(node); } /*-------------------------------------------------- Ygraph_edgeDelete: free edges from data structure --------------------------------------------------*/ VOID Ygraph_edgeDelete(graph,edge,userEdgeFree) YGRAPHPTR graph; YEDGEPTR edge; VOID (*userEdgeFree)(); { YEDGEPTR edge2; D( "Ygraph_edgeDelete", ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_edgeDelete","bogus"); ) ; userEdgeFreeS = userEdgeFree; if ( ! edge ){ M( ERRMSG, "Ygraph_edgeDelete","Null edge\n" ) ; } /* delete the edge from node adj edge lists */ graph_adjedge_free(edge->node1->adjEdge,edge); graph_adjedge_free(edge->node2->adjEdge,edge); graph_adjedge_free(edge->node2->backEdge,edge); /* Delete the edge from the global edge tree */ /* User's comparison function may not be unique, */ /* so do an interval to get the right edge */ for ( edge2 = (YEDGEPTR) Yrbtree_interval(graph->edgeTree,edge,edge,TRUE); edge2; edge2 = (YEDGEPTR) Yrbtree_interval(graph->edgeTree,edge,edge,FALSE) ){ if ( edge2 == edge ) { /* null for user edge free because graph_edge_free() does it below */ Yrbtree_deleteCurrentInterval(graph->edgeTree,NULL); break; } } if ( !edge2 ) { M( ERRMSG, "Ygraph_edgeDelete","Edge not found in global edge tree\n" ) ; } /* free the edge and user data */ graph_edge_free(edge); D( "Ygraph_edgeDelete", ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_edgeDelete","bogus"); ) ; } /*------------------------------------------------- Ygraph_edgeFindByNodes -------------------------------------------------*/ YEDGEPTR Ygraph_edgeFindByNodes( graph, node1, node2 ) YGRAPHPTR graph; YNODEPTR node1; YNODEPTR node2; { YEDGEPTR edge; YEDGEPTR *c_p; YEDGEPTR *l_p; YEDGEPTR adjEdge; /* check node1 adj edge tree to */ /* see if the edge already exists */ edge = NIL(YEDGEPTR) ; c_p = node1->adjEdge + START; l_p = c_p + (INT) node1->adjEdge[SIZE]; for ( ; c_p < l_p; c_p ++ ) { adjEdge = *c_p; if (adjEdge->node1 == node1 && adjEdge->node2 == node2 ) { edge = adjEdge; break; } else if ( ! (graph->flags & YGRAPH_DIRECTED) ) { if ( adjEdge->node2 == node1 && adjEdge->node1 == node2 ) { edge = adjEdge; break; } } } return(edge); } /* end Ygraph_edgeFindByNodes() */ /*------------------------------------------------- Ygraph_edgeFindByNodeData -------------------------------------------------*/ YEDGEPTR Ygraph_edgeFindByNodeData( graph, node1Data, node2Data ) YGRAPHPTR graph; VOIDPTR node1Data; VOIDPTR node2Data; { YNODEPTR node1; YNODEPTR node2; YEDGEPTR edge; YEDGEPTR *c_p; YEDGEPTR *l_p; YEDGEPTR adjEdge; if(!(node1 = Ygraph_nodeFind( graph, node1Data ))){ return( NIL(YEDGEPTR) ) ; } if(!(node2 = Ygraph_nodeFind( graph, node2Data ))){ return( NIL(YEDGEPTR) ) ; } /* check node1 adj edge tree to */ /* see if the edge already exists */ edge = NIL(YEDGEPTR) ; c_p = node1->adjEdge + START; l_p = c_p + (INT) node1->adjEdge[SIZE]; for ( ; c_p < l_p; c_p ++ ) { adjEdge = *c_p; if (adjEdge->node1 == node1 && adjEdge->node2 == node2 ) { edge = adjEdge; break; } else if ( ! (graph->flags & YGRAPH_DIRECTED) ) { if ( adjEdge->node2 == node1 && adjEdge->node1 == node2 ) { edge = adjEdge; break; } } } return(edge); } /* end Ygraph_edgeFindByNodes() */ /*------------------------------------------------- Ygraph_edgeFind -------------------------------------------------*/ YEDGEPTR Ygraph_edgeFind( graph, edgeData, node1Data, node2Data ) YGRAPHPTR graph; VOIDPTR edgeData; VOIDPTR node1Data; VOIDPTR node2Data; { YEDGEPTR edge; YEDGE edgeDummy; YNODE node1Dummy; YNODE node2Dummy; edgeDummy.data = edgeData; /* user may have edge sorted by node data */ node1Dummy.data = node1Data; node2Dummy.data = node2Data; edgeDummy.node1 = &node1Dummy; edgeDummy.node2 = &node2Dummy; fprintf( stderr, "Obsolete routine. Use edgeFindByNode() or edgeFindByNodeData().\n" ) ; edge = (YEDGEPTR) Yrbtree_search(graph->edgeTree,&edgeDummy); /* if the edge was not found, reverse the nodes and look again */ /* if the graph does not have directed edges */ if (!edge && !(graph->flags & YGRAPH_DIRECTED)) { edgeDummy.node1 = &node2Dummy; edgeDummy.node2 = &node1Dummy; edge = (YEDGEPTR) Yrbtree_search(graph->edgeTree,&edgeDummy); } return(edge); } /*------------------------------------------------- Ygraph_edgeEnumeratePush -------------------------------------------------*/ VOID Ygraph_edgeEnumeratePush( graph) YGRAPHPTR graph; { Yrbtree_enumeratePush( graph->edgeTree); } /*------------------------------------------------- Ygraph_edgeEnumeratePop -------------------------------------------------*/ VOID Ygraph_edgeEnumeratePop(graph) YGRAPHPTR graph; { Yrbtree_enumeratePop( graph->edgeTree); } /*------------------------------------------------- Ygraph_edgeEnumerate -------------------------------------------------*/ YEDGEPTR Ygraph_edgeEnumerate( graph, startFlag ) YGRAPHPTR graph; BOOL startFlag; { return ( (YEDGEPTR)Yrbtree_enumerate(graph->edgeTree, startFlag) ); } /*------------------------------------------------- Ygraph_edgeMin -------------------------------------------------*/ YEDGEPTR Ygraph_edgeMin(graph) YGRAPHPTR graph; { return ( (YEDGEPTR) Yrbtree_min(graph->edgeTree) ); } /*------------------------------------------------- Ygraph_edgeMax -------------------------------------------------*/ YEDGEPTR Ygraph_edgeMax(graph) YGRAPHPTR graph; { return ( (YEDGEPTR) Yrbtree_max(graph->edgeTree) ); } /*------------------------------------------------- Ygraph_listAdjEdges -------------------------------------------------*/ YEDGEPTR Ygraph_listAdjEdges( node, listNum ) YNODEPTR node; INT listNum; { YEDGEPTR edge; edge = NIL(YEDGEPTR); if ( listNum < 1 ) { M( ERRMSG, "Ygraph_listAdjEdge","adj list numbered 1-n\n" ) ; } if ( listNum <= (INT) node->adjEdge[SIZE] ) { edge = node->adjEdge[listNum]; } return(edge); } /*------------------------------------------------- Ygraph_listBackEdges -------------------------------------------------*/ YEDGEPTR Ygraph_listBackEdges( node, listNum ) YNODEPTR node; INT listNum; { YEDGEPTR edge; edge = NIL(YEDGEPTR); if ( listNum < 1 ) { M( ERRMSG, "Ygraph_listBackEdges","adj list numbered 1-n\n" ) ; } if ( listNum <= (INT) node->backEdge[SIZE] ) { edge = node->backEdge[listNum]; } return(edge); } /*------------------------------------------------- Ygraph_edgeInterval -------------------------------------------------*/ YEDGEPTR Ygraph_edgeInterval( graph, loData, hiData, startFlag ) YGRAPHPTR graph; VOIDPTR loData; VOIDPTR hiData; BOOL startFlag; { YEDGE lo; YEDGE hi; lo.data = loData; hi.data = hiData; return ((YEDGEPTR) Yrbtree_interval(graph->edgeTree, &lo, &hi, startFlag) ); } /*------------------------------------------------- Ygraph_edgeIntervalPush -------------------------------------------------*/ VOID Ygraph_edgeIntervalPush(graph) YGRAPHPTR graph; { Yrbtree_intervalPush(graph->edgeTree); } /*------------------------------------------------- Ygraph_edgeIntervalPop -------------------------------------------------*/ VOID Ygraph_edgeIntervalPop(graph) YGRAPHPTR graph; { Yrbtree_intervalPop(graph->edgeTree); } /*------------------------------------------------- Ygraph_edgeNodes -------------------------------------------------*/ VOID Ygraph_edgeNodes( edge, p1, p2 ) YEDGEPTR edge; YNODEPTR *p1; YNODEPTR *p2; { *p1 = edge->node1; *p2 = edge->node2; } /*------------------------------------------------- Ygraph_edgeData -------------------------------------------------*/ VOIDPTR Ygraph_edgeData( edge ) YEDGEPTR edge; { return(edge->data); } /*------------------------------------------------- Ygraph_edgeNode1 -------------------------------------------------*/ YNODEPTR Ygraph_edgeNode1( edge ) YEDGEPTR edge; { return(edge->node1); } /*------------------------------------------------- Ygraph_edgeNode2 -------------------------------------------------*/ YNODEPTR Ygraph_edgeNode2( edge ) YEDGEPTR edge; { return(edge->node2); } /*------------------------------------------------- Ygraph_edgeNode1Data -------------------------------------------------*/ VOIDPTR Ygraph_edgeNode1Data( edge ) YEDGEPTR edge; { return(edge->node1->data); } /*------------------------------------------------- Ygraph_edgeNode2Data -------------------------------------------------*/ VOIDPTR Ygraph_edgeNode2Data( edge ) YEDGEPTR edge; { return(edge->node2->data); } /*------------------------------------------------- Ygraph_edgeWeight -------------------------------------------------*/ INT Ygraph_edgeWeight( edge ) YEDGEPTR edge; { return( edge->weight ); } /*------------------------------------------------- Ygraph_edgeWeightSet -------------------------------------------------*/ INT Ygraph_edgeWeightSet( edge, weight ) YEDGEPTR edge; INT weight; { edge->weight = weight; return( edge->weight ); } /*------------------------------------------------- Ygraph_edgeWeights2Size Sum all of the edge weights, and put into the graph size field. -------------------------------------------------*/ INT Ygraph_edgeWeights2Size( graph ) YGRAPHPTR graph; { YEDGEPTR edge; INT size; size = 0; Ygraph_edgeEnumeratePush(graph); for ( edge = (YEDGEPTR) Ygraph_edgeEnumerate(graph,TRUE); edge; edge = (YEDGEPTR) Ygraph_edgeEnumerate(graph,FALSE) ){ size += edge->weight; } Ygraph_edgeEnumeratePop(graph); return (graph->size = size); } /*------------------------------------------------- Ygraph_edgeNode1Data -------------------------------------------------*/ int Ygraph_edgeType( edge ) YEDGEPTR edge; { return(edge->type); } /*------------------------------------------------- Ygraph_edgeInsert: insert an edge into the graph The new YEDGEPTR is returned. If the edge already existed, NULL is returned. -------------------------------------------------*/ YEDGEPTR Ygraph_edgeInsert( graph, edgeData, edgeWeight, nodeData, node2Data) YGRAPHPTR graph; VOIDPTR edgeData; /* users optional edge Data */ INT edgeWeight; VOIDPTR nodeData; VOIDPTR node2Data; { YNODEPTR node1; YNODEPTR node2; YEDGEPTR adjEdge; YEDGEPTR edge; YEDGEPTR edge2; YEDGEPTR *c_p; YEDGEPTR *l_p; node1 = Ygraph_nodeInsert ( graph, nodeData ); node2 = Ygraph_nodeInsert ( graph, node2Data ); edge = NIL(YEDGEPTR); edge2 = NIL(YEDGEPTR); /* check node1 adj edge tree to */ /* see if the edge already exists */ c_p = node1->adjEdge + START; l_p = c_p + (INT) node1->adjEdge[SIZE]; for ( ; c_p < l_p; c_p ++ ) { adjEdge = *c_p; if (adjEdge->node1 == node1 && adjEdge->node2 == node2 ) { edge = adjEdge; break; } else if ( ! (graph->flags & YGRAPH_DIRECTED) ) { if ( adjEdge->node2 == node1 && adjEdge->node1 == node2 ) { edge = adjEdge; break; } } } /* the edge does not exist, so we need to create it */ if ( !edge ) { edge2 = YMALLOC( 1, YEDGE ); edge2->node1 = node1; edge2->node2 = node2; edge2->weight = edgeWeight; edge2->data = edgeData; edge2->color = WHITE; edge2->type = ( graph->flags & YGRAPH_DIRECTED ); /* edge is always add to node1 adj edge tree */ node1->adjEdge = graph_adjedge_insert(node1->adjEdge,edge2); /* edge is added to node2 adj edge tree if graph is not directed */ if ( graph->flags & YGRAPH_DIRECTED ) { node2->backEdge = graph_adjedge_insert(node2->backEdge,edge2); } else { node2->adjEdge = graph_adjedge_insert(node2->adjEdge,edge2); } /* Add edge to global edge tree */ Yrbtree_insert(graph->edgeTree,edge2); } /* end create a new edge */ D("Ygraph_edgeInsert", ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_edgeInsert","bogus"); ASSERTNFAULT(Ygraph_nodeVerify(node1),"Ygraph_edgeInsert","bogus node1"); ASSERTNFAULT(Ygraph_nodeVerify(node2),"Ygraph_edgeInsert","bogus node2"); if ( !edge ) { ASSERTNFAULT(Ygraph_edgeVerify(edge2),"Ygraph_edgeInsert","bogus edge"); } else { ASSERTNFAULT(Ygraph_edgeVerify(edge),"Ygraph_edgeInsert","bogus edge"); } ); return(edge2); } /*------------------------------------------------- Ygraph_flags -------------------------------------------------*/ INT Ygraph_flags( graph ) YGRAPHPTR graph; { return(graph->flags); } /*------------------------------------------------- Ygraph_flagsSet -------------------------------------------------*/ INT Ygraph_flagsSet(graph, flag ) YGRAPHPTR graph; INT flag; { return(graph->flags = flag); } /*------------------------------------------------- Ygraph_size() Returns the graph size field. The size of the graph is set if the graph was generated and returned by Ygraph_steiner(). Also, Ygraph_edgeWeights2Size() can be called to add up all of the edge weights into a single size. -------------------------------------------------*/ INT Ygraph_size( graph ) YGRAPHPTR graph; { return(graph->size); } /*------------------------------------------------- Ygraph_copy: returns a copy of a graph -------------------------------------------------*/ YGRAPHPTR Ygraph_copy( graph ) YGRAPHPTR graph; { YGRAPHPTR newGraph; YEDGEPTR edge; YNODEPTR node; INT (*nodeComp)(); INT (*edgeComp)(); edgeComp = Yrbtree_get_compare(graph->edgeTree); nodeComp = Yrbtree_get_compare(graph->nodeTree); /* initialize a new graph */ newGraph = Ygraph_init( nodeComp, edgeComp, graph->userEdgeWeight, graph->flags ); /* copy the draw functions */ Ygraph_drawFunctions(newGraph,graph->userDrawNode,graph->userDrawEdge); D("Ygraph_copy", ASSERTNFAULT(Ygraph_verify(graph), "Ygraph_copy","old graph verification fails"); ASSERTNFAULT(Ygraph_verify(newGraph), "Ygraph_copy","new graph verification fails"); ); /* duplicate the nodes */ for ( node = (YNODEPTR) Yrbtree_enumerate(graph->nodeTree,TRUE); node; node = (YNODEPTR) Yrbtree_enumerate(graph->nodeTree,FALSE)){ Ygraph_nodeInsert ( newGraph, node->data); /* DEBUG */ ASSERTNFAULT(Ygraph_nodeFind(graph,node->data),"Ygraph_copy","bad"); ASSERTNFAULT(Ygraph_nodeFind(newGraph,node->data),"Ygraph_copy","bad"); } /* duplicate the edges */ for ( edge = (YEDGEPTR) Yrbtree_enumerate(graph->edgeTree,TRUE); edge; edge = (YEDGEPTR) Yrbtree_enumerate(graph->edgeTree,FALSE)){ Ygraph_edgeInsert ( newGraph, edge->data, edge->weight, edge->node1->data,edge->node2->data); /* DEBUG */ ASSERTNFAULT( Ygraph_edgeFind(graph,edge->data,edge->node1->data,edge->node2->data), "Ygraph_copy","bad"); ASSERTNFAULT( Ygraph_edgeFind(newGraph,edge->data,edge->node1->data,edge->node2->data), "Ygraph_copy","bad"); } ASSERTNFAULT(Ygraph_nodeCount(newGraph)==Ygraph_nodeCount(graph), "Ygraph_copy","node count mismatch"); ASSERTNFAULT(Ygraph_edgeCount(newGraph)==Ygraph_edgeCount(graph), "Ygraph_copy","edge count mismatch"); D("Ygraph_copy", ASSERTNFAULT(Ygraph_verify(graph), "Ygraph_copy","old graph verification fails"); ASSERTNFAULT(Ygraph_verify(newGraph), "Ygraph_copy","new graph verification fails"); ); /* return the copy */ return(newGraph); } /*-------------------------------------------------- breadth first search Perform a beadth first seach rooted at sourceNode. Optionally, the user can provide a targetNode beyond which the search is terminated. --------------------------------------------------*/ VOID Ygraph_bfs(graph,sourceNode,targetNode) YGRAPHPTR graph; YNODEPTR sourceNode; YNODEPTR targetNode; { YNODEPTR nextNode; YNODEPTR adjNode; YEDGEPTR adjEdge; YEDGEPTR *c_p; YEDGEPTR *l_p; YHEAPPTR heap; if ( !sourceNode ) { M( ERRMSG, "Ygraph_bfs","BFS cannot start from a null node\n" ) ; return; } /* create a heap */ heap = Yheap_init_with_parms(compare_node_distance); /* initialize elements of priority heap with source adj edge */ Yheap_insert(heap,sourceNode); /* initialize all nodes in the graph */ for (nextNode = (YNODEPTR) Yrbtree_enumerate(graph->nodeTree,TRUE); nextNode; nextNode = (YNODEPTR) Yrbtree_enumerate(graph->nodeTree,FALSE) ) { nextNode->color = WHITE; nextNode->distance = INT_MAX; nextNode->predecessor = nextNode; } /* initialize the source */ sourceNode->color = GRAY; sourceNode->distance = 0; /* initially on the source is in the fifo */ Yheap_insert(heap,sourceNode); while ( nextNode = (YNODEPTR) Yheap_delete_min(heap) ) { /* enumerate all of the adjacent nodes */ c_p = nextNode->adjEdge + START; l_p = c_p + (INT) nextNode->adjEdge[SIZE]; /* search list for edges */ for ( ; c_p < l_p; c_p++ ) { adjEdge = *c_p; /* get the adjacent node */ if (adjEdge->node1 == nextNode) { adjNode = adjEdge->node2; } else { ASSERT(adjEdge->node2 == nextNode,"Ygraph_bfs","corrupt graph"); adjNode = adjEdge->node1; } if ( adjNode->color != BLACK ) { if ( adjNode->distance > nextNode->distance + EDGEWEIGHT(graph,adjEdge) ) { adjNode->color = GRAY; adjNode->distance = nextNode->distance + adjEdge->weight; adjNode->predecessor = nextNode; Yheap_insert(heap,adjNode); } } } /* END enumerate all of the adjacent nodes */ nextNode->color = BLACK; /* if we found the target node, we can quit now */ if ( nextNode == targetNode ) { break; } } /* end pop items off of the queue */ if ( targetNode && targetNode != nextNode ) { M(WARNMSG,"Ygraph_bfs","target node specified, but not found\n"); } /* free up the heap */ Yheap_free(heap); } /* end Ygraph_bfs */ /*-------------------------------------------------------------------- Ygraph_path: returns a deck containing a path between the target and the source of the last execute graph search algorithm. To use, first run Ygraph_bfs or Ygraph_dijkstra. Returns a deck of nodes. Target is on top. Source is on bottom. User is responsible for freeing the Deck. ---------------------------------------------------------------------*/ YDECKPTR Ygraph_path(graph,targetNode) YGRAPHPTR graph; YNODEPTR targetNode; { YNODEPTR nextNode; YDECKPTR pathDeck ; pathDeck = Ydeck_init(); for (nextNode = targetNode; nextNode != nextNode->predecessor; nextNode = nextNode->predecessor ) { Ydeck_push(pathDeck,nextNode); } Ydeck_push(pathDeck,nextNode); D("Ygraph_path", fprintf(stderr,"path found with %d nodes\n",Ydeck_size(pathDeck)); ASSERTNFAULT(Ydeck_verify(pathDeck),"Ygraph_path","bad deck"); ); return( pathDeck ); } /*--------------------------------------------------------------------- graph_dfs_visit: depth first search subroutine This is not the quickest dfs visit available, but is is quite general. It it will correctly identify edge types for the directed, undirected, and mixed case. -----------------------------------------------------------------------*/ static VOID graph_dfs_visit(node) YNODEPTR node; { YNODEPTR adjNode; YNODEPTR node1; YNODEPTR node2; YNODEPTR ancestorNode; YEDGEPTR adjEdge; YEDGEPTR *c_p; /* current list pointer */ YEDGEPTR *c2_p; /* current list pointer */ YEDGEPTR *l_p; /* last item in list pointer */ YEDGEPTR *l2_p; /* last item in list pointer */ YDECKPTR swapDeck; node->color = GRAY; dfs_timeS ++; node->start = dfs_timeS; D("Ygraph_dfs", fprintf(stderr,"dfs visit start\n"); Ygraph_draw(graphS); ); /* enumerate all of the adjacent nodes */ c_p = node->adjEdge + START; l_p = c_p + (INT) node->adjEdge[SIZE]; /* search list for edges */ for ( ; c_p < l_p; c_p++ ) { adjEdge = *c_p; /* get the adjacent node */ if (adjEdge->node1 == node) { adjNode = adjEdge->node2; } else { ASSERT(adjEdge->node2 == node,"graph_dfs","corrupt graph"); adjNode = adjEdge->node1; } /* This code handles mixed, directed, and undirected graphs */ /* through the following */ if (adjEdge->type == YGRAPH_NONDIRECTED ){ if (adjNode == node->predecessor ) { /* Do go not go back to parent on non directed edge */ continue; } } /* classify edge. white=tree edge, gray=back edge, */ /* black=forward/cross edge. */ adjEdge->color = adjNode->color; D("Ygraph_dfs", if ( adjEdge->color == GRAY ) { fprintf(stderr,"edge classified as back edge (GRAY)\n"); } else if ( adjEdge->color == WHITE ) { fprintf(stderr,"edge classified as tree edge (WHITE)\n"); } else if ( adjEdge->color == BLACK ) { fprintf(stderr,"edge classified as forward/cross edge (BLACK)\n"); } else { fprintf(stderr,"edge classified as unknow edge (UNKNOWN)\n"); } Ygraph_draw(graphS); ); /* This code handles mixed, directed, and undirected graphs */ /* through the following */ /* this is necessary to correctly find back edges in the mixed case */ if (adjEdge->color == BLACK) { /* A back edge in the mixed case, may actually be a cycle */ /* This is needed so that an undirected edge can be used in both */ /* direction in a mixed type graph. It should be ok because */ /* forward and cross edges should not occur in a purly undirected */ /* graph, so this code will not be executed. In the purely directed */ /* case, this code break will not break out until the first */ /* directed edge is traced back */ node1 = adjNode; node2 = adjNode->predecessor; ancestorNode = node; swapDeck = Ydeck_init(); while ( node2 != node1 && ancestorNode !=node1) { /* enumerate all of the adjacent nodes */ c2_p = node2->adjEdge + START; l2_p = c2_p + (INT) node2->adjEdge[SIZE]; /* search list for edges */ for ( ; c2_p < l2_p; c2_p++ ) { adjEdge = *c2_p; /* get the adjacent node */ if (adjEdge->node1 == node1 || adjEdge->node2 == node1 ) { break; } /* end get adj with adj node */ } /* end for each adjacent edge */ if (adjEdge->type == YGRAPH_NONDIRECTED) { /* need to switch the direction traveled on this undirected edge */ Ydeck_push(swapDeck,adjEdge); node1 = node2; node2 = node2->predecessor; /* trace back forward/cross edge towards a common ancestor */ while (ancestorNode->start > node1->start && ancestorNode != ancestorNode->predecessor ) { ancestorNode = ancestorNode->predecessor; } /* end trace back to potential ancestor */ } else { break; /* an undirected edge was found. */ } /* end if type is undirected */ } /* end for each node1/node2 pair */ if (ancestorNode == node1) { adjNode->predecessor = node; adjEdge->color = GRAY; D("Ygraph_dfs", fprintf(stderr,"mixed graph edge re-classified\n"); Ygraph_draw(graphS); ); Ydeck_pop(swapDeck); while (adjEdge = (YEDGEPTR) Ydeck_pop(swapDeck)) { adjEdge->node1->predecessor = adjEdge->node2; D("Ygraph_dfs", fprintf(stderr,"%d predecessor = %d\n", adjEdge->node1->start,adjEdge->node2->start); ); } } Ydeck_free(swapDeck,NULL); } /* end if this is a back Edge, handle special mixed case */ if (adjNode->color == WHITE) { adjNode->predecessor = node; graph_dfs_visit(adjNode); } } Ydeck_push(graphS->topSortDeck,node); node->color = BLACK; dfs_timeS ++; node->finish = dfs_timeS; D("Ygraph_dfs", fprintf(stderr,"dfs visit complete\n"); Ygraph_draw(graphS); ); } /*-------------------------------------------------- Ygraph_dfs: Perform a depth first search Returns a Deck to the nodes topologically sorted. User is responsible for freeing deck. --------------------------------------------------*/ YDECKPTR Ygraph_dfs(graph) YGRAPHPTR graph; { YNODEPTR nextNode; graphS = graph; graph->topSortDeck = Ydeck_init(); /* initialize all nodes in the graph */ for (nextNode = (YNODEPTR) Yrbtree_enumerate(graph->nodeTree,TRUE); nextNode; nextNode = (YNODEPTR) Yrbtree_enumerate(graph->nodeTree,FALSE) ) { nextNode->color = WHITE; nextNode->distance = INT_MAX; nextNode->predecessor = nextNode; } D("Ygraph_dfs", fprintf(stderr,"Ygraph_dfsstart\n"); Ygraph_draw(graph); ); dfs_timeS = 0; /* do the depth first search */ for (nextNode = (YNODEPTR) Yrbtree_enumerate(graph->nodeTree,TRUE); nextNode; nextNode = (YNODEPTR) Yrbtree_enumerate(graph->nodeTree,FALSE) ) { if (nextNode->color == WHITE) { graph_dfs_visit(nextNode); } } return(graph->topSortDeck); } /*---------------------------------------------------------- Ygraph_mst_Kruskal: Find a mst using Kruskal's algorithm ----------------------------------------------------------*/ YDECKPTR Ygraph_mst_kruskal(graph) YGRAPHPTR graph; { YEDGEPTR nextEdge; YDSETPTR dset; YHEAPPTR heap; /* initialize mst deck */ Ydeck_free(graph->mstDeck,NULL); graph->mstDeck = Ydeck_init(); /* initialize disjoint set and heap */ dset = Ydset_init(set_compare_node_ptr); heap = Yheap_init_with_parms(compare_edge_weight); /* initialize elements of priority heap and disjoint sets */ for (nextEdge = (YEDGEPTR) Yrbtree_enumerate(graph->edgeTree,TRUE); nextEdge; nextEdge = (YEDGEPTR) Yrbtree_enumerate(graph->edgeTree,FALSE) ) { Ydset_find(dset,nextEdge->node1); Ydset_find(dset,nextEdge->node2); Yheap_insert(heap,nextEdge); } while ( nextEdge = (YEDGEPTR)Yheap_delete_min(heap)) { if ( Ydset_find_set(dset,nextEdge->node1) != Ydset_find_set(dset,nextEdge->node2) ) { Ydset_union(dset,nextEdge->node1,nextEdge->node1); Ydeck_push(graph->mstDeck,nextEdge->data); } } Yheap_free(heap); Ydset_free(dset,NULL); return(graph->mstDeck); } /*---------------------------------------------------------- Ygraph_mst_prim: Find a mst using prim's algorithm ----------------------------------------------------------*/ YDECKPTR Ygraph_mst_prim(graph,source) YGRAPHPTR graph; YNODEPTR source; { YNODEPTR nextNode; YEDGEPTR adjEdge; YEDGEPTR nextEdge; YHEAPPTR heap; YEDGEPTR *c_p; YEDGEPTR *l_p; /* initialize edge colors */ for (nextEdge = (YEDGEPTR) Yrbtree_enumerate(graph->edgeTree,TRUE); nextEdge; nextEdge = (YEDGEPTR) Yrbtree_enumerate(graph->edgeTree,FALSE) ) { nextEdge->color = WHITE; /* mark edge not found */ nextEdge->node1->color = WHITE; /* mark node not found */ nextEdge->node2->color = WHITE; /* mark node not found */ } /* initialize mst deck */ Ydeck_free(graph->mstDeck,NULL); graph->mstDeck = Ydeck_init(); /* initialize disjoint set and heap */ heap = Yheap_init_with_parms(compare_edge_weight); /* initialize elements of priority heap with source adj edge */ /* enumerate all of the adjacent nodes */ c_p = source->adjEdge + START; l_p = c_p + (INT) source->adjEdge[SIZE]; /* search list for edges */ for ( ; c_p < l_p; c_p++ ) { nextEdge = *c_p; nextEdge->color=GRAY; /* mark edge as queued */ Yheap_insert(heap,nextEdge); } source->color = BLACK; /* make node as edges queued */ while ( nextEdge = (YEDGEPTR)Yheap_delete_min(heap)) { nextEdge->color = BLACK; /* make edge as part of mst */ Ydeck_push(graph->mstDeck,nextEdge->data); for ( nextNode = nextEdge->node1; nextNode; nextNode = nextNode == nextEdge->node1 ? nextEdge->node2:NIL(YNODEPTR) ) { if ( nextNode->color != BLACK ) { /* enumerate all of the adjacent nodes */ c_p = nextNode->adjEdge + START; l_p = c_p + (INT) nextNode->adjEdge[SIZE]; /* search list for edges */ for ( ; c_p < l_p; c_p++ ) { adjEdge = *c_p; if (adjEdge->color == WHITE) { adjEdge->color=GRAY; /* mark edge as queued */ Yheap_insert(heap,nextEdge); } } nextNode->color = BLACK; /* make node as edges queued */ } } } Yheap_free(heap); return(graph->mstDeck); } /*---------------------------------------------------------- Ygraph_dijkstra: Find a shortest paths from source This could be speeded up for some uses by sending a target and terminating when that target is found. ----------------------------------------------------------*/ VOID Ygraph_dijkstra(graph,sourceNode) YGRAPHPTR graph; YNODEPTR sourceNode; { YNODEPTR adjNode; YEDGEPTR adjEdge; YEDGEPTR *c_p; YEDGEPTR *l_p; YNODEPTR nextNode; YHEAPPTR heap; D("Ygraph_dijkstra", fprintf(stderr,"start dijkstra \n"); ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_dijkstra","bogus graph"); Ygraph_draw(graph); ); ASSERTNFAULT(Ygraph_nodeFind(graph,sourceNode->data), "Ygraph_dijkstra","no source"); /* initialize all nodes in the graph */ for (nextNode=(YNODEPTR)Yrbtree_enumerate(graph->nodeTree,TRUE); nextNode; nextNode=(YNODEPTR)Yrbtree_enumerate(graph->nodeTree,FALSE)){ nextNode->distance = INT_MAX; nextNode->predecessor = NIL(YNODEPTR); nextNode->color = WHITE; /* mark node as not found */ } sourceNode->distance = 0; sourceNode->predecessor = sourceNode; sourceNode->color = GRAY; /* mark node as on heap */ /* initialize disjoint set and heap */ heap = Yheap_init_with_parms(compare_node_distance); /* initialize elements of priority heap with source adj edge */ Yheap_insert(heap,sourceNode); D("Ygraph_dijkstra", fprintf(stderr,"dijkstra initialized\n"); Ygraph_draw(graph); ); while ( nextNode = (YNODEPTR)Yheap_delete_min(heap)) { /* the priority queue code does not allow an arbitrary item */ /* in the queue to change its key. If a node is relaxed, */ /* it is added to the queue again. Thus, a node may be in the queue */ /* more than once. The colors are used to detect this situation */ if (nextNode->color == BLACK) { continue; /* node was relaxed and is already done */ } /* enumerate all of the adjacent edges */ c_p = nextNode->adjEdge + START; l_p = c_p + (INT) nextNode->adjEdge[SIZE]; /* search list for edges */ for ( ; c_p < l_p; c_p++ ) { adjEdge = *c_p; /* get the adjacent node */ if (adjEdge->node1 == nextNode) { adjNode = adjEdge->node2; } else { ASSERT(adjEdge->node2 == nextNode,"graph_dfs","corrupt graph"); adjNode = adjEdge->node1; } /* relax */ if ( adjNode->distance > nextNode->distance + EDGEWEIGHT(graph,adjEdge) ) { adjNode->distance = nextNode->distance + adjEdge->weight; adjNode->predecessor = nextNode; adjNode->color = GRAY; /* mark edge as in heap */ Yheap_insert(heap,adjNode); D("Ygraph_dijkstra", fprintf(stderr,"dijkstra adj node relaxed\n"); ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_dijkstra","bogus graph"); /* Ygraph_draw(graph); /* debug */ ); } } nextNode->color = BLACK; /* make node as done */ } D("Ygraph_dijkstra", fprintf(stderr,"dijkstra complete\n"); ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_dijkstra","bogus graph"); Ygraph_draw(graph); ); Yheap_free(heap); } /*---------------------------------------------------------- Ygraph_bellman_ford: single source shortest path for directed edge graph. Returns TRUE if shortest path found. Returns FALSE if negative weight cycle exists ----------------------------------------------------------*/ BOOL Ygraph_bellman_ford(graph,sourceNode) YGRAPHPTR graph; YNODEPTR sourceNode; { YNODEPTR nextNode; YNODEPTR node1; YNODEPTR node2; YEDGEPTR nextEdge; YTREEPTR tree; INT count; INT numberOfNodes; /* make sure graph is directed edge graph */ if ( ! ( graph->flags & YGRAPH_DIRECTED ) ) { M( ERRMSG, "Ygraph_bellman_ford","not a directed graph\n" ) ; } /* initialize all nodes in the graph */ for (nextNode=(YNODEPTR)Yrbtree_enumerate(graph->nodeTree,TRUE); nextNode; nextNode=(YNODEPTR)Yrbtree_enumerate(graph->nodeTree,FALSE)){ nextNode->distance = INT_MAX; nextNode->predecessor = NIL(YNODEPTR); } sourceNode->distance = 0; numberOfNodes = Yrbtree_size( graph->nodeTree ); for ( count = 1; count < numberOfNodes; count ++) { tree = graph->edgeTree; for (nextEdge = (YEDGEPTR) Yrbtree_enumerate(tree,TRUE); nextEdge; nextEdge = (YEDGEPTR) Yrbtree_enumerate(tree,FALSE) ) { node1 = nextEdge->node1; node2 = nextEdge->node2; /* relax */ if ( node2->distance > node1->distance + EDGEWEIGHT(graph,nextEdge) ) { node2->distance = node1->distance + nextEdge->weight; node2->predecessor = node1; } } } for (nextEdge = (YEDGEPTR) Yrbtree_enumerate(tree,TRUE); nextEdge; nextEdge = (YEDGEPTR) Yrbtree_enumerate(tree,FALSE) ) { node1 = nextEdge->node1; node2 = nextEdge->node2; /* check for negative weight cycle*/ if ( node2->distance > node1->distance + nextEdge->weight ) { return (FALSE); } } /* no negative weight cycle, so shortest path is valid */ return(TRUE); } /*---------------------------------------------------------------- Ygraph_cycles: uses depth first search to find cycles in a graph. The returned deck contains all cycles. Each cycle is a deck. User is responsible for freeing decks ------------------------------------------------------------------*/ YDECKPTR Ygraph_cycles(graph) YGRAPHPTR graph; { YNODEPTR node1; YNODEPTR node2; YNODEPTR finalNode; YEDGEPTR edge; YDECKPTR cycle; YDECKPTR subtractCycle; YDECKPTR cycle1; YDECKPTR cycle2; graph->cycleDecks = Ydeck_init(); Ygraph_dfs(graph); D("Ygraph_cycles", ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_cycles","bad graph"); Ygraph_draw(graph); ); /* walk all edges and find back edges (GRAY) */ for ( edge = Ygraph_edgeEnumerate(graph,TRUE); edge; edge = Ygraph_edgeEnumerate(graph,FALSE) ) { /* For a directed graph, only gray edges are part of cycles */ /* If a graph contains undirected edges, use black edges also */ if ( edge->color == GRAY ) { D("Ygraph_cycles", ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_cycles","bad graph"); fprintf(stderr,"back edge found\n"); ); node1 = Ygraph_edgeNode1(edge); node2 = Ygraph_edgeNode2(edge); cycle1 = Ygraph_path(graph,node1); /* give Ygraph_path a fresh deck for next call */ /* Actuallly, Ygraph_path does this. */ cycle2 = Ygraph_path(graph,node2); /* give Ygraph_path a fresh deck for next call */ /* Actuallly, Ygraph_path does this. */ /* the cycle is max deck - min deck*/ if ( Ydeck_size(cycle1) > Ydeck_size(cycle2) ) { cycle = cycle1; subtractCycle = cycle2; finalNode = node2; } else { cycle = cycle2; subtractCycle = cycle1; finalNode = node1; } /* subtract out nodes which are not part of the cycle */ while( Ydeck_pop(subtractCycle) ) { Ydeck_pop(cycle); } Ydeck_free(subtractCycle,NULL); /* complete the loop */ Ydeck_push(cycle,finalNode); Ydeck_enqueue(cycle,finalNode); Ydeck_push(graph->cycleDecks,cycle); } } D("Ygraph_cycles", ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_cycles","bad graph"); fprintf(stderr,"%d cycles found\n",Ydeck_size(graph->cycleDecks)); ); return(graph->cycleDecks); } /*------------------------------------------------- Ygraph_nodeRequired: insert a node which must be part of any steiner tree -------------------------------------------------*/ YNODEPTR Ygraph_nodeRequired( graph, node, equivNode) YGRAPHPTR graph; YNODEPTR node; /* users node Data */ YNODEPTR equivNode; /* equiv node is equivalent to node */ { static char routineNameS[32] = "Ygraph_nodeRequired"; YNODEPTR returnNode; D( routineNameS, ASSERTNFAULT(Ydset_verify(graph->sourceSet),routineNameS,"bad set"); /* make sure nodes are valid */ ASSERTNFAULT(Ygraph_nodeVerify(node),routineNameS,"bogus node"); ); if ( equivNode ) { D(routineNameS, ASSERTNFAULT(Ygraph_nodeVerify(equivNode),routineNameS,"bogus node"); ); returnNode = (YNODEPTR) Ydset_union(graph->sourceSet,node,equivNode); } else { returnNode = (YNODEPTR) Ydset_find(graph->sourceSet,node); } D( routineNameS, ASSERTNFAULT(Ygraph_verify(graph),routineNameS,"badGraph"); ASSERTNFAULT(Ydset_verify(graph->sourceSet),routineNameS,"bad set"); ); return( returnNode ); } /*------------------------------------------------- Ygraph_nodeRequiredCount: Returns the number of nodes in the required node set. -------------------------------------------------*/ INT Ygraph_nodeRequiredCount( graph ) YGRAPHPTR graph; { return( Ydset_superset_size( graph->sourceSet ) ); } /*------------------------------------------------- Ygraph_clearRequired: clear all nodes which must part of any steiner tree -------------------------------------------------*/ VOID Ygraph_clearRequired(graph) YGRAPHPTR graph; { Ydset_empty(graph->sourceSet,NULL); } /*------------------------------------------------- Ygraph_enumerateRequired: enumerates all nodes which must be part of any steiner tree or required path. -------------------------------------------------*/ YNODEPTR Ygraph_enumerateRequired(graph,startFlag) YGRAPHPTR graph; BOOL startFlag; { YNODEPTR node; if ( graph->sourceSet ) { return( (YNODEPTR) Ydset_enumerate(graph->sourceSet,startFlag) ); } else { return( NIL(YNODEPTR) ); } } /*------------------------------------------------- Ygraph_edgePrime: Prime a steiner tree search with this edge -------------------------------------------------*/ VOID Ygraph_edgePrime( graph, edge) YGRAPHPTR graph; YEDGEPTR edge; /* users edge */ { static char routineNameS[32] = "Ygraph_edgePrime"; D( routineNameS, /* make sure edge is valid */ ASSERTNFAULT(Ygraph_edgeVerify(edge),routineNameS,"bogus node"); ); Ydeck_push( graph->primeDeck, edge ); } /*------------------------------------------------- Ygraph_clearPrime: clear all nodes which must part of any steiner tree -------------------------------------------------*/ VOID Ygraph_clearPrime(graph) YGRAPHPTR graph; { Ydeck_empty( graph->primeDeck, NULL ); } /*---------------------------------------------------------- stiener_trace_back: trace back and add edges to a deck user is responsible for freeing deck. ----------------------------------------------------------*/ static YDECKPTR steiner_trace_back(bridgeEdge) YEDGEPTR bridgeEdge; { static char routineNameS[32] = "steiner_trace_back"; YNODEPTR sourceNode; YNODEPTR targetNode; YNODEPTR traceBackNode; YNODEPTR currentNode; YEDGEPTR traceBackEdge; YEDGEPTR *c_p; YEDGEPTR *l_p; YDECKPTR traceBackDeck; /* cycle has been found. save the edges to help generate n */ /* best steiner trees */ traceBackDeck = Ydeck_init(); /* the edge between source and target is part of the cycle */ bridgeEdge->color = GRAY; /* mark edge as traced */ Ydeck_push(traceBackDeck,bridgeEdge); sourceNode = bridgeEdge->node1; targetNode = bridgeEdge->node2; /* predecessor edges of source and target are part of the cycle */ for (traceBackNode = sourceNode; traceBackNode; traceBackNode = traceBackNode == sourceNode ? targetNode : NIL(YNODEPTR) ) { currentNode = traceBackNode; /* trace back predecessors to originator */ while (currentNode->predecessor != currentNode) { /* go back to the predessor in case directed edge */ /* enumerate all of the adjacent edges */ c_p = currentNode->predecessor->adjEdge + START; l_p = c_p + (INT) currentNode->predecessor->adjEdge[SIZE]; /* search list for edges */ for ( ; c_p < l_p; c_p++ ) { traceBackEdge = *c_p; if ( traceBackEdge->node1 == currentNode || traceBackEdge->node2 == currentNode ) { currentNode = currentNode->predecessor; break; } } /* end look for trace back edge */ traceBackEdge->color = GRAY; /* mark edge as traced */ if ( traceBackNode == sourceNode ) { Ydeck_push(traceBackDeck,traceBackEdge); } else { Ydeck_enqueue(traceBackDeck,traceBackEdge); } } /* end while traceBackNode->predecessor != traceBackNode) */ } /* end for each source and target node trace back */ D( routineNameS, ASSERTNFAULT(Ydeck_verify(traceBackDeck),routineNameS,"bad deck"); ); return(traceBackDeck); } /*-------------------------------------------------- Perform a beadth first seach to find a single path between nodes of different sets. Use Ygraph_nodeRequired() to set up initial sets. Use Ygraph_clearRequired() to clear initial sets. --------------------------------------------------*/ YDECKPTR Ygraph_requiredPath(graph) YGRAPHPTR graph; { static char routineNameS[32] = "Ygraph_requiredPath"; YNODEPTR nextNode; YNODEPTR node; YNODEPTR node1; YNODEPTR node2; YNODEPTR adjNode; YEDGEPTR bestSpanEdge; YEDGEPTR adjEdge; YEDGEPTR edge; YEDGEPTR *c_p; YEDGEPTR *l_p; YHEAPPTR heap; YDSETPTR dset; YDECKPTR spanDeck; INT distance; int sourceSetCount; bestSpanEdge = NIL(YEDGEPTR); bestSpanDistanceS = INT_MAX; /* create a heap */ heap = Yheap_init_with_parms(compare_node_distance); /* The BFS starts simultaneously from all pins. Use disjoint sets */ /* to handle equivalent pins */ dset = Ydset_init(set_compare_node_ptr); /* return nil if no path can be found */ spanDeck = NIL(YDECKPTR); /* initialize all nodes in the graph */ for (node = (YNODEPTR) Yrbtree_enumerate(graph->nodeTree,TRUE); node; node = (YNODEPTR) Yrbtree_enumerate(graph->nodeTree,FALSE) ) { node->color = WHITE; node->distance = INT_MAX; node->predecessor = node; } sourceSetCount = 0; /* initialize the priority queue with nodes to be a part of the tree */ for( node=(YNODEPTR)Ydset_enumerate(graph->sourceSet,TRUE); node; node=(YNODEPTR)Ydset_enumerate(graph->sourceSet,FALSE) ) { node->distance = 0; node->predecessor = node; node->color = GRAY; /* mark node as on heap*/ Yheap_insert(heap,node); /* handle equivalent pins by always union with parent */ adjNode = (YNODEPTR) Ydset_find_set(graph->sourceSet,node); Ydset_union(dset,node,adjNode); sourceSetCount++; } /* initialize with edges required to be a part of the tree */ for( Ydeck_top(graph->primeDeck); Ydeck_notEnd(graph->primeDeck); Ydeck_down(graph->primeDeck) ) { edge = (YEDGEPTR) Ydeck_getData(graph->primeDeck); node1 = edge->node1; node2 = edge->node2; node1->distance = 0; node1->predecessor = node1; node1->color = GRAY; /* mark node as on heap*/ Yheap_insert(heap,node1); node2->distance = 0; node2->predecessor = node2; node2->color = GRAY; /* mark node as on heap*/ Yheap_insert(heap,node2); edge->color = BLACK; /* make edge as part of tree */ Ydset_union(dset,node1,node2); sourceSetCount++; } if ( sourceSetCount < 2 ) { M( ERRMSG, routineNameS, "not enough required nodes or primed edges\n" ); } node = (YNODEPTR) Ydset_enumerate(graph->sourceSet,TRUE); /* make sure there is some work to do */ if ( Ydset_superset_size(dset) == Ydset_subset_size(dset,node) ) { /* force fall through to free heap and free set by depleting the heap */ Yheap_empty(heap); } D(routineNameS, fprintf(stderr,"%s: initialize\n",routineNameS); Ygraph_draw(graph); /* DEBUG */ ); while ( nextNode = (YNODEPTR) Yheap_delete_min(heap) ) { if (nextNode->color == BLACK) { continue; /* node was relaxed and is already done */ } nextNode->color = BLACK; Ydset_union(dset,nextNode,nextNode->predecessor); /* enumerate all of the adjacent nodes */ c_p = nextNode->adjEdge + START; l_p = c_p + (INT) nextNode->adjEdge[SIZE]; /* search list for edges */ for ( ; c_p < l_p; c_p++ ) { adjEdge = *c_p; /* get the adjacent node */ if (adjEdge->node1 == nextNode) { adjNode = adjEdge->node2; } else { ASSERT(adjEdge->node2 == nextNode,"Ygraph_bfs","corrupt graph"); adjNode = adjEdge->node1; } if ( adjNode->color != BLACK ) { if ( adjNode->distance > nextNode->distance + EDGEWEIGHT(graph,adjEdge) ) { adjNode->color = GRAY; adjNode->distance = nextNode->distance + EDGEWEIGHT(graph,adjEdge); adjNode->predecessor = nextNode; Yheap_insert(heap,adjNode); } } else if ( nextNode->predecessor != adjNode ) { if (Ydset_find_set(dset,adjNode) != Ydset_find_set(dset,nextNode) ) { /* we have found a connection, but it is not necessarily the */ /* best connection. We cannot be sure until the cost of nodes */ /* on the heap, exceedS the cost of the current best connection */ if ( nextNode->distance > bestSpanDistanceS ) { /* we cannot find a better connection force stop */ Yheap_empty(heap); break; } else { distance = nextNode->distance + adjNode->distance + EDGEWEIGHT(graph,adjEdge); if ( distance < bestSpanDistanceS ) { bestSpanDistanceS = distance; bestSpanEdge = adjEdge; } } } } } /* END enumerate all of the adjacent nodes */ D(routineNameS, fprintf(stderr,"%s: ready to pop heap\n",routineNameS); Ygraph_draw(graph); /* DEBUG */ ); } /* end pop items off of the queue */ /* if a bridge edge was found, trace it back in both directions */ if ( bestSpanEdge ) { spanDeck = steiner_trace_back(bestSpanEdge); } D(routineNameS, fprintf(stderr,"%s single path finished:\n",routineNameS); Ygraph_draw(graph); /* DEBUG */ ); /* free up the heap */ Yheap_free(heap); /* free the disjoint set */ Ydset_free(dset,NULL); return (spanDeck); } /* end Ygraph_bfs */ /*-------------------------------------------------- Return size of last required path --------------------------------------------------*/ INT Ygraph_requiredPathSize(graph) YGRAPHPTR graph; { return(bestSpanDistanceS); } /*---------------------------------------------------------- Ygraph_steiner: Find the mst for a set of nodes. Returns a graph which spans the required nodes. The returned graph is not guaranteed to be optimal. A random interchange is performed maxImproves times in an attempt to reduce the weight of the spanning graph. The user can use Ygraph_size() to find the total cost of the returned steiner tree. ----------------------------------------------------------*/ YGRAPHPTR Ygraph_steiner(graph,maxImproves) YGRAPHPTR graph; int maxImproves; { static char routineNameS[16] = "Ygraph_steiner"; YNODEPTR node; YNODEPTR adjNode; YNODEPTR node1; YNODEPTR node2; YEDGEPTR edge; YHEAPPTR heap; YDECKPTR deck; YDECKPTR pathDeck; YDECKPTR savePrimeDeck; YDSETPTR dset; YDSETPTR saveSourceSet; YGRAPHPTR steinerGraph; INT (*compareEdge)(); INT (*compareNode)(); int done = FALSE; /* first run a sanity on the graph */ D( routineNameS, ASSERTNFAULT(Ygraph_verify(graph),"generateTrees","bogus graph"); ); /* initialize internal data structures */ /* use priority queue keyed on node distance for BFS type tree building */ heap = Yheap_init_with_parms(compare_node_distance); /* Use disjoint sets to determine which nodes are part of a tree */ dset = Ydset_init(set_compare_node_ptr); /* dummy deck */ deck = Ydeck_init(); /* save the users required nodes and prime edges */ /* this routine will change them */ savePrimeDeck = graph->primeDeck; saveSourceSet = graph->sourceSet; compareEdge = Yrbtree_get_compare(graph->edgeTree); compareNode = Yrbtree_get_compare(graph->nodeTree); steinerGraph = Ygraph_init(compareNode,compareEdge, graph->userEdgeWeight,YGRAPH_NONDIRECTED); /* initialize the dset with nodes to be a part of the tree */ for( node=(YNODEPTR)Ydset_enumerate(saveSourceSet,TRUE); node; node=(YNODEPTR)Ydset_enumerate(saveSourceSet,FALSE) ) { /* handle equivalent pins by always union with parent */ adjNode = (YNODEPTR) Ydset_find_set(saveSourceSet,node); Ydset_union(dset,node,adjNode); } D(routineNameS, fprintf(stderr,"%s edge initialized\n",routineNameS); Ygraph_draw(graph); /* DEBUG */ ); /* initialize with dset with edge nodes required to be a part of the tree */ for( Ydeck_top(savePrimeDeck); Ydeck_notEnd(savePrimeDeck); Ydeck_down(savePrimeDeck) ) { edge = (YEDGEPTR) Ydeck_getData(savePrimeDeck); node1 = edge->node1; node2 = edge->node2; edge->color = BLACK; /* make edge as part of tree */ Ygraph_edgeInsert(steinerGraph,edge->data,edge->weight, node1->data,node2->data); Ydset_union(dset,node1,node2); } D(routineNameS, fprintf(stderr,"%s steiner tree primed\n",routineNameS); Ygraph_draw(graph); /* DEBUG */ ); /* replace graph prime deck and source set with our own */ /* this allows us to change the source set as the tree is built up */ graph->sourceSet = dset; graph->primeDeck = deck; for ( pathDeck = Ygraph_requiredPath(graph); pathDeck; pathDeck = Ygraph_requiredPath(graph) ) { while ( edge = (YEDGEPTR) Ydeck_pop( pathDeck ) ) { node1 = edge->node1; node2 = edge->node2; edge->color = BLACK; Ygraph_edgeInsert(steinerGraph,edge->data,edge->weight, node1->data,node2->data); Ydset_union(graph->sourceSet,node1,node2); } Ydeck_free(pathDeck,NULL); } graph->primeDeck = savePrimeDeck; graph->sourceSet = saveSourceSet; Ygraph_steinerImprove(graph,steinerGraph,maxImproves); Yheap_free(heap); Ydeck_free(deck,NULL); Ydset_free(dset,NULL); D(routineNameS, fprintf(stderr,"spanning tree found with %d edges and %d nodes \n", Ygraph_edgeCount(steinerGraph), Ygraph_nodeCount(steinerGraph)); Ygraph_draw(graph); /* DEBUG */ ); return(steinerGraph); } /*---------------------------------------- Improves the steiner tree. The original graph must have its required nodes properly set. ----------------------------------------*/ VOID Ygraph_steinerImprove(graph,steinerGraph,maxIterations) YGRAPHPTR graph; YGRAPHPTR steinerGraph; int maxIterations; { static char routineNameS[32]="Ygraph_steinerImprove"; YTREEPTR pathTree; YDECKPTR primeDeck; YDECKPTR savePrimeDeck; YDECKPTR connectDeck; YEDGEPTR nextEdge; YEDGEPTR edge; YEDGEPTR edge2; YNODEPTR node; YNODEPTR nextNode; YNODEPTR lastNode; YNODEPTR node1; YNODEPTR node2; YNODEPTR origNode; INT oldWeight; INT newWeight; int count; int numEdges; int pass; int r; if ( ! Ygraph_nodeCount(steinerGraph) ) { M(ERRMSG,routineNameS,"aborting: steiner graph has no nodes\n"); return; } if ( ! Ygraph_edgeCount(steinerGraph) ) { M(ERRMSG,routineNameS,"aborting: steiner graph has no edges\n"); return; } if ( Ygraph_nodeCount(steinerGraph) < 3 || Ygraph_edgeCount(steinerGraph) < 2 ) { Ygraph_edgeWeights2Size(steinerGraph); return; } pathTree = Yrbtree_init(compare_edge); primeDeck = Ydeck_init(); while ( maxIterations-- ) { /* get a random edge */ numEdges = Yrbtree_size(steinerGraph->edgeTree); r = Yacm_random() % numEdges; edge = (YEDGEPTR) Yrbtree_enumerate(steinerGraph->edgeTree,TRUE); while ( r-- ) { edge = (YEDGEPTR) Yrbtree_enumerate(steinerGraph->edgeTree,FALSE); } Yrbtree_insert(pathTree,edge); oldWeight = EDGEWEIGHT(steinerGraph,edge); node1 = edge->node1; node2 = edge->node2; /* build a path starting with this edge */ /* the path should extend until the end points are */ /* nodes with degree > 2 OR a required node */ for ( pass = 0; pass < 2; pass ++ ) { if ( pass ) { node = node1; lastNode = node2; } else { node = node2; lastNode = node1; } origNode = Ygraph_nodeFind(graph,node->data); while ( Ygraph_nodeDegree(node) <= 2 && ! Ydset_search(graph->sourceSet,origNode) ) { for ( count = 1; nextEdge = (YEDGEPTR) Ygraph_listAdjEdges(node,count); count++ ) { /* get adjacent nodes */ if ( nextEdge->node1 == node ) { nextNode = nextEdge->node2; } else { nextNode = nextEdge->node1; } /* avoid backtrace */ if ( nextNode == lastNode ) { continue; } lastNode = node; node = nextNode; origNode = Ygraph_nodeFind(graph,node->data); oldWeight += EDGEWEIGHT(steinerGraph,nextEdge); Yrbtree_insert(pathTree,nextEdge); break; } ASSERTNFAULT(node,"Ygraph_steinerImprove","dangling node found"); ASSERTNFAULT(origNode, "Ygraph_steinerImprove", "node in steiner, but not original graph\n"); } /* end while node is unrequired or degree < 2 */ } /* end for each pass */ /* save the users required nodes and prime edges */ /* this routine will change them */ savePrimeDeck = graph->primeDeck; graph->primeDeck = primeDeck; /* build a new prime deck. This deck cointains all edges in */ /* the existing steiner tree except the segment determined above */ for ( edge = (YEDGEPTR) Yrbtree_enumerate(steinerGraph->edgeTree,TRUE); edge; edge = (YEDGEPTR) Yrbtree_enumerate(steinerGraph->edgeTree,FALSE) ) { if ( !Yrbtree_search(pathTree,edge) ) { node1 = edge->node1; node2 = edge->node2; edge2 = Ygraph_edgeFindByNodeData( graph, node1->data, node2->data ); Ydeck_push(primeDeck,edge2); } } connectDeck = Ygraph_requiredPath(graph); /* restore the original prime deck */ graph->primeDeck = savePrimeDeck; newWeight = 0; for ( Ydeck_top(connectDeck); Ydeck_notEnd(connectDeck); Ydeck_down(connectDeck) ) { edge = (YEDGEPTR) Ydeck_getData(connectDeck); newWeight += edge->weight; } if ( newWeight < oldWeight ) { D("Ygraph_steinerImprove", fprintf(stderr,"steiner graph improved %d -> %d\n", oldWeight,newWeight); ); /* remove old edges from the graph */ for ( edge2 = (YEDGEPTR) Yrbtree_enumerate(pathTree,TRUE); edge2; edge2 = (YEDGEPTR) Yrbtree_enumerate(pathTree,FALSE) ) { Ygraph_edgeDelete(steinerGraph,edge2,NULL); } /* put new edges into the graph */ while ( edge2 = (YEDGEPTR) Ydeck_pop(connectDeck) ) { node1 = edge2->node1; node2 = edge2->node2; Ygraph_edgeInsert(steinerGraph, edge2->data, edge2->weight, node1->data, node2->data); } /* end put new edges into graph */ } /* end if new weight is better than old weight */ Yrbtree_empty(pathTree,NULL); Ydeck_empty(primeDeck,NULL); Ydeck_free(connectDeck,NULL); } /* end for each iteration count */ Ygraph_edgeWeights2Size(steinerGraph); Yrbtree_free(pathTree,NULL); Ydeck_free(primeDeck,NULL); } /*---------------------------------------------------------- Ygraph_nodeVerify: exercise graph data structures ----------------------------------------------------------*/ int Ygraph_nodeVerify(node) YNODEPTR node; { int rc = TRUE; if (YcheckDebug(node) < sizeof(YNODE)) { M(ERRMSG,"Ygraph_nodeVerify","node memory corrupt\n"); rc = FALSE; } if ( YcheckDebug( &node->adjEdge[LO] ) < ( sizeof(YEDGEPTR) * ( (INT) node->adjEdge[MAXSIZE] - LO + 1 ) ) ) { M(ERRMSG,"Ygraph_nodeVerify","bogus node adj edge list\n"); rc = FALSE; } if ( YcheckDebug( &node->backEdge[LO] ) < ( sizeof(YEDGEPTR) * ( (INT) node->backEdge[MAXSIZE] - LO + 1 ) ) ) { M(ERRMSG,"Ygraph_nodeVerify","bogus node adj edge list\n"); rc = FALSE; } return(rc); } /*---------------------------------------------------------- Ygraph_edgeVerify: exercise graph data structures ----------------------------------------------------------*/ int Ygraph_edgeVerify(edge) YEDGEPTR edge; { int rc = TRUE; if (YcheckDebug(edge) < sizeof(YEDGE)) { M(ERRMSG,"Ygraph_edgeVerify","edge memory corrupt\n"); rc = FALSE; } if (YcheckDebug(edge->node1) < sizeof(YNODE)) { M(ERRMSG,"Ygraph_edgeVerify","edge node1 memory corrupt\n"); rc = FALSE; } if (YcheckDebug(edge->node2) < sizeof(YNODE)) { M(ERRMSG,"Ygraph_edgeVerify","edge node2 memory corrupt\n"); rc = FALSE; } if ( ! (edge->type == YGRAPH_DIRECTED || edge->type == YGRAPH_NONDIRECTED)){ M(ERRMSG,"Ygraph_edgeVerify","edge type is bogus\n"); rc = FALSE; } return(rc); } /*---------------------------------------------------------- Ygraph_verify: exercise graph data structures ----------------------------------------------------------*/ int Ygraph_verify(graph) YGRAPHPTR graph; { YNODEPTR node; YNODEPTR node1; YNODEPTR node2; YEDGEPTR edge; YEDGEPTR edge2; YEDGEPTR edge3; YEDGEPTR edge4; YEDGEPTR edge5; YEDGEPTR adjEdge; YEDGEPTR *c_p; YEDGEPTR *l_p; int rc = TRUE; ASSERTNFAULT(YcheckDebug(graph) >= sizeof(YGRAPH), "Ygraph_verify","graph memory corrupt"); if ( ! Yrbtree_verify(graph->nodeTree) ) { M(ERRMSG,"Ygraph_verify","bogus graph node tree\n"); rc = FALSE; } if ( ! Yrbtree_verify(graph->edgeTree) ) { M(ERRMSG,"Ygraph_verify","bogus graph edge tree\n"); rc = FALSE; } if ( ! Ydeck_verify(graph->primeDeck) ) { M(ERRMSG,"Ygraph_verify","bogus prime deck\n"); rc = FALSE; } if ( ! Ydeck_verify(graph->cyclePrimeDecks) ) { M(ERRMSG,"Ygraph_verify","cyclePrimeDecks\n"); rc = FALSE; } if ( ! Ydset_verify(graph->sourceSet) ) { M(ERRMSG,"Ygraph_verify","bogus graph source tree\n"); rc = FALSE; } if ( graph->flags < 0 || graph->flags > YGRAPH_DIRECTED ) { M(ERRMSG,"Ygraph_verify","bogus graph flags\n"); rc = FALSE; } Ygraph_nodeEnumeratePush(graph); for ( node = (YNODEPTR) Ygraph_nodeEnumerate(graph,TRUE); node; node = (YNODEPTR) Ygraph_nodeEnumerate(graph,FALSE) ){ if ( ! Ygraph_nodeVerify(node) ) { M(ERRMSG,"Ygraph_verify","graph has bogus node\n"); rc = FALSE; } node2 = Ygraph_nodeFind(graph,node->data); if ( !node2 ) { M(ERRMSG,"Ygraph_verify","could not find node\n"); rc = FALSE; } if ( node2 != node ) { M(WARNMSG,"Ygraph_verify","found duplicate node\n"); rc = FALSE; } /* check node's adjacent edge list */ c_p = node->adjEdge + START; l_p = c_p + (INT) node->adjEdge[SIZE]; /* search list for edges */ for ( ; c_p < l_p; c_p++ ) { adjEdge = *c_p; if ( ! Ygraph_edgeVerify(adjEdge) ) { M(ERRMSG,"Ygraph_verify","node has bogus adj edge\n"); rc = FALSE; } } /* check node's back edge list */ c_p = node->backEdge + START; l_p = c_p + (INT) node->backEdge[SIZE]; /* search list for edges */ for ( ; c_p < l_p; c_p++ ) { adjEdge = *c_p; if ( ! Ygraph_edgeVerify(adjEdge) ) { M(ERRMSG,"Ygraph_verify","node has bogus back edge\n"); rc = FALSE; } } } Ygraph_nodeEnumeratePop(graph); /* Verify all the edges in the graph */ Ygraph_edgeEnumeratePush(graph); for ( edge = (YEDGEPTR) Ygraph_edgeEnumerate(graph,TRUE); edge; edge = (YEDGEPTR) Ygraph_edgeEnumerate(graph,FALSE) ){ if ( ! Ygraph_edgeVerify(edge) ) { M(ERRMSG,"Ygraph_verify","graph has bogus edge\n"); rc = FALSE; } if ( ! Ygraph_nodeVerify(edge->node1) ) { M(ERRMSG,"Ygraph_verify","graph has bogus node\n"); rc = FALSE; } if ( ! Ygraph_nodeVerify(edge->node2) ) { M(ERRMSG,"Ygraph_verify","graph has bogus node\n"); rc = FALSE; } /* see if the edge's exists in its node adj trees */ node1 = edge->node1; node2 = edge->node2; if ( edge->node1 == edge->node2 ) { M(ERRMSG,"Ygraph_verify","edge has the same node on both ends\n"); rc = FALSE; } /* enumerate all of the adjacent edges */ c_p = node1->adjEdge + START; l_p = c_p + (INT) node1->adjEdge[SIZE]; /* search list for edges */ for ( edge2=NIL(YEDGEPTR) ; c_p < l_p; c_p++ ) { adjEdge = *c_p; if (adjEdge->node1 == node1 && adjEdge->node2 == node2 ) { edge2 = adjEdge; break; } } if ( !edge2 ) { M(ERRMSG,"Ygraph_verify","could not find edge in edge's node1 list\n"); rc = FALSE; } else if ( edge2 != edge ) { M(WARNMSG,"Ygraph_verify","found duplicate edge in edge's node1 list\n"); rc = FALSE; } c_p = node1->backEdge + START; l_p = c_p + (INT) node1->backEdge[SIZE]; /* search list for edges */ for ( edge3=NIL(YEDGEPTR) ; c_p < l_p; c_p++ ) { adjEdge = *c_p; if (adjEdge->node1 == node1 && adjEdge->node2 == node2 ) { edge3 = adjEdge; break; } } if ( edge3 ) { M(ERRMSG,"Ygraph_verify","found edge in edge's node1 back list\n"); rc = FALSE; } /* enumerate all of the adjacent edges */ c_p = node2->adjEdge + START; l_p = c_p + (INT) node2->adjEdge[SIZE]; /* search list for edges */ for ( edge4=NIL(YEDGEPTR) ; c_p < l_p; c_p++ ) { adjEdge = *c_p; if (adjEdge->node1 == node1 && adjEdge->node2 == node2 ) { edge4 = adjEdge; break; } } if ( edge->type == YGRAPH_DIRECTED ) { if ( edge4 ) { M(ERRMSG,"Ygraph_verify","directed edge in edge's node2 adj list\n"); rc = FALSE; } } else if ( !edge4 ) { M(ERRMSG,"Ygraph_verify","could not find edge in edge's node2 list\n"); rc = FALSE; } else if ( edge4 != edge ) { M(WARNMSG,"Ygraph_verify","found duplicate edge in edge's node2 list\n"); rc = FALSE; } c_p = node2->backEdge + START; l_p = c_p + (INT) node2->backEdge[SIZE]; /* search list for edges */ for ( edge5=NIL(YEDGEPTR) ; c_p < l_p; c_p++ ) { adjEdge = *c_p; if (adjEdge->node1 == node1 && adjEdge->node2 == node2 ) { edge5 = adjEdge; break; } } if ( edge->type == YGRAPH_NONDIRECTED ) { if ( edge5 ) { M(ERRMSG,"Ygraph_verify","undirected edge in edge's node2 back list\n"); rc = FALSE; } } else if ( !edge5 ) { M(ERRMSG,"Ygraph_verify","directed edge not in edge's node2 back list\n"); rc = FALSE; } else if ( edge5 != edge ) { M(WARNMSG,"Ygraph_verify","duplicate edge in edge's node2 back list\n"); rc = FALSE; } if ( !edge->node1 || !edge->node2) { M(ERRMSG,"Ygraph_verify","edge has Null node\n"); rc = FALSE; } } /* end for each edge */ Ygraph_edgeEnumeratePop(graph); return(rc); } /*--------------------------------------------------------- Dump graph statistics and call users print functions for nodes and edges ---------------------------------------------------------*/ VOID Ygraph_dump(graph,printNode,printEdge) YGRAPHPTR graph; VOID (*printNode)(); VOID (*printEdge)(); { YEDGEPTR edge; YNODEPTR node; D("Ygraph_dump", ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_dump","bogus graph"); ); fprintf(stderr,"graph has %d edges \n",Ygraph_edgeCount(graph)); if ( printEdge ) { Ygraph_edgeEnumeratePush(graph); /* now draw the edges */ for (edge=Ygraph_edgeEnumerate(graph,TRUE); edge; edge=Ygraph_edgeEnumerate(graph,FALSE) ) { (*printEdge)(edge); } /* end for each edge */ Ygraph_edgeEnumeratePop(graph); } fprintf(stderr,"graph has %d nodes \n",Ygraph_nodeCount(graph)); if ( printNode ) { Ygraph_nodeEnumeratePush(graph); /* now draw the nodes which have not yet been drawn */ for (node = Ygraph_nodeEnumerate(graph,TRUE); node; node = Ygraph_nodeEnumerate(graph,FALSE) ) { (*printNode)(node); } Ygraph_nodeEnumeratePop(graph); } /* end for each node */ } /*--------------------------------------------------------- Sets up the users draw functions for Ygraph_draw. ---------------------------------------------------------*/ VOID Ygraph_drawFunctions(graph,userNodeDraw, userEdgeDraw) YGRAPHPTR graph; VOID (*userNodeDraw)(); VOID (*userEdgeDraw)(); { graph->userDrawNode = userNodeDraw; graph->userDrawEdge = userEdgeDraw; } /*--------------------------------------------------------- Get the current edge weight function ---------------------------------------------------------*/ INT (*Ygraph_getEdgeWeightFunction(graph))() YGRAPHPTR graph; { return( graph->userEdgeWeight ); } /*--------------------------------------------------------- Set the current edge weight function ---------------------------------------------------------*/ VOID Ygraph_setEdgeWeightFunction(graph,userEdgeWeight) YGRAPHPTR graph; INT (*userEdgeWeight)(); { graph->userEdgeWeight = userEdgeWeight; } /*--------------------------------------------------------- Call the users drawing functions for all required nodes To use this function first call Ygraph_drawFunctions(). The user's node draw function will be passed a node and a color. The user's edge draw function will be passed an edge and a color. Some sample edge and node draw function are below: VOID drawNode(node,color) YNODEPTR node; int color; { myNodeType n; n = (myNodeType) Ygraph_nodeData(node); TW3DdrawLine(0,n->x,n->y,n->z,n->x,n->y,n->z,color,0); } VOID drawEdge(edge,color) YEDGEPTR edge; int color; { myEdgeType e; e = (myEdgeType) Ygraph_edgeData(edge); TW3DdrawLine(0,e->x1,e->y1,e->z1,e->x2,e->y2,e->z2,color,0); } ---------------------------------------------------------*/ VOID Ygraph_drawRequired(graph) YGRAPHPTR graph; { YNODEPTR node; D("Ygraph_drawRequired", ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_drawRequired","bogus graph"); ); if ( graph->userDrawNode ) { /* now draw the nodes which have not yet been drawn */ for (node = (YNODEPTR) Ydset_enumerate(graph->sourceSet,TRUE); node; node = (YNODEPTR) Ydset_enumerate(graph->sourceSet,FALSE) ) { (*graph->userDrawNode)(node,node->color); } } /* end for each node */ TWflushFrame(); /* draw any pending events */ D("Ygraph_drawRequired", TWmessage("Waiting for keypress:"); getchar(); TWmessage("keypress acknowledged..."); ); } /*--------------------------------------------------------- Call the users drawing functions for all primed edges User must write drawing routines since library has no way of knowing what node and edge data is. To use this function first call Ygraph_drawFunctions(). The user's node draw function will be passed a node and a color. The user's edge draw function will be passed an edge and a color. Some sample edge and node draw function are below: VOID drawNode(node,color) YNODEPTR node; int color; { myNodeType n; n = (myNodeType) Ygraph_nodeData(node); TW3DdrawLine(0,n->x,n->y,n->z,n->x,n->y,n->z,color,0); } VOID drawEdge(edge,color) YEDGEPTR edge; int color; { myEdgeType e; e = (myEdgeType) Ygraph_edgeData(edge); TW3DdrawLine(0,e->x1,e->y1,e->z1,e->x2,e->y2,e->z2,color,0); } ---------------------------------------------------------*/ VOID Ygraph_drawPrime(graph) YGRAPHPTR graph; { YEDGEPTR edge; D("Ygraph_drawPrime", ASSERTNFAULT(Ygraph_verify(graph),"Ygraph_drawPrime","bogus graph"); ); if ( graph->userDrawEdge ) { /* now draw the nodes which have not yet been drawn */ for ( Ydeck_top(graph->primeDeck); Ydeck_notEnd(graph->primeDeck); Ydeck_down(graph->primeDeck ) ) { edge = (YEDGEPTR) Ydeck_getData(graph->primeDeck); (*graph->userDrawEdge)(edge,edge->color); } } /* end for each node */ TWflushFrame(); /* draw any pending events */ D("Ygraph_drawPrime", TWmessage("Waiting for keypress:"); getchar(); TWmessage("keypress acknowledged..."); ); } /*--------------------------------------------------------- Call the users drawing functions for all nodes and edges User must write drawing routines since library has no way of knowing what node and edge data is. To use this function first call Ygraph_drawFunctions(). The user's node draw function will be passed a node and a color. The user's edge draw function will be passed an edge and a color. Some sample edge and node draw function are below: VOID drawNode(node,color) YNODEPTR node; int color; { myNodeType n; n = (myNodeType) Ygraph_nodeData(node); TW3DdrawLine(0,n->x,n->y,n->z,n->x,n->y,n->z,color,0); } VOID drawEdge(edge,color) YEDGEPTR edge; int color; { myEdgeType e; e = (myEdgeType) Ygraph_edgeData(edge); TW3DdrawLine(0,e->x1,e->y1,e->z1,e->x2,e->y2,e->z2,color,0); } ---------------------------------------------------------*/ VOID Ygraph_draw(graph) YGRAPHPTR graph; { YEDGEPTR edge; YNODEPTR node; D("Ygraph_draw", ASSERTNFAULT(Ygraph_verify(graph),"generateTrees","bogus graph"); ); if ( graph->userDrawEdge ) { Ygraph_edgeEnumeratePush(graph); /* now draw the edges */ for (edge=Ygraph_edgeEnumerate(graph,TRUE); edge; edge=Ygraph_edgeEnumerate(graph,FALSE) ) { (*graph->userDrawEdge)(edge,edge->color); } /* end for each edge */ Ygraph_edgeEnumeratePop(graph); } if ( graph->userDrawNode ) { Ygraph_nodeEnumeratePush(graph); /* now draw the nodes which have not yet been drawn */ for (node = Ygraph_nodeEnumerate(graph,TRUE); node; node = Ygraph_nodeEnumerate(graph,FALSE) ) { (*graph->userDrawNode)(node,node->color); } Ygraph_nodeEnumeratePop(graph); } /* end for each node */ TWflushFrame(); /* draw any pending events */ D("Ygraph_draw", TWmessage("Waiting for keypress:"); getchar(); TWmessage("keypress acknowledged..."); ); } #ifdef TEST /* ################################################################## TEST OF GRAPH ROUTINES ################################################################## */ typedef struct { INT len; char *name ; } DATA, *DATAPTR ; static int compare_node( node1, node2 ) YNODEPTR node1; YNODEPTR node2; { DATAPTR n1; DATAPTR n2; n1 = Ygraph_nodeData(node1); n2 = Ygraph_nodeData(node2); return( strcmp(n1->name,n2->name) ); } /* end node */ static VOID print_node_data( node ) YNODEPTR node; { DATAPTR data ; data = (DATAPTR) Ygraph_nodeData(node); fprintf( stderr, "%s:%d ", data->name, data->len ) ; } /* end print_data() */ static VOID print_node_info( node ) YNODEPTR node; { DATAPTR data ; data = (DATAPTR) Ygraph_nodeData(node); fprintf( stderr, "node %s has %d neighbors\n", data->name, Ygraph_nodeDegree(node) ) ; } /* end print_data() */ static VOID print_edge_info( edge ) YEDGEPTR edge; { DATAPTR n1; DATAPTR n2; n1 = Ygraph_edgeNode1Data(edge); n2 = Ygraph_edgeNode2Data(edge); fprintf( stderr, "edge from "); fprintf( stderr, "%s\t ", n1->name ) ; fprintf( stderr, "to "); fprintf( stderr, "%s\t ", n2->name ) ; fprintf( stderr, "has weight = %d ", Ygraph_edgeWeight(edge) ) ; fprintf( stderr, "\n") ; } /* end print_data() */ static VOID free_data( data ) DATAPTR data; { YFREE( data->name ) ; YFREE( data ) ; } /* end print_data() */ static char *make_data( string ) char *string ; { DATAPTR data ; data = YMALLOC( 1, DATA ) ; data->len = strlen(string) + 1 ; data->name = YMALLOC( data->len, char ) ; strcpy( data->name, string ) ; return( (char *) data ) ; } /* end make_data */ main() { YGRAPHPTR graph; DATAPTR the; DATAPTR one; DATAPTR red; DATAPTR fox; DATAPTR jumped; DATAPTR silverish; DATAPTR n2; YNODEPTR theNode; YNODEPTR jumpedNode; YNODEPTR node; YEDGEPTR edge; YDECKPTR pathDeck; YdebugMemory( TRUE ) ; fprintf(stderr,"start\n"); /* initialize a graph with no compare edge function AND no graph flags */ graph = Ygraph_init(compare_node,NULL,NULL,NULL); /* make some data */ the = (DATAPTR) make_data("the"); one = (DATAPTR) make_data("one"); red = (DATAPTR) make_data("red"); fox = (DATAPTR) make_data("fox"); jumped = (DATAPTR) make_data("jumped"); silverish = (DATAPTR) make_data("silverish"); /* build the graph with edge weights = 1 but with no data */ Ygraph_edgeInsert(graph,NULL,1,the,one); Ygraph_edgeInsert(graph,NULL,1,one,red); Ygraph_edgeInsert(graph,NULL,1,red,fox); Ygraph_edgeInsert(graph,NULL,1,fox,jumped); Ygraph_edgeInsert(graph,NULL,1,the,silverish); Ygraph_edgeInsert(graph,NULL,1,silverish,fox); /* get the nodes which contain the data */ theNode = Ygraph_nodeFind(graph,the); jumpedNode = Ygraph_nodeFind(graph,jumped); /* verify integrity of graph */ Ygraph_verify(graph); /* perform a breath first search from starting with node "the" */ Ygraph_bfs(graph,theNode,NULL); /* find the shortest path from "the" to "jumped" */ pathDeck = Ygraph_path(graph,jumpedNode); /* print out the shortest path */ fprintf(stderr,"\nshortest path from `the` to `jumped`\n"); fprintf(stderr,"edge weights = 1\n"); while ( node = (YNODEPTR) Ydeck_pop(pathDeck) ) { print_node_data(node); } fprintf(stderr,"\n"); /* free the path deck */ Ydeck_free(pathDeck,NULL); /* now set all edge weights equal to number of chars in node2 data */ for ( edge = Ygraph_edgeEnumerate(graph,TRUE); edge; edge = Ygraph_edgeEnumerate(graph,FALSE) ) { n2 = Ygraph_edgeNode2Data(edge); Ygraph_edgeWeightSet(edge,n2->len); } /* perform a breath first search from starting with node "the" */ Ygraph_bfs(graph,theNode,NULL); /* find the shortest path from "the" to "jumped" */ pathDeck = Ygraph_path(graph,jumpedNode); /* print out the shortest path */ fprintf(stderr,"\nshortest path from `the` to `jumped`\n"); fprintf(stderr,"edge weights = number of chars word\n"); while ( node = (YNODEPTR) Ydeck_pop(pathDeck) ) { print_node_data(node); } fprintf(stderr,"\n"); /* print whole tree */ fprintf(stderr,"FINAL GRAPH\n"); fprintf(stderr,"===========\n"); Ygraph_dump(graph,print_node_info,print_edge_info); fprintf(stderr,"\n"); /* free the path deck */ Ydeck_free(pathDeck,NULL); /* free the graph */ Ygraph_free(graph, free_data, NULL); fprintf( stderr, "Final memory:%d\n", YgetCurMemUse() ) ; Yprint_stats( stderr ) ; Ydump_mem() ; exit(0) ; } #endif /* TEST */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/grid.c000066400000000000000000000112771305746555600205530ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: grid.c DESCRIPTION:These routines grid data to the specified grid. CONTENTS: YforceGrid( x , y ) INT *x , *y ; Ygridx( x ) INT *x ; Ygridx( x ) INT *x ; Ygridx_down( x ) INT *x ; Ygridy_down( y ) INT *y ; Ygridx_up( x ) INT *x ; Ygridy_up( y ) INT *y ; Ygrid_setx( x, offset ) INT x, offset ; Ygrid_sety( y, offset ) INT y, offset ; Ygrid_getx( x, offset ) INT *x, *offset ; Ygrid_gety( y, offset ) INT *y, *offset ; DATE: Oct 27, 1989 REVISIONS: Thu Apr 18 00:39:45 EDT 1991 - renamed functions so that names were consistent. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) grid.c version 1.4 4/18/91" ; #endif #include static INT offsetxS = 0 ; /* initially set offset to zero */ static INT offsetyS = 0 ; static INT xgridS = 1 ; /* default grid is one */ static INT ygridS = 1 ; /* ***************************************************************** */ /* force coordinate to closest xy grid position */ YforceGrid( x , y ) INT *x , *y ; { Ygridx( x ) ; Ygridy( y ) ; } /* end forceGrid */ /* force coordinate to closest x grid position */ Ygridx( x ) INT *x ; { INT newx ; newx = ( (*x - offsetxS) / xgridS ) * xgridS + offsetxS ; if( ABS(newx + xgridS - *x) < ABS(newx - *x) ) { newx += xgridS ; } /* now return values */ *x = newx ; } /* end Ygridy */ /* force coordinate to closest x grid position */ Ygridy( y ) INT *y ; { INT newy ; newy = ( (*y - offsetyS) / ygridS ) * ygridS + offsetyS ; if( ABS(newy + ygridS - *y) < ABS(newy - *y) ) { newy += ygridS ; } /* now return values */ *y = newy ; } /* end Ygridy */ /* force coordinate to smallest x grid position */ Ygridx_down( x ) INT *x ; { INT newx ; newx = ( (*x - offsetxS) / xgridS ) * xgridS + offsetxS ; /* now return values */ *x = newx ; } /* end Ygridx_down */ /* force coordinate to smallest y grid position */ Ygridy_down( y ) INT *y ; { INT newy ; newy = ( (*y - offsetyS) / ygridS ) * ygridS + offsetyS ; /* now return values */ *y = newy ; } /* end Ygridy_down */ /* round coordinate to larger x grid position */ Ygridx_up( x ) INT *x ; { INT newx ; newx = ( (*x - offsetxS) / xgridS ) * xgridS + offsetxS ; if( ABS(newx - *x)) { newx += xgridS ; } /* now return values */ *x = newx ; } /* end Ygridx_up */ /* round coordinate to larger y grid position */ Ygridy_up( y ) INT *y ; { INT newy ; newy = ( (*y - offsetyS) / ygridS ) * ygridS + offsetyS ; if( ABS(newy - *y)) { newy += ygridS ; } /* now return values */ *y = newy ; } /* end Ygridy_up */ Ygrid_setx( x, offset ) INT x, offset ; { xgridS = x ; offsetxS = offset ; } /* end Ygrid_setx */ Ygrid_sety( y, offset ) INT y, offset ; { ygridS = y ; offsetyS = offset ; } /* end Ygrid_sety */ Ygrid_getx( x, offset ) INT *x, *offset ; { *x = xgridS ; *offset = offsetxS ; } /* end Ygrid_getx */ Ygrid_gety( y, offset ) INT *y, *offset ; { *y = ygridS ; *offset = offsetyS ; } /* end Ygrid_gety */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/hash.c000066400000000000000000000252341305746555600205470ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: hash.c DESCRIPTION:This file contains the routines for building and maintaining a hash table. CONTENTS: DATE: Jul 7, 1988 REVISIONS: Nov 6, 1988 - added user defined hash delete function. Jan 18, 1989 - added delete operation albeit inefficient to hash_search routine. Apr 27, 1989 - changed to Y prefix. Apr 29, 1990 - added message.h Aug 3, 1990 - added hash_add as a convenience function. Oct 8, 1990 - made consistent with prototypes. Dec 8, 1990 - fixed Yhash_table_size. Fri Jan 18 18:38:36 PST 1991 - fixed to run on AIX. Thu Apr 18 00:40:49 EDT 1991 - renamed functions for consistency. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) hash.c version 3.11 12/15/91" ; #endif #include #include #include #include extern char *Ystrclone(char *); /* definitions local to this file only */ #define PRIMECOUNT 200 #define MINPRIMESIZE 23 /* static global to this file only */ static INT tablesize ; static YTABLEPTR *table ; YHASHPTR Yhash_table_create( numentries ) INT numentries ; { YHASHPTR hashtable ; INT Yhash_table_size() ; hashtable = YMALLOC( 1, YHASHBOX ) ; hashtable->size = tablesize = Yhash_table_size( numentries ) ; table = YCALLOC( tablesize, YTABLEPTR ) ; hashtable->hash_table = table ; hashtable->thread = NULL ; /* initialize list */ return(hashtable) ; } /* end Yhash_create */ INT Yhash_table_get( hashtable ) YHASHPTR hashtable ; { return(hashtable->size) ; } Yhash_table_delete(hashtable, userdelete ) YHASHPTR hashtable ; INT (*userdelete)() ; { INT i ; YTABLEPTR hptr , zapptr ; table = hashtable->hash_table ; tablesize = hashtable->size ; for( i = 0 ; i < tablesize ; i++ ) { for( hptr=table[i];hptr; ){ zapptr = hptr ; hptr = hptr->next ; /* execute user define delete function if requested */ if( userdelete ){ (*userdelete)(zapptr->data) ; } YFREE( zapptr ) ; } } YFREE( table ) ; YFREE( hashtable ) ; } /* returns true if conflict occured */ char *Yhash_search(hashtable, key, data, operation ) YHASHPTR hashtable ; char *key ; VOIDPTR data ; INT operation ; { #ifdef HASHFUNC1 INT i , len ; #else INT shift ; char *name ; #endif UNSIGNED_INT hsum = 0 ; YTABLEPTR curPtr, temptr, curTable, tempThread ; /* initialization */ table = hashtable->hash_table ; tablesize = hashtable->size ; #ifdef HASHFUNC1 len = strlen(key) ; for( i = 0 ;i < len; i++ ) { hsum += ( UNSIGNED_INT ) key[i] ; } #else /* FUNCTION hash_key */ name = key ; for (shift=1 ;*name; name++){ hsum = hsum + *name<next ) { if( strcmp(curPtr->key, key ) == STRINGEQ ){ if( operation == DELETE ){ /* delete item in table by making data NULL */ /* this is only a quick fix and should be */ /* modified in the future to remove the space */ curPtr->data = NULL ; /* operation a success so return -1 */ return( (char *) -1 ) ; } else { /* operation find or enter - return item */ return( curPtr->data ) ; } } } if( operation == ENTER ){ /* now save data */ table[hsum] = curTable = YMALLOC( 1, YTABLEBOX ) ; curTable->data = (char *) data ; curTable->key = (char *) Ystrclone( key ) ; curTable->next = temptr ; /* now fix thread which goes through hash table */ tempThread = hashtable->thread ; hashtable->thread = curTable ; curTable->threadNext = tempThread ; } } else { /* no list started at this hash */ if( operation == ENTER ){ /* enter into the table on an enter command */ curTable = table[hsum] = YMALLOC( 1, YTABLEBOX ) ; curTable->data = (char *) data ; curTable->key = (char *) Ystrclone( key ) ; curTable->next = NULL ; /* now fix thread which goes through hash table */ if( tempThread = hashtable->thread ){ hashtable->thread = curTable ; curTable->threadNext = tempThread ; } else { /* first entry into hash table */ hashtable->thread = curTable ; curTable->threadNext = NULL ; } /* thread fixed */ } else { /* cant find anything on a find operation */ return( NULL ) ; } } return( NULL ) ; /* no conflict on a enter */ } /* end hash_search */ /* hash add adds to table if it doesn't already exist - new flag will be set to true. If key already exists in table then hash add will not add it to the hash table but will notify the user by setting new flag to false. */ char *Yhash_add( hashtable, key, add_function, new_flag ) YHASHPTR hashtable ; char *key ; char *(*add_function)() ; BOOL *new_flag ; { #ifdef HASHFUNC1 INT i , len ; #else INT shift ; char *name ; #endif UNSIGNED_INT hsum = 0 ; YTABLEPTR curPtr, temptr, curTable, tempThread ; /* initialization */ table = hashtable->hash_table ; tablesize = hashtable->size ; #ifdef HASHFUNC1 len = strlen(key) ; for( i = 0 ;i < len; i++ ) { hsum += ( UNSIGNED_INT ) key[i] ; } #else /* FUNCTION hash_key */ name = key ; for (shift=1 ;*name; name++){ hsum = hsum + *name<next ) { if( strcmp(curPtr->key, key ) == STRINGEQ ){ /* item is currently in the table set */ /* new flag to false */ *new_flag = FALSE ; return( curPtr->data ) ; } } /* otherwise add to the table */ /* now save data */ table[hsum] = curTable = YMALLOC( 1, YTABLEBOX ) ; curTable->data = (*add_function)() ; curTable->key = (char *) Ystrclone( key ) ; curTable->next = temptr ; /* now fix thread which goes through hash table */ tempThread = hashtable->thread ; hashtable->thread = curTable ; curTable->threadNext = tempThread ; } else { /* no list started at this hash */ /* enter into the table on an enter command */ curTable = table[hsum] = YMALLOC( 1, YTABLEBOX ) ; curTable->data = (*add_function)() ; curTable->key = (char *) Ystrclone( key ) ; curTable->next = NULL ; /* now fix thread which goes through hash table */ if( tempThread = hashtable->thread ){ hashtable->thread = curTable ; curTable->threadNext = tempThread ; } else { /* first entry into hash table */ hashtable->thread = curTable ; curTable->threadNext = NULL ; } /* thread fixed */ } *new_flag = TRUE ; return( curTable->data ) ; /* no conflict on a enter */ } /* end hash_add */ INT Yhash_set_size(hashtable) YHASHPTR hashtable ; { INT count = 0 ; YTABLEPTR thread ; for( thread = hashtable->thread;thread;thread=thread->threadNext ){ count++; } return(count) ; } /*---------------------------- hash_table_size -------------------------*/ INT Yhash_table_size( minEntries ) INT minEntries; { INT i; BOOL isPrime; INT prime; INT testPrime; static INT primes[PRIMECOUNT] = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 991, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,1009,1013,1019, 1021,1031,1033,1039,1049,1051,1061,1063,1069,1087, 1091,1093,1097,1103,1109,1117,1123,1129,1151,1153, 1163,1171,1181,1187,1193,1201,1213,1217,1223,1229 }; if (minEntries <= MINPRIMESIZE){ return(MINPRIMESIZE); } else { testPrime = minEntries; /* test to see if even */ if ((testPrime % 2) == 0){ testPrime = testPrime + 1; } do { testPrime = testPrime + 2; isPrime = TRUE; for (i=0;i < PRIMECOUNT;i++){ prime = primes[i]; if (testPrime < prime*prime){ break; } if ((testPrime % prime) == 0){ isPrime = FALSE; break; } } } while (!(isPrime)); return(testPrime); } } /* FUNCTION Yhash_table_size */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/heap.c000066400000000000000000000360321305746555600205370ustar00rootroot00000000000000/* * Copyright (C) 1990-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /**************************************************************************** **************************************************************************** File : heap.c Author : Ted Stanion Date : Tue May 1 00:06:55 1990 Abstract : Implements a heap structure or priority queue. Each heap may have its own compare function. It is recommended that you use the predefined functions heap_cmp_ptr, heap_cmp_num and strcmp, if your keys are pointers, numbers or strings. If you create a heap with no function specified, heap_cmp_num is assumed. The following operations are defined: * create : creates an empty heap. * insert : insert an arbitrary key and data into the heap. * delete_min : delete and return the minimum heap element. * meld : returns the heap formed by combining two disjoint heaps. This implementation is based on Chapter 3.3 of Tarjan's SIAM book, Data_Structures_and_Network_Algorithms. We use a leftist heap in order to guarantee O(log n) time complexity. Revisions : 2 April 1991 -- Ted Stanion -- Hid HEAP_EL from user. June 1991 - Port to TimberWolf library. R.A.Weier October 1991 - Make changes for Gnu gcc, a strict compiler. R.A.Weier Futures : ; **************************************************************************** ****************************************************************************/ #include #ifndef lint static char Yheap_Id[] = "@(#) heap.c version 1.8 12/15/91"; #endif /**************************************************************************** Structure : heap_el Author : Ted Stanion Date : Mon Apr 30 22:59:47 1990 Abstract : Structure for holding a heap element. Points to the left and rite children of this element, and this elements key and data items. *****************************************************************************/ typedef struct heap_el { VOIDPTR data; INT rank; struct heap_el *left, *rite; } HEAP_EL_STRUCT, *HEAP_EL; /************************************************************************ * * * Access Macros * * * ************************************************************************/ #define get_data(e) ((e)->data) #define set_data(e,d) (e)->data = (d) #define get_rank(e) ((e) ? (e)->rank : 0) #define set_rank(e,r) (e)->rank = (r) #define get_left(e) ((e)->left) #define set_left(e,l) (e)->left = (l) #define get_rite(e) ((e)->rite) #define set_rite(e,r) (e)->rite = (r) /************************************************************************ * * * Local Functions * * * ************************************************************************/ static VOID free_all_els(P1(HEAP_EL)); static HEAP_EL meld(P3(HEAP_EL, HEAP_EL, INT (*cmp)())); static HEAP_EL mesh(P3(HEAP_EL, HEAP_EL, INT (*cmp)())); static YHEAPPTR allocate_heap(); static HEAP_EL allocate_heap_el(); static VOID free_heap(P1(YHEAPPTR)); static VOID free_heap_el(P1(HEAP_EL)); /************************************************************************ * * * Local Variables * * * ************************************************************************/ static long heaps_allocated = 0L; static long heap_els_allocated = 0L; /************************************************************************ * * * Local Defines * * * ************************************************************************/ #define GTR(fn,e1,e2) \ ((fn) == Yheap_cmp_num ? (get_data(e1) > get_data(e2)) : \ (fn) == Yheap_cmp_ptr ? (get_data(e1) > get_data(e2)) : \ (fn)(get_data(e1), get_data(e2)) > 0L) /*************************************************************************** Function : heap_create Author : Ted Stanion Date : Tue May 1 00:19:11 1990 Abstract : Returns a new heap structure. *****************************************************************************/ extern YHEAPPTR Yheap_init() { YHEAPPTR tmp; tmp = allocate_heap(); tmp->heap_cmp = Yheap_cmp_num; return tmp; } /* heap_create */ /**************************************************************************** Function : heap_create_with_parms Author : Ted Stanion Date : Fri Sep 21 11:27:59 1990 Abstract : Creates a new heap with a user specified compare function. *****************************************************************************/ extern YHEAPPTR Yheap_init_with_parms(fn) INT (*fn)(); { YHEAPPTR tmp; tmp = allocate_heap(); tmp->heap_cmp = fn; return tmp; } /* heap_create_with_parms */ /**************************************************************************** Function : heap_empty Author : Ted Stanion Date : Tue May 1 00:25:16 1990 Abstract : Removes all elements from a heap. Note: this function does not free the data or key items. *****************************************************************************/ extern VOID Yheap_empty(heap) YHEAPPTR heap; { free_all_els(heap->top); heap->top = NIL(HEAP_EL); } /* heap_clear */ /**************************************************************************** Function : heap_free Author : Ted Stanion Date : Tue May 1 16:56:02 1990 Abstract : Frees up a heap and all of its elements. *****************************************************************************/ extern VOID Yheap_free(heap) YHEAPPTR heap; { Yheap_empty(heap); free_heap(heap); } /* heap_free */ /**************************************************************************** Function : heap_insert Author : Ted Stanion Date : Tue May 1 00:29:08 1990 Abstract : Inserts a data item associated with a key into the heap. *****************************************************************************/ extern VOID Yheap_insert(heap, data) YHEAPPTR heap; VOIDPTR data; { HEAP_EL el; /********************************************************************** * * * Create a new heap element. * * * **********************************************************************/ el = allocate_heap_el(); el->data = data; el->rank = 1; /********************************************************************** * * * This new element is technically a heap by itself. This allows * * us to call MELD to get the new heap. * * * **********************************************************************/ heap->top = meld(el, heap->top, heap->heap_cmp); } /* heap_insert */ /**************************************************************************** Function : heap_delete_min Author : Ted Stanion Date : Tue May 1 17:06:59 1990 Abstract : Returns data associated with the heap element with the lowest valued key and deletes it from the heap. *****************************************************************************/ extern VOIDPTR Yheap_delete_min(heap) YHEAPPTR heap; { HEAP_EL el; VOIDPTR rtn; if (el = heap->top) { heap->top = meld(get_left(el), get_rite(el), heap->heap_cmp); rtn = get_data(el); free_heap_el(el); } else { /* if (el = ... */ rtn = (VOIDPTR) NULL; } return rtn; } /* heap_delete_min */ /**************************************************************************** Function : heap_meld Author : Ted Stanion Date : Tue May 1 17:38:14 1990 Abstract : Returns the heap formed by joining two disjoint heaps. This operation destroys h1 and h2 in the process. This procedure ASSUMES that h1 and h2 have the same compare function. The new heap is pointed to by h1. *****************************************************************************/ extern YHEAPPTR Yheap_meld(h1,h2) YHEAPPTR h1; YHEAPPTR h2; { if ((h1->heap_cmp) != (h2->heap_cmp)) { fprintf(stderr, "HEAP: melding heaps with different compare functions.\n"); abort(); } else { h1->top = meld(h1->top, h2->top, h1->heap_cmp); } /* if (h1->heap_cmp ... */ return h1; } /* heap_meld */ /**************************************************************************** Function : free_all_els Author : Ted Stanion Date : Wed May 2 09:42:11 1990 Abstract : Recursively frees all elements rooted at el. *****************************************************************************/ static VOID free_all_els(el) HEAP_EL el; { if (el != NIL(HEAP_EL)) { free_all_els(get_left(el)); free_all_els(get_rite(el)); free_heap_el(el); } /* if (el ... */ } /* free_all_els */ /**************************************************************************** Function : meld Author : Ted Stanion Date : Tue May 1 18:27:38 1990 Abstract : Performs meld operation on heaps rooted at E1 and E2 using compare function FN. *****************************************************************************/ static HEAP_EL meld(e1,e2,fn) HEAP_EL e1; HEAP_EL e2; INT (*fn)(); { if ( ! e1) return e2; else if ( ! e2) return e1; else return mesh(e1, e2, fn); } /* meld */ /**************************************************************************** Function : mesh Author : Ted Stanion Date : Tue May 1 18:30:46 1990 Abstract : Performs actual melding process on two non-empty heaps. *****************************************************************************/ static HEAP_EL mesh(e1,e2,fn) HEAP_EL e1; HEAP_EL e2; INT (*fn)(); { HEAP_EL tmp; if (GTR(fn, e1, e2)) { tmp = e1; e1 = e2; e2 = tmp; } e1->rite = (get_rite(e1) == NIL(HEAP_EL)) ? e2 : mesh(get_rite(e1), e2, fn); if (get_rank(get_left(e1)) < get_rank(get_rite(e1))) { tmp = get_rite(e1); e1->rite = get_left(e1); e1->left = tmp; } /* if (get_rank ... */ e1->rank = get_rank(get_rite(e1)) + 1; return e1; } /* mesh */ /**************************************************************************** Function : heap_cmp_num Author : Ted Stanion Date : Fri Sep 21 12:56:44 1990 Abstract : Compares two numbers. *****************************************************************************/ INT extern Yheap_cmp_num(x, y) INT x; INT y; { return x - y; } /* heap_cmp_num */ /**************************************************************************** Function : heap_cmp_ptr Author : Ted Stanion Date : Fri Sep 21 12:56:44 1990 Abstract : Compares two numbers. *****************************************************************************/ INT extern Yheap_cmp_ptr( x, y) VOIDPTR x; VOIDPTR y; { return (INT) ((long) x - (long) y); } /* heap_cmp_ptr */ /**************************************************************************** Function : allocate_heap Author : Ted Stanion Date : Fri Apr 20 13:38:51 1990 Abstract : Returns a HEAP structure from the free list. If the free list is empty, then more are allocated from memory. *****************************************************************************/ static YHEAPPTR allocate_heap() { YHEAPPTR tmp; tmp = YCALLOC(1,YHEAP); heaps_allocated++; return tmp; } /* allocate_heap */ /**************************************************************************** Function : allocate_heap_el Author : Ted Stanion Date : Fri Apr 20 13:38:51 1990 Abstract : Returns a HEAP_EL structure from the free list. If the free list is empty, then more are allocated from memory. *****************************************************************************/ static HEAP_EL allocate_heap_el() { HEAP_EL tmp; tmp = YCALLOC(1,HEAP_EL_STRUCT); tmp->data = (VOIDPTR)0; tmp->rank = -1; tmp->left = tmp->rite = NIL(HEAP_EL); heap_els_allocated++; return tmp; } /* allocate_heap_el */ /**************************************************************************** Function : free_heap Author : Ted Stanion Date : Tue May 1 19:16:16 1990 Abstract : Puts a HEAP structure back onto the free list. *****************************************************************************/ static VOID free_heap(heap) YHEAPPTR heap; { YFREE(heap); heaps_allocated--; } /* free_heap */ /**************************************************************************** Function : free_heap_el Author : Ted Stanion Date : Tue May 1 19:17:44 1990 Abstract : Puts a HEAP_EL structure back onto the free list. *****************************************************************************/ static VOID free_heap_el(el) HEAP_EL el; { YFREE(el); heap_els_allocated--; } /* free_heap_el */ /**************************************************************************** Function : heap_check_mem Author : Ted Stanion Date : Wed May 2 17:09:22 1990 Abstract : Prints out status of heap memory. *****************************************************************************/ extern VOID Yheap_check_mem() { fprintf(stderr,"\theaps_allocated = %d\n", heaps_allocated); fprintf(stderr,"\theap_els_allocated = %d\n", heap_els_allocated); } /* heap_check_mem */ /*-------------------------------- Yheap_verify: Verify heap data structures --------------------------------*/ extern INT Yheap_verify(heap) YHEAPPTR heap; { INT rc = TRUE; if ( YcheckDebug(heap) < sizeof(YHEAP) ) { fprintf(stderr,"tile memory corrupt\n"); rc = FALSE; } /* Future enhancements */ /* we need a heap_suc here to implement a clean search of heap tree */ /* OR create a recursive heal_el_verify */ return( rc ); } graywolf-0.1.4+20170307gite1bf319/src/Ylib/info.h000066400000000000000000000056641305746555600205710ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) info.h (Yale) version 3.10 1/30/92" FILE: info.h DESCRIPTION:include file for graphics screen routines CONTENTS: typedefs, and external routines for TWinfo record. DATE: Mar 21, 1989 - original coding moved from draw.h REVISIONS: Sep 23, 1989 - added color fields for TWtoggleColor() Oct 12, 1990 - modified structure to accommodate 4 draw windows. Dec 7, 1990 - added stipple switch to information. Mon Jan 7 18:17:44 CST 1991 - made SAFE_WAIT_TIME user programmable for slow machines. Thu Mar 7 01:23:40 EST 1991 - added refresh function so that dialog box works correctly. ----------------------------------------------------------------- */ #ifndef INFO_H #define INFO_H #include #define GRAPHICS "graywolf" /* the name of prog in Xdefaults */ #define MENUHEIGHT 20 /* give menu extra pixels in width */ #ifdef YDRAW_VARS #define EXTERN #else #define EXTERN extern #endif typedef struct { GC *graphicContext ; /* array of color contexts */ Display *dpy ; /* the display */ Window backWindow; /* the backing window */ Window drawWindow; /* the main drawing window */ Window rootWindow; /* the root window */ INT screen; /* the current screen */ char *fontname ; /* main font window font */ XFontStruct *fontinfo ; /* font information */ DOUBLE scaleFactor ; /* scale data to screen dim.*/ INT xoffset ; /* data offset to x screen dim.*/ INT yoffset ; /* data offset to y screen dim.*/ INT winwidth ; /* window width in pixels */ INT winheight ; /* window height in pixels */ INT winx ; /* window origin x from ul */ INT winy ; /* window origin y from ul */ BOOL *colorOn ; /* array of whether color is on */ BOOL stipple ; /* whether stipple has been requested*/ INT numColors ; /* number of colors */ char **colors ; /* names of the user given colors */ Pixmap pixmap ; /* pixmap for redraw after menus */ INT (*refresh_func)() ;/* store the refresh function */ } TWINFO, *TWINFOPTR ; /* ****************** GLOBALS ************************** */ /* GLOBAL VARIABLES */ EXTERN INT TWsafe_wait_timeG ;/* time to wait before redraw */ extern TWINFOPTR TWgetDrawInfo() ; /* TW library routines use this */ extern TWsetDrawInfo( P3( INT winheight, INT winwidth, Pixmap pixmap )) ; extern Window TWgetWindowId( P2(Display *dpy, Window backwindow) ) ; extern BOOL TWinitMenuWindow( P1(TWMENUPTR menu_fields) ) ; extern XFontStruct *TWgetfont( P2(char *fname, Font *font) ) ; #undef EXTERN #endif /* INFO_H */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/list.c000066400000000000000000000533601305746555600206000ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: list.c DESCRIPTION:Provides a generalized method for handling linked lists. Currently the only access routines make the list act like a generalized queue. Push and pop functions make it act like a LIFO queue or stack. Enqueue and pop make it act like a FIFO. A dequeue function is added for completeness. CONTENTS: DATE: Dec 9, 1989 REVISIONS: Oct 9, 1990 - rename routines for easier use. Thu Apr 19 22:29:18 1990 - revisions from Ted. 15 OCT 1990 -- Ted Stanion -- LIST_DELETE() function added. 31 JAN 1991 -- Ted Stanion -- Added capability to have sorted lists. New functions: Ylist_create_with_parms(); Ylist_insert_before(); Ylist_insert_after(); Ylist_insert_in_order(); Ylist_sort(); New macros; Ylist_for_all_safe() { } Ylist_for_all_end; 18 MAR 1991 -- Ted Stanion -- Added function LIST_APPEND(). 28 OCT 1991 -- Ted Stanion -- Added function LIST_FIND_AND_DELETE(). Made LIST_SORT into a quicksort for greater than 20 elements. LIST_SORT returns a new list. (Old undiscovered bug.) Sun Nov 3 12:54:08 EST 1991 - added to library. 12/09/91 - cleanup for non-ANSI compilers -R.A.Weier ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) list.c Yale Version 1.9 12/9/91" ; #endif #include /************************************************************************ * * * Internal Functions * * * ************************************************************************/ static YLIST insort(P1(YLIST list)); static YLIST quicksort(P1(YLIST list)); static YLIST allocate_list(); static YLIST_EL allocate_list_el(); static VOID free_list(P1(YLIST)); static VOID free_list_el(P1(YLIST_EL)); static INT def_comp(P2(VOIDPTR, VOIDPTR)); /************************************************************************ * * * Internal Variables * * * ************************************************************************/ static YLIST free_listS = NIL(YLIST); static YLIST_EL free_list_elS = NIL(YLIST_EL); static long lists_allocatedS = 0L; static long list_els_allocatedS = 0L; /************************************************************************ * * * Internal Macros * * * ************************************************************************/ #define COMP(l, d, e) \ ((l)->comp == def_comp ? (d) < (e) : \ (l)->comp((d), (e)) > 0L) #define EQ(l, d, e) ((COMP((l),(d),(e)) == 0) ? TRUE : FALSE) /**************************************************************************** Function : Ylist_create Author : Ted Stanion Date : Fri Apr 20 10:46:00 1990 Abstract : Creates a list. All other routines work on this list. *****************************************************************************/ YLIST Ylist_create() { YLIST list = allocate_list(); list->comp = def_comp; return list; } /* Ylist_create */ /************************************************************************* Function : Ylist_create_with_parms Author : Ted Stanion Date : Thu Jan 31 11:26:06 1991 Abstract : Creates a parameterized list. Currently the only parameter is a compare function. This function returns a positive value if the first argument should precede the second in the list, a negative value if the second should precede the first and zero if their order is irrelevant. **************************************************************************/ YLIST Ylist_create_with_parms(comp) INT (*comp)(); { YLIST list = allocate_list(); list->comp = comp; return list; } /* Ylist_create_with_parms */ /**************************************************************************** Function : Ylist_enqueue Author : Ted Stanion Date : Fri Apr 20 10:49:11 1990 Abstract : Puts a data item at the end of a list. *****************************************************************************/ VOID Ylist_enqueue(list, data) YLIST list; VOIDPTR data; { YLIST_EL el; el = allocate_list_el(); el->data = data; if (list->last == NIL(YLIST_EL)) list->first = list->last = el; else { list->last->next = el; el->prev = list->last; list->last = el; } /* if (list ... */ list->size++; } /* Ylist_enqueue */ /**************************************************************************** Function : Ylist_push Author : Ted Stanion Date : Fri Apr 20 10:54:10 1990 Abstract : Puts a data item at the beginning of a list. *****************************************************************************/ VOID Ylist_push(list, data) YLIST list; VOIDPTR data; { YLIST_EL el; el = allocate_list_el(); el->data = data; if (list->first == NIL(YLIST_EL)) list->first = list->last = el; else { list->first->prev = el; el->next = list->first; list->first = el; } /* if (list ... */ list->size++; } /* Ylist_push */ /************************************************************************* Function : Ylist_insert_after Author : Ted Stanion Date : Thu Jan 31 11:13:35 1991 Abstract : Insert DATA after ITEM in LIST. WARNING: No check is made to make sure ITEM really is in LIST. **************************************************************************/ VOID Ylist_insert_after(list, item, data) YLIST list; YLIST_EL item; VOIDPTR data; { YLIST_EL el, tmp; el = allocate_list_el(); el->data = data; if (list->last == item) { list->last = item->next = el; el->prev = item; } else { tmp = Ylist_next(item); item->next = el; el->prev = item; el->next = tmp; tmp->prev = el; } /* if (list ... */ list->size++; } /* Ylist_insert_after */ /************************************************************************* Function : Ylist_insert_before Author : Ted Stanion Date : Thu Jan 31 11:23:29 1991 Abstract : Insert DATA before ITEM in LIST. WARNING: No check is made to make sure ITEM really is in LIST. **************************************************************************/ VOID Ylist_insert_before(list, item, data) YLIST list; YLIST_EL item; VOIDPTR data; { YLIST_EL el, tmp; el = allocate_list_el(); el->data = data; if (list->first == item) { list->first = item->prev = el; el->next = item; } else { tmp = Ylist_prev(item); item->prev = el; el->next = item; el->prev = tmp; tmp->next = el; } /* if (list ... */ list->size++; } /* Ylist_insert_before */ /************************************************************************* Function : Ylist_insert_in_order Author : Ted Stanion Date : Thu Jan 31 11:42:10 1991 Abstract : Insert DATA into LIST in order using the compare function of LIST. **************************************************************************/ VOID Ylist_insert_in_order(list, data) YLIST list; VOIDPTR data; { YLIST_EL el; INT tmp; for (el = Ylist_first(list); el && ((tmp = COMP(list, Ylist_data(el), data)) > 0); el = Ylist_next(el)); if (el) Ylist_insert_before(list, el, data); else Ylist_enqueue(list, data); } /* list_insert_in_order */ /**************************************************************************** Function : Ylist_dequeue Author : Ted Stanion Date : Fri Apr 20 11:03:37 1990 Abstract : Returns the last data item of a list and deletes it from the list. *****************************************************************************/ VOIDPTR Ylist_dequeue(list) YLIST list; { YLIST_EL el; VOIDPTR data; if (Ylist_empty(list)) { fprintf(stderr, "LIST: Dequeue of empty list."); abort(); } el = list->last; if (list->first == list->last) list->first = list->last = NIL(YLIST_EL); else { list->last = list->last->prev; list->last->next = NIL(YLIST_EL); } /* if (list ... */ data = el->data; free_list_el(el); list->size--; return data; } /* list_dequeue */ /**************************************************************************** Function : Ylist_pop Author : Ted Stanion Date : Fri Apr 20 12:19:52 1990 Abstract : Returns the first item in a list and deletes it from the list. *****************************************************************************/ VOIDPTR Ylist_pop(list) YLIST list; { YLIST_EL el; VOIDPTR data; if (Ylist_empty(list)) { return NIL(VOIDPTR); } el = list->first; if (list->first == list->last) list->first = list->last = NIL(YLIST_EL); else { list->first = list->first->next; list->first->prev = NIL(YLIST_EL); } /* if (list ... */ data = el->data; free_list_el(el); list->size--; return data; } /* list_pop */ /************************************************************************* Function : Ylist_delete Author : Ted Stanion Date : Mon Oct 15 07:56:09 1990 Abstract : Deletes EL from LIST. Automatically disposes of EL. Do NOT do this inside of a list_for_all loop!!! **************************************************************************/ VOID Ylist_delete(list, el, user_delete) YLIST list; YLIST_EL el; INT (*user_delete)(); { if (el->prev) el->prev->next = el->next; else list->first = el->next; if (el->next) el->next->prev = el->prev; else list->last = el->prev; if( user_delete ){ (*user_delete)( Ylist_data(el) ) ; } free_list_el(el); list->size--; } /* Ylist_delete */ /************************************************************************* Function : Ylist_find_and_delete Author : Ted Stanion Date : Mon Oct 28 15:18:24 1991 Abstract : Searches LIST for element whit data element equal to DATA. If the LIST has a comparison function, it is used for equality checking, otherwise, the pointer must match. If the element is found, it is deleted from the list and the function returns TRUE. Otherwise, it returns FALSE. **************************************************************************/ BOOL Ylist_find_and_delete(list, data, user_delete ) YLIST list; VOIDPTR data; INT (*user_delete)(); { YLIST_EL el; BOOL found_it = FALSE; Ylist_for_all(list, el) { if (EQ(list, Ylist_data(el), data)) { found_it = TRUE; break; } /* if (EQ( ... */ } Ylist_for_all_end; if (found_it) { Ylist_delete(list, el, user_delete ) ; } /* if (found_it) ... */ return found_it; } /* Ylist_find_and_delete */ /************************************************************************* Function : Ylist_sort Author : Ted Stanion Date : Thu Jan 31 11:55:27 1991 Abstract : Sorts LIST using its compare function. Uses simple insertion sort. Should be modified to use a quicksort for large lists. **************************************************************************/ YLIST Ylist_sort(list) YLIST list; { if (list->size > 20) { list = quicksort(list); } else { list = insort(list); } /* if (list->size ... */ return list; } /* Ylist_sort */ /************************************************************************* Function : insort Author : Ted Stanion Date : Mon Oct 28 15:39:39 1991 Abstract : Sorts LIST using insertion sort. **************************************************************************/ static YLIST insort(list) YLIST list; { YLIST nu_list = Ylist_create_with_parms(list->comp); VOIDPTR data; while (!(Ylist_empty(list))) { data = Ylist_pop(list); Ylist_insert_in_order(nu_list, data); } /* while (not Ylist_empty( ... */ Ylist_free(list); return nu_list; } /* insort */ /************************************************************************* Function : quicksort Author : Ted Stanion Date : Mon Oct 28 15:42:20 1991 Abstract : Sorts LIST using QUICKSORT algorithm. **************************************************************************/ static YLIST quicksort(list) YLIST list; { YLIST before, after; VOIDPTR pivot, tmp; if (Ylist_size(list) > 1) { before = Ylist_create_with_parms(list->comp); after = Ylist_create_with_parms(list->comp); pivot = Ylist_pop(list); while (!(Ylist_empty(list))) { tmp = Ylist_pop(list); if (COMP(list, pivot, tmp) > 0) { Ylist_enqueue(after, tmp); } else { Ylist_enqueue(before, tmp); } /* if (COMP( ... */ } /* while (not Ylist_empty( ... */ before = Ylist_sort(before); after = Ylist_sort(after); Ylist_enqueue(before, pivot); if (Ylist_size(after) > 0) { Ylist_append(before, after); } /* if (Ylist_size( ... */ Ylist_free(after); Ylist_free(list); return before; } else { return list; } /* if (Ylist_size( ... */ } /* quicksort */ /************************************************************************* Function : Ylist_append Author : Ted Stanion Date : Mon Mar 18 17:44:23 1991 Abstract : Appends list L2 to the end of list L1. This is a destructive operation which destroys L2. (L2 is set to be an empty list.) L2 must still be freed by the user. **************************************************************************/ VOID Ylist_append( l1, l2) YLIST l1; YLIST l2; { l1->size = l1->size + l2->size; l1->last->next = l2->first; l2->first->prev = l1->last; l1->last = l2->last; l2->size = 0; l2->first = l2->last = NIL(YLIST_EL); } /* Ylist_append */ /**************************************************************************** Function : Ylist_clear Author : Ted Stanion Date : Fri Apr 20 13:35:10 1990 Abstract : Deletes all elements of a list. *****************************************************************************/ VOID Ylist_clear(list) YLIST list; { YLIST_EL el, el1; for (el = list->first; el; el = el1) { el1 = el->next; free_list_el(el); } /* for (el ... */ list->first = list->last = NIL(YLIST_EL); list->size = 0L; } /* list_clear */ /**************************************************************************** Function : Ylist_free Author : Ted Stanion Date : Fri Apr 20 13:37:50 1990 Abstract : Clears a list then frees it. *****************************************************************************/ VOID Ylist_free(list) YLIST list; { Ylist_clear(list); free_list(list); } /* Ylist_free */ /**************************************************************************** Function : allocate_list Author : Ted Stanion Date : Fri Apr 20 13:38:51 1990 Abstract : Returns a LIST structure from the free list. If the free list is empty, then more are allocated from memory. *****************************************************************************/ #define NUM_LISTS 10L static YLIST allocate_list() { YLIST tmp; long idx; static long last_id; if (!(free_listS)) { tmp = YMALLOC(NUM_LISTS, YLIST_STRUCT) ; for (idx = 0; idx < NUM_LISTS; idx++, tmp++) { tmp->next = free_listS; free_listS = tmp; } /* for (idx = 0; ... */ } /* if (not free_lists ... */ tmp = free_listS; free_listS = tmp->next; lists_allocatedS++; tmp->size = 0L; tmp->first = tmp->last = NIL(YLIST_EL); tmp->next = NIL(YLIST); return tmp; } /* allocate_list */ /**************************************************************************** Function : allocate_list_el Author : Ted Stanion Date : Fri Apr 20 13:43:45 1990 Abstract : Returns a LIST structure from the free list. If the free list is empty, then more are allocated from memory. *****************************************************************************/ #define NUM_LIST_ELS 50L static YLIST_EL allocate_list_el() { YLIST_EL tmp; long idx; static long last_id; if (!(free_list_elS)) { tmp = YMALLOC(NUM_LIST_ELS, YLIST_EL_STRUCT); for (idx = 0; idx < NUM_LIST_ELS; idx++, tmp++) { tmp->next = free_list_elS; free_list_elS = tmp; } /* for (idx = 0; ... */ } /* if (not free_list_els ... */ tmp = free_list_elS; free_list_elS = tmp->next; list_els_allocatedS++; tmp->data = NIL(VOIDPTR); tmp->next = tmp->prev = NIL(YLIST_EL); return tmp; } /* allocate_list_el */ /**************************************************************************** Function : free_list Author : Ted Stanion Date : Fri Apr 20 13:46:23 1990 Abstract : Puts a LIST structure back onto the free list. *****************************************************************************/ static VOID free_list(list) YLIST list; { list->next = free_listS; free_listS = list; lists_allocatedS--; } /* free_list */ /**************************************************************************** Function : free_list_el Author : Ted Stanion Date : Fri Apr 20 13:49:05 1990 Abstract : Puts a LIST_EL structure back onto the free list. *****************************************************************************/ static VOID free_list_el(el) YLIST_EL el; { el->next = free_list_elS; free_list_elS = el; list_els_allocatedS--; } /* free_list_el */ /************************************************************************* Function : def_comp Author : Ted Stanion Date : Thu Jan 31 11:53:01 1991 Abstract : Default compare function for lists. **************************************************************************/ static INT def_comp(d1, d2) VOIDPTR d1; VOIDPTR d2; { return ( (INT) d1 - (INT) d2 ) ; } /* def_comp */ /**************************************************************************** Function : list_check_mem Author : Ted Stanion Date : Wed May 2 17:11:01 1990 Abstract : Prints out status of list memory usage. *****************************************************************************/ VOID Ylist_check_mem() { printf("\tlists_allocated = %d\n", lists_allocatedS); printf("\tlist_els_allocated = %d\n", list_els_allocatedS); } /* Ylist_check_mem */ #ifdef TEST /********************************************************************/ /* */ /* Local Functions */ /* */ /********************************************************************/ static VOID Yprint_list( P1(YLIST list) ) ; static VOID ph1(); /**************************************************************************** Function : main Author : Ted Stanion Date : Wed May 2 09:09:16 1990 Abstract : Main driver. *****************************************************************************/ INT main(argc, argv) INT argc; char *argv[]; { char c; INT data; YLIST list; fprintf( stderr, "List testing program. Enter ? to start\n" ) ; list = Ylist_create(); while ((c = getchar()) != EOF) { switch (c) { case 'e' : (VOID) scanf("%d", &data); Ylist_enqueue(list, (VOIDPTR) data); break; case 'u' : (VOID) scanf("%d", &data); Ylist_push(list, (VOIDPTR) data); break; case 'd' : data = (int) Ylist_dequeue(list); printf("\t%d\n", data); break ; case 'o' : data = (int) Ylist_pop(list); printf("\t%d\n", data); break ; case 'c' : printf("Clearing list ...\n"); Ylist_clear(list); break; case 'p': Yprint_list(list); break; case 's': list = Ylist_sort(list); break; case 'q' : return; case 'h' : case '?' : printf("e : enqueue onto list.\n"); printf("u : push onto list.\n"); printf("d : dequeue element from list.\n"); printf("o : pop element from list.\n"); printf("p : print list.\n"); printf("s : sort list.\n"); printf("c : clear all elements from list.\n"); printf("q : quit.\n"); } /* switch(c ... */ } /* while ((c ... */ } /* main */ /**************************************************************************** Function : print_list Author : Ted Stanion Date : Wed May 2 09:53:11 1990 Abstract : Prints out a list. *****************************************************************************/ static VOID Yprint_list(list) YLIST list; { YLIST_EL el; printf("\t"); Ylist_for_all(list, el) { printf("%d ", (INT) Ylist_data(el)); } Ylist_for_all_end; printf("\n"); } /* print_list */ #endif /* TEST */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/log.c000066400000000000000000000063441305746555600204060ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: log.c DESCRIPTION:This file contains routines for logging the execution times of the program. CONTENTS: Ylog_msg( message ) char *message ; Ylog_start( message ) char *message ; DATE: May 7, 1989 - original coding. REVISIONS: Aug 7, 1989 - Moved to libary. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) log.c version 1.2 8/28/90" ; #endif #include #include #include #include static char cktNameS[LRECL] = " " ; /* put a message in the log file */ Ylog_msg( message ) char *message ; { INT timestamp ; /* seconds since Jan 1, 1970 */ char *time, *YcurTime() ; /* YcurTime returns ASCII time string */ char filename[LRECL] ; /* log file name */ FILE *fp ; /* logfile */ sprintf( filename, "%s.log", cktNameS ) ; fp = TWOPEN( filename, "a", ABORT ) ; time = YcurTime( ×tamp ) ; fprintf( fp, "time %8d %s:%s\n", timestamp, time, message ) ; TWCLOSE( fp ) ; } /* end log */ Ylog_start( design, message ) char *design ; char *message ; { INT timestamp ; /* seconds since Jan 1, 1970 */ char *time, *YcurTime() ; /* YcurTime returns ASCII time string */ char filename[LRECL] ; /* log file name */ FILE *fp ; /* logfile */ strcpy( cktNameS, design ) ; sprintf( filename, "%s.log", cktNameS ) ; fp = TWOPEN( filename, "a", ABORT ) ; time = YcurTime( ×tamp ) ; fprintf( fp,"####################################################\n"); fprintf( fp, "time %8d %s:%s\n", timestamp, time, message ) ; TWCLOSE( fp ) ; } /* end log */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/menus.c000066400000000000000000001656101305746555600207560ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: menus.c DESCRIPTION:graphic drawing routines for handling menus There are two windows of interest in this file: wS - parent window is the large TW drawing window. menuS - INT small window at the top of the large TW window. The name of the menus are displayed in the menuS window but when a menu is selected it is draw in the large wS window. The variables which have top in their name refer to the menuS window and variable with entry in their name refer to the menu entry pixmaps which are drawn in the large window. CONTENTS: TWinforMenus( ) INT TWsaveState() TWrestoreState() BOOL TWinitMenuWindow( menu_fields, parasite ) TWMENUPTR menu_fields ; BOOL parasite ; TWdrawMenus() static set_window_lights( flag ) BOOL flag ; static checkwindow_lights() INT TWcheckMouse() TWgetPt( x, y ) INT *x, *y ; TWmessage( message ) char *message ; char *TWgetString( directions ) char *directions ; BOOL TWgetPt2( x, y ) INT *x, *y ; BOOL TWcheckExposure() BOOL TWinterupt() TWcheckReconfig() TWfreeMenuWindows() TWMENUPTR TWread_menus( filename ) char *filename ; static char *cap_item( sptr ) char *sptr ; static debug_menus( menu_field ) TWMENUPTR menu_field ; DATE: Jan 25, 1989 - major rewrite of version 1.0 REVISIONS: Jan 31, 1989 - added screen routines. Feb 21, 1989 - original version of graphics routines. Mar 16, 1989 - turned off XSync in TWinterupt - too slow. Mar 22, 1989 - added info.h. Mar 23, 1989 - now TWinitMenus returns a boolean value signifying whether it was sucessful. May 10, 1989 - added parasite window properties. May 24, 1989 - fixed TWmessage and added TWDIR environ var. Jul 31, 1989 - fixed problem with NULL in TWgetPt2. Aug 16, 1989 - added user defined fonts and fixed problem with TWreconfigure and TWcheckExposure so that reconfigs work properly at least in nonparasite mode. Sep 11, 1989 - added subwindows for top menu window to make more user friendly. Sep 16, 1989 - all debug directed to stderr. Oct 6, 1989 - now menus can be compiled into program. Sep 15, 1990 - made a compromise fix for TWcheckExposure. Oct 11, 1990 - added sleep so that program won't spend much time in TWcheckMouse if nothing is going on for 10 secs. Oct 12, 1990 - Rewrote draw routines to use 4 windows and added pixmap for fast redraws. Oct 21, 1990 - fixed parasite resizing. Dec 27, 1990 - fixed multiple redraws on TWcheckReconfig. Dec 28, 1990 - worked on multiple redraws on slow nodes. Mon Jan 7 18:17:44 CST 1991 - made SAFE_WAIT_TIME user programmable for slow machines. Fri Jan 25 16:17:21 PST 1991 - now look for backspace or delete key when in window. Sat Feb 16 15:34:23 EST 1991 - now set input focus for TWgetString. Sun Feb 17 17:13:23 EST 1991 - added TWmouse_tracking routines for 3D graphics. Thu Mar 7 01:26:56 EST 1991 - tried to fix a SUN race condition. Thu Mar 28 14:36:22 EST 1991 - added three button mouse option. Wed Apr 17 23:38:31 EDT 1991 - put back missing Xselect input. Sun Apr 28 22:06:15 EDT 1991 - set colors right for reverse video. Wed Jul 24 15:59:59 CDT 1991 - added message window timeout. Sun Nov 3 12:53:20 EST 1991 - fixed gcc complaints. Thu Jan 30 00:10:58 EST 1992 - made expert mode for three button mouse key. Wed Feb 26 03:54:12 EST 1992 - added persistent windows and added dim features. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) menus.c (Yale) version 3.36 2/26/92" ; #endif #ifndef NOGRAPHICS #include #include #include #include #include #include #include #include #include #include #include #include #include #include "info.h" #define DEFAULT_TIMEOUT 10 * 1000 /* 10 seconds to timeout on message window */ /* data record for menu information */ typedef struct { Window top_window ; /* heading window for menu */ Window *window ; /* window for each menu entry */ char *name ; /* the name of this menu */ INT xpos ; /* x pos of entry menu in messageW */ INT name_len ; /* name length of top menu */ INT pix_len ; /* pixlength of top menu entry */ INT entry_wid ; /* width in pix of max menu entry */ INT numentries ; /* number of entries in menu */ INT *function ; /* function number of each entry */ char **entry ; /* name of each menu entry */ INT *entry_len ; /* len of each menu entry */ INT *xpos_adj ; /* position of each menu entry str */ INT width ; /* width of menu entry */ BOOL *bool_entry ; /* tells whether entry is boolean */ BOOL *state ; /* state of this window entry */ INT *function2 ; /* alternate function for boolean */ char **entry2 ; /* for Boolean entries */ INT *xpos_adj2 ; /* position of alternate menu entry*/ INT *entry_len2 ; /* len of each menu entry */ BOOL *enabled ; /* whether menu item is enable or not */ } MENUBOX, *MENUPTR ; static TWINFOPTR infoS ; /* information about main details */ static Display *dpyS; /* the display */ static Window menuS; /* the current menu window */ static Window drawS; /* the main draw window */ static Window backS; /* the backing window */ static Window messageS; /* the message display window */ static GC menuGCS ; /* graphics context for menus */ static GC menuRGCS ; /* reverse gc for turning on menus */ static INT screenS ; /* the current screen */ static UNSIGNED_INT backgrdS ; static UNSIGNED_INT foregrdS ; static INT winwidthS ; /* window width */ static MENUPTR *menuArrayS ; /* contains info about menus */ static XFontStruct *fontinfoS ; /* font information */ static Font fontS ; /* current font */ static INT numMenuS ; /* number of menus */ static INT stepsizeS ; /* spacing between menus in x direction */ static BOOL parasiteS=FALSE; /* whether this menu init is a parasite */ static Pixmap pixmapS ; /* offscreen copy of data */ static BOOL three_button_mouseS ; /* whether 3 button mouse */ static INT message_timeoutS ;/* how long to wait in message window */ static char persistent_messageS[LRECL];/* stores persistent message */ static BOOL persistenceS = TRUE ; /* whether message is persistent */ #define MENUKEYWORD "MENU" #define MENUBORDER 20 /* give menu extra pixels in width */ #define MENUYPOS 14 /* y position of top menu strings */ #define POS 5 /* start of MSG in pixels*/ #define WHITE 1 /* white parent gc is one in array */ #define BLACK 2 /* black parent gc is two in array */ #define CANCEL 0 /* code for cancel menu activity */ #define NUMWINDOWS 3 /* number of windows normally shown*/ #define DELETE_CH '\177' /* delete character */ #define BACKSPACE '\010' /* backspace character */ #define RETURN '\015' /* return charachter */ #define COMMENT '#' /* comment character in first col */ #define SLEEPTIME (unsigned) 2 /* sleep for two seconds */ /* define static functions */ static set_window_lights( P1(BOOL flag) ) ; static resize_windows( P2( INT winwidth, INT winheight ) ) ; static debug_menus( P1(TWMENUPTR menu_field) ) ; static draw_persistent_message( P1(char *message) ) ; /* get information from main draw routine and set it */ TWinforMenus( ) { TWINFOPTR TWgetDrawInfo() ; infoS = TWgetDrawInfo() ; /* save display info for future use */ dpyS = infoS->dpy ; screenS = infoS->screen ; drawS = infoS->drawWindow ; backS = infoS->backWindow ; pixmapS = infoS->pixmap ; fontinfoS = infoS->fontinfo ; fontS = fontinfoS->fid ; winwidthS = infoS->winwidth ; } /* end set StaticInfo */ INT TWsaveState() { /* turn off all event reporting to these windows */ XSelectInput(dpyS,drawS,NoEventMask) ; XSelectInput(dpyS,backS,NoEventMask) ; XSelectInput(dpyS,menuS,NoEventMask) ; XSelectInput(dpyS,messageS,NoEventMask) ; set_window_lights( FALSE ) ; /* next flush event queue by calling XSync with discard true */ XSync( dpyS, TRUE ) ; return( (INT) backS ) ; } /* end TWgetWindowId */ TWrestoreState() { long event_mask ; /* used to set input selection to window */ XWindowAttributes wattr; /* get the window attributes */ /* restore normal state to all the windows */ event_mask = ButtonPressMask ; XSelectInput(dpyS,menuS,event_mask); event_mask = StructureNotifyMask | SubstructureNotifyMask | VisibilityChangeMask ; if( three_button_mouseS ){ event_mask |= ButtonPressMask ; } XSelectInput(dpyS,backS,event_mask); event_mask = ExposureMask | ButtonPressMask ; XSelectInput(dpyS,drawS,event_mask); XSelectInput(dpyS,messageS,NoEventMask) ; set_window_lights( TRUE ) ; /* next flush event queue by calling XSync with discard true */ XSync( dpyS, TRUE ) ; /* now see if the user resized window in parasite */ TWinforMenus() ; XGetWindowAttributes( dpyS, backS, &wattr ) ; wattr.height -= 2 * MENUHEIGHT ; if( wattr.width != infoS->winwidth || wattr.height != infoS->winheight ){ resize_windows( wattr.width, wattr.height ) ; } } /* end TWgetWindowId */ /* retrieve the window information only occurs during a parasite */ Window TWgetWindowId( dpy, backwindow ) Display *dpy ; Window backwindow ; { Atom menuAtom ; /* need to store menu property */ Atom messageAtom ; /* need to store message property */ Atom drawAtom ; /* need to store draw property */ Atom actual ; /* actual atom return from XGetWindowProperty */ char windowIdString[LRECL] ; /* buffer for window id string */ unsigned char *prop; /* used to retrieve the property added to window */ int junk1 ; unsigned long junk2 ; /* ignore junk */ unsigned long length ; /* length of string */ backS = backwindow ; parasiteS = TRUE ; /* save for future use */ menuAtom = XInternAtom( dpy, "menuWindowId", FALSE ) ; messageAtom = XInternAtom( dpy, "messageWindowId", FALSE ) ; drawAtom = XInternAtom( dpy, "drawWindowId", FALSE ) ; /* if parasite get windows back by looking at menu and */ /* message properties stores in main window. Were stored */ /* there on creation of those windows during normal case */ XGetWindowProperty(dpy, backS, menuAtom, 0L, 200L, False, XA_STRING, &actual, &junk1, &junk2, &length, &prop); if( !(menuS = atoi( prop ))){ M( ERRMSG,"TWinitMenus","Could not find menu property\n" ) ; return( FALSE ) ; } XGetWindowProperty(dpy, backS, messageAtom, 0, 200, False, XA_STRING, &actual, &junk1, &junk2, &length, &prop); if( !(messageS = atoi( prop ))){ M( ERRMSG,"TWinitMenus","Could not find message property\n") ; return( FALSE ) ; } XGetWindowProperty(dpy, backS, drawAtom, 0, 200, False, XA_STRING, &actual, &junk1, &junk2, &length, &prop); if( !(drawS = atoi( prop ))){ M( ERRMSG,"TWinitMenus","Could not find draw property\n") ; return( FALSE ) ; } /* new to return draw window */ return( drawS ) ; } /* end TWgetWindowId */ /* perform initialization of menu windows */ BOOL TWinitMenuWindow( menu_fields ) TWMENUPTR menu_fields ; { MENUPTR menuptr ; /* temporary for speed */ TWMENUPTR mptr ; /* current field of the menu fields */ UNSIGNED_INT white, black ; INT menu ; /* counter for menus */ INT items ; /* counter for menu items */ INT length ; /* length of string */ INT i, j ; /* counters */ INT strwidth ; /* temp for calculating width of string in pixels */ INT xpos ; /* temp to calculate xposition of menu */ INT halfstep ; /* half the calculated stepsize */ INT entry_width ; /* size of entry pixmap in pixels */ INT entry ; /* keep count of entries in each menu */ long event_mask ; /* set up event catching with this mask */ Atom menuAtom ; /* need to store menu property */ Atom messageAtom ; /* need to store message property */ Atom drawAtom ; /* need to store draw property */ Atom actual ; /* actual atom return from XGetWindowProperty */ char windowIdString[LRECL] ; /* buffer for window id string */ char *prop; /* used to retrieve the property added to window */ INT junk1, junk2 ; /* ignore junk */ char *reply ; /* reply back from Xdefaults */ /* get static information from main draw module */ /* try to do crude object oriented programming */ TWinforMenus() ; black = BlackPixel(dpyS,screenS); white = WhitePixel(dpyS,screenS); backgrdS = black ; foregrdS = white ; menuAtom = XInternAtom( dpyS, "menuWindowId", FALSE ) ; messageAtom = XInternAtom( dpyS, "messageWindowId", FALSE ) ; drawAtom = XInternAtom( dpyS, "drawWindowId", FALSE ) ; if( parasiteS == FALSE ){ /* normal case - need to create menu window */ menuS = XCreateSimpleWindow( dpyS, backS, 1, 1, infoS->winwidth, MENUHEIGHT, 1L, white, backgrdS ) ; /* now raise menu window so we can see it */ XMapWindow( dpyS, menuS ) ; /* now create a message window below main window */ messageS = XCreateSimpleWindow( dpyS, backS, 1, infoS->winheight + MENUHEIGHT, infoS->winwidth, MENUHEIGHT,1L,white,backgrdS ) ; /* now raise message window so we can see it */ XMapWindow( dpyS, messageS ) ; XClearWindow( dpyS, messageS ) ; /* store the windowIds of the two window so that a parasite */ /* can find its way later */ sprintf( windowIdString, "%d", drawS ) ; /* store as a string */ XChangeProperty( dpyS, backS, drawAtom, XA_STRING, 8, PropModeAppend, (unsigned char *) windowIdString, strlen(windowIdString) ) ; sprintf( windowIdString, "%d", menuS ) ; /* store as a string */ XChangeProperty( dpyS, backS, menuAtom, XA_STRING, 8, PropModeAppend, (unsigned char *) windowIdString, strlen(windowIdString) ) ; sprintf( windowIdString, "%d", messageS ) ;/* store as a string */ XChangeProperty( dpyS, backS, messageAtom, XA_STRING, 8, PropModeAppend, (unsigned char *) windowIdString, strlen(windowIdString) ) ; } /* end normal case */ /* set graphic contexts */ menuGCS = infoS->graphicContext[WHITE] ; menuRGCS = infoS->graphicContext[BLACK] ; /* user deliberately gave us a NULL menu so we have no more work */ if( !(menu_fields) ){ return( TRUE ) ; } if( XGetDefault( dpyS, GRAPHICS, "three_button_mouse" )){ three_button_mouseS = TRUE ; event_mask = StructureNotifyMask | SubstructureNotifyMask | VisibilityChangeMask | ButtonPressMask ; XSelectInput(dpyS,backS,event_mask) ; } else { three_button_mouseS = FALSE ; } if( reply = XGetDefault( dpyS, GRAPHICS, "message_timeout" )){ /* time is in milliseconds */ message_timeoutS = atoi( reply ) * 1000 ; } else { message_timeoutS = DEFAULT_TIMEOUT ; } /* count number of menus and menu items */ numMenuS = 0 ; items = 0 ; for( i=0; menu_fields[i].item ; i++ ){ if( menu_fields[i].menuNotItem ){ numMenuS++ ; } items++ ; } /* allocate memory for menu data */ menuArrayS = YMALLOC( numMenuS, MENUPTR ) ; for( i=0; i< numMenuS; i++ ){ menuArrayS[i] = YCALLOC( 1, MENUBOX ) ; } menu = -1 ; for( i=0; i < items; i++ ){ mptr = &(menu_fields[i]) ; if( mptr->menuNotItem ){ /* start of a new menu */ /* increment menu count */ menuptr = menuArrayS[++menu] ; /* find width of menu string in characters */ length = strlen( mptr->item ) ; menuptr->name_len = length ; /* find width of menu in pixels */ menuptr->pix_len = XTextWidth( fontinfoS, mptr->item, length ) ; /* save menu name */ menuptr->name = Ystrclone( mptr->item ) ; } else if( menu >= 0 ){ /* avoid obvious error if menu -1 */ /* add to number of entries */ menuArrayS[menu]->numentries++ ; /* find maximum length of entries of this menu */ length = strlen( mptr->item ) ; strwidth = XTextWidth( fontinfoS, mptr->item, length ) ; menuArrayS[menu]->entry_wid = MAX( menuArrayS[menu]->entry_wid, strwidth ) ; if( mptr->bool_item ){ /* also check the complement */ length = strlen( mptr->bool_item ) ; strwidth = XTextWidth( fontinfoS,mptr->bool_item,length ); menuArrayS[menu]->entry_wid = MAX( menuArrayS[menu]->entry_wid, strwidth ) ; } } } if( numMenuS < 0 || numMenuS != ++menu ){ M( ERRMSG, "initMenus", "Problems with menu array\n" ) ; return( FALSE ) ; } /* first calculate position of the menus based on equal spacing */ stepsizeS = winwidthS / numMenuS ; halfstep = stepsizeS / 2 ; xpos = halfstep ; /* placement of first menu */ /* build menus */ menu = -1 ; for( i=0; i < items; i++ ){ mptr = &(menu_fields[i]) ; if( mptr->menuNotItem ){ /* start of a new menu */ /* increment menu count */ menuptr = menuArrayS[++menu] ; /* save where to draw menu title in menu window */ menuptr->xpos = halfstep - menuptr->pix_len / 2 ; menuptr->width = entry_width = menuptr->entry_wid + MENUBORDER ; /* create a top subwindow */ menuptr->top_window = XCreateSimpleWindow( dpyS, menuS, xpos - halfstep, 0, stepsizeS, MENUHEIGHT, 0L, black, backgrdS ) ; /* now raise window so we can see it */ XMapWindow( dpyS, menuptr->top_window ) ; /* set the events for top subwindow */ event_mask = EnterWindowMask | LeaveWindowMask ; XSelectInput(dpyS,menuptr->top_window,event_mask) ; /* create an array of simple windows for menus */ menuptr->window = YMALLOC( menuptr->numentries, Window ) ; for( j=0; j< menuptr->numentries; j++ ){ menuptr->window[j] = XCreateSimpleWindow( dpyS, backS, xpos - menuptr->width / 2, (j+1) * MENUHEIGHT, entry_width, MENUHEIGHT, 1L, black, backgrdS ) ; } /* now create entry array for each menu entry string */ menuptr->entry = YMALLOC( menuptr->numentries, char * ) ; /* now create function array for each entry window */ menuptr->function = YMALLOC( menuptr->numentries, INT ) ; /* now create adjusted position array for each menu entry */ menuptr->xpos_adj = YMALLOC( menuptr->numentries, INT ) ; /* now create name len array for each menu entry */ menuptr->entry_len = YMALLOC( menuptr->numentries, INT ) ; /* now create enabled array for each entry window */ menuptr->enabled = YMALLOC( menuptr->numentries, BOOL ) ; /* now create second version of arrays for Boolean */ /* complementary state */ menuptr->bool_entry = YMALLOC( menuptr->numentries, BOOL ) ; menuptr->state = YMALLOC( menuptr->numentries, BOOL ) ; menuptr->entry2 = YMALLOC( menuptr->numentries, char * ) ; menuptr->function2 = YCALLOC( menuptr->numentries, INT ) ; menuptr->xpos_adj2 = YMALLOC( menuptr->numentries, INT ) ; /* now create name len array for each menu entry */ menuptr->entry_len2 = YMALLOC( menuptr->numentries, INT ) ; entry = 0 ; /* reset entry */ /* now update position of next menu */ xpos += stepsizeS ; } else { length = strlen( mptr->item ) ; /* save string in array */ menuptr->entry[entry] = Ystrclone( mptr->item ) ; /* save string len in array */ menuptr->entry_len[entry] = length ; /* save function number - last token */ menuptr->function[entry] = mptr->action_index ; menuptr->enabled[entry] = TRUE ; strwidth = XTextWidth( fontinfoS, mptr->item, length ) ; /* save where to draw string */ menuptr->xpos_adj[entry] = (menuptr->width-strwidth) / 2 ; if( mptr->bool_item ){ menuptr->bool_entry[entry] = TRUE ; length = strlen( mptr->bool_item ) ; /* save string in array */ menuptr->entry2[entry] = Ystrclone( mptr->bool_item ) ; /* save string len in array */ menuptr->entry_len2[entry] = length ; /* save function number - last token */ menuptr->function2[entry] = mptr->action_indexb ; strwidth = XTextWidth( fontinfoS,mptr->bool_item,length ); /* save where to draw string */ menuptr->xpos_adj2[entry] = (menuptr->width - strwidth) / 2 ; /* set initial state 1 means first entry set active */ menuptr->state[entry] = mptr->bool_init ; } else { /* number of tokens == 2 */ menuptr->bool_entry[entry] = FALSE ; } /* increment entry for next string */ entry++ ; } } /* end for loop */ /* now enable it so we can see mouse button in this window */ event_mask = ButtonPressMask ; XSelectInput(dpyS,menuS,event_mask); /* sucessful if we got to here */ return( TRUE ) ; } /* end TWinitMenuWindow */ TWdrawMenus() { INT i ; MENUPTR menuptr ; XClearWindow( dpyS, menuS ) ; for( i = 0; i< numMenuS ; i++ ){ menuptr = menuArrayS[i] ; XClearWindow( dpyS, menuptr->top_window ) ; XDrawString( dpyS, menuptr->top_window, menuGCS, menuptr->xpos, MENUYPOS, menuptr->name, menuptr->name_len ) ; } XFlush( dpyS ) ; } /* end TWdrawMenus */ /* turn top window entering and leaving lights */ static set_window_lights( flag ) BOOL flag ; { INT i ; /* window counter */ MENUPTR menuptr ; /* pointer to current window */ long event_mask ; /* used to set input selection to window */ if( flag ){ /* turn on menu subwindows */ event_mask = EnterWindowMask | LeaveWindowMask ; for( i = 0; i< numMenuS ; i++ ){ menuptr = menuArrayS[i] ; XSelectInput(dpyS,menuptr->top_window,event_mask) ; } } else { /* turn off menu subwindows */ for( i = 0; i< numMenuS ; i++ ){ menuptr = menuArrayS[i] ; XSelectInput(dpyS,menuptr->top_window,NoEventMask) ; } } } /* end set_window_lights */ /* draw whether cursor is entering window */ static BOOL checkwindow_lights() { long event_mask ; /* used to set input selection to window */ INT i ; /* window counter */ MENUPTR menuptr ; /* menu pointer */ Window win ; /* match window */ BOOL foundWindow; /* flag to match window */ XEvent event ; /* describes entering or leaving event */ event_mask = EnterWindowMask | LeaveWindowMask ; foundWindow = FALSE ; if( XCheckMaskEvent( dpyS, event_mask, &event ) ){ switch( event.type ){ case EnterNotify: /* light up window */ /* find window match */ win = event.xcrossing.window ; foundWindow = FALSE ; for( i = 0; i < numMenuS; i++ ){ if( win == menuArrayS[i]->top_window ){ menuptr = menuArrayS[i] ; foundWindow = TRUE ; break ; } } /* end search for window */ if( foundWindow ){ /* a match light up window */ XFillRectangle( dpyS,win, menuGCS, 2,2, stepsizeS-2, MENUHEIGHT-4 ) ; XDrawImageString( dpyS, win, menuRGCS, menuptr->xpos, MENUYPOS, menuptr->name, menuptr->name_len ) ; } break ; case LeaveNotify: /* turn off window */ /* find window match */ win = event.xcrossing.window ; foundWindow = FALSE ; for( i = 0; i < numMenuS; i++ ){ if( win == menuArrayS[i]->top_window ){ menuptr = menuArrayS[i] ; foundWindow = TRUE ; break ; } } /* end search for window */ if( foundWindow ){ /* turn off window */ XClearWindow( dpyS, win ) ; XDrawString( dpyS, win, menuGCS, menuptr->xpos, MENUYPOS, menuptr->name, menuptr->name_len ) ; } break ; } /* end switch */ } return( foundWindow ) ; } /* end checkwindow_lights */ /* check to see mouse button was click. If true put up appropriate */ /* menu and return value to user */ INT TWcheckMouse() { BOOL foundWindow ; /* used in window search to find match */ XEvent event ; /* describes button event */ INT i ; /* menu desired by user */ INT x ; /* pixel location button was pushed */ INT menu_requested ; /* the menu the user requested */ long event_mask ; /* setup menus */ Window win ; /* temporary for selected menu window */ MENUPTR menuptr ; /* temporary for selected menu record */ BOOL press ; /* tells whether button has been pushed */ GC menu_GC ; /* normal menu graphics context */ GC reverse_menuGC ; /* reverse menu context */ static INT last_timeL=0;/* the last time we interupted */ static INT last_commandL = CANCEL ; /* the last command issued */ static INT countL = 0 ; /* the last command issued */ INT cur_time ; /* the current time since start of process */ /* now avoid looking for interuptions all the time */ /* it take too much time*/ Ytimer_elapsed( &cur_time ) ; if( cur_time - last_timeL > 10000 ){ sleep( (UNSIGNED_INT) 1 ) ; } /* always set window lights on in this routine */ set_window_lights( TRUE ) ; /* always check for window reconfiguration calls */ TWcheckReconfig() ; if( checkwindow_lights() ){ last_timeL = cur_time ; } /* check if there is any mouse activity */ if( three_button_mouseS ){ press = XCheckMaskEvent( dpyS, ButtonPressMask,&event ) ; D( "TWcheckMouse", if( press ){ fprintf( stderr, "window = %d\n", event.xbutton.window ) ; } ) ; if(!(press)){ /* nothin' shakin' */ return( CANCEL ) ; } else if( event.xbutton.window != menuS ){ if( event.xbutton.button == 2 ){ if( last_commandL != CANCEL ){ TWmessage( "Repeating last command..." ) ; if( ++countL <= 3 ){ (VOID) sleep( (unsigned) 2 ) ; } return( last_commandL ) ; } } /* nothin' shakin' */ return( CANCEL ) ; } } else { /* a one button mouse */ press = XCheckTypedWindowEvent( dpyS,menuS,ButtonPress,&event ) ; if(!(press)){ /* nothin' shakin' */ return( CANCEL ) ; } } last_timeL = cur_time ; /* ****** otherwise process the mouse button press ******** */ D( "TWcheckMouse", fprintf( stderr,"Button event-button:%d\n",event.xbutton.button); ) ; /* now disable top menu so we cant get false clicks */ event_mask = NoEventMask ; XSelectInput(dpyS,menuS,event_mask); /* now disable main window clicks so we cant get false clicks */ event_mask = NoEventMask ; XSelectInput(dpyS,drawS,event_mask) ; /* now draw menus */ TWdrawMenus() ; /* determine which menu has been selected */ x = event.xbutton.x ; i = x / stepsizeS ; /* make sure we are in range */ if( i >= numMenuS ){ i = numMenuS - 1 ; } /* pick window and menu for speed */ menuptr = menuArrayS[i] ; /* show all windows for this menu and initialize input selection*/ /* next draw the menu entry string */ event_mask = ButtonPressMask | EnterWindowMask | LeaveWindowMask ; for( i = 0 ; i < menuptr->numentries; i++ ){ XMapRaised( dpyS, menuptr->window[i] ) ; XSelectInput(dpyS,menuptr->window[i],event_mask); XClearWindow( dpyS, menuptr->window[i] ) ; /* check to see if we have a boolean menu entry */ if( menuptr->enabled[i] ){ menu_GC = menuGCS ; } else { menu_GC = infoS->graphicContext[TWGRAY] ; } if( menuptr->bool_entry[i] ){ /* see what state we are in */ if( menuptr->state[i] ){ /* always draw what to change to */ XDrawString( dpyS, menuptr->window[i], menu_GC, menuptr->xpos_adj2[i], MENUYPOS, menuptr->entry2[i], menuptr->entry_len2[i] ) ; } else { /* draw the complement */ XDrawString( dpyS, menuptr->window[i], menu_GC, menuptr->xpos_adj[i], MENUYPOS, menuptr->entry[i], menuptr->entry_len[i] ) ; } } else { /* regular menu entry */ XDrawString( dpyS, menuptr->window[i], menu_GC, menuptr->xpos_adj[i], MENUYPOS, menuptr->entry[i], menuptr->entry_len[i] ) ; } } /* now draw menus */ XFlush( dpyS ) ; /* now look for button press */ press = FALSE ; menu_requested = -1 ; while(!(press )){ if( XCheckMaskEvent( dpyS, event_mask, &event ) ){ switch( event.type ){ case ButtonPress: /* how we exit */ win = event.xbutton.window ; /* window event occurred */ for( i = 0; i < menuptr->numentries; i++ ){ if( win == menuptr->window[i] && menuptr->enabled[i] ){ menu_requested = i ; press = TRUE ; } } break ; case EnterNotify: /* light up window */ /* find window match */ win = event.xcrossing.window ; foundWindow = FALSE ; for( i = 0; i < menuptr->numentries; i++ ){ if( win == menuptr->window[i] ){ /* a match if enabled */ foundWindow = TRUE ; break ; } } /* end search for window */ if( foundWindow ){ /* a match - light up window */ if( menuptr->enabled[i] ){ menu_GC = menuGCS ; reverse_menuGC = menuRGCS ; } else { menu_GC = infoS->graphicContext[TWGRAY] ; reverse_menuGC = infoS->graphicContext[TWGRAY] ; } XFillRectangle( dpyS,event.xcrossing.window, menu_GC, 0,0,menuptr->width,MENUHEIGHT ) ; /* check for boolean entry */ if( menuptr->bool_entry[i] ){ /* see what state we are in */ if( menuptr->state[i] ){ /* always draw what to change to */ XDrawImageString( dpyS, menuptr->window[i], reverse_menuGC, menuptr->xpos_adj2[i], MENUYPOS, menuptr->entry2[i], menuptr->entry_len2[i]) ; } else { /* draw the complement */ XDrawImageString( dpyS, menuptr->window[i], reverse_menuGC, menuptr->xpos_adj[i], MENUYPOS, menuptr->entry[i],menuptr->entry_len[i]) ; } } else { /* regular menu entry */ XDrawImageString( dpyS, menuptr->window[i], reverse_menuGC, menuptr->xpos_adj[i], MENUYPOS, menuptr->entry[i], menuptr->entry_len[i] ) ; } } break ; case LeaveNotify: /* turn off window */ /* find window match */ win = event.xcrossing.window ; foundWindow = FALSE ; for( i = 0; i < menuptr->numentries; i++ ){ if( win == menuptr->window[i] ){ foundWindow = TRUE ; break ; } } /* end search for window */ if( foundWindow ){ /* turn off window */ XClearWindow( dpyS, menuptr->window[i] ) ; /* check for boolean entry */ if( menuptr->enabled[i] ){ menu_GC = menuGCS ; } else { menu_GC = infoS->graphicContext[TWGRAY] ; } if( menuptr->bool_entry[i] ){ /* see what state we are in */ if( menuptr->state[i] ){ /* always draw what to change to */ XDrawString( dpyS, menuptr->window[i], menu_GC, menuptr->xpos_adj2[i], MENUYPOS, menuptr->entry2[i], menuptr->entry_len2[i]) ; } else { /* draw the complement */ XDrawString( dpyS, menuptr->window[i], menu_GC, menuptr->xpos_adj[i], MENUYPOS, menuptr->entry[i],menuptr->entry_len[i]) ; } } else { /* regular menu entry */ XDrawString( dpyS, menuptr->window[i], menu_GC, menuptr->xpos_adj[i], MENUYPOS, menuptr->entry[i], menuptr->entry_len[i] ) ; } } break ; } } } /* we got an answer unmap window and turn off events for these */ /* windows */ event_mask = NoEventMask ; for( i = 0 ; i < menuptr->numentries; i++ ){ XUnmapWindow( dpyS, menuptr->window[i] ) ; XSelectInput(dpyS,menuptr->window[i],event_mask); } /* now again enable top menu so we can get clicks */ event_mask = ButtonPressMask ; XSelectInput(dpyS,menuS,event_mask); /* turn on the drawing window */ event_mask = ExposureMask | ButtonPressMask ; XSelectInput(dpyS,drawS,event_mask); XCopyArea( dpyS, pixmapS, drawS, menuGCS, 0L, 0L, infoS->winwidth, infoS->winheight, 0L, 0L ) ; /* determine which menu entry has been selected */ if( menu_requested >= 0 ){ /* we need to set the state to complement if boolean menu */ if( menuptr->bool_entry[menu_requested] ){ if( menuptr->state[menu_requested] ){ /* was true change to false */ menuptr->state[menu_requested] = FALSE ; last_commandL = menuptr->function2[menu_requested] ; D( "TWcheckMouse",fprintf( stderr,"return %d\n", last_commandL ) ) ; return( last_commandL ) ; } else { /* was false change to true */ menuptr->state[menu_requested] = TRUE ; last_commandL = menuptr->function[menu_requested] ; D( "TWcheckMouse",fprintf( stderr, "return %d\n", last_commandL ) ) ; return( last_commandL ) ; } } last_commandL = menuptr->function[menu_requested] ; D( "TWcheckMouse", fprintf( stderr, "return %d\n", last_commandL ) ) ; return( last_commandL ) ; } /* outside windows return cancel */ return( CANCEL ) ; } /* end TWcheckMouse */ TWdisableMenu( menu_item ) INT menu_item ; { INT menu ; /* counter */ INT entry ; /* counter */ MENUPTR menuptr ; /* temporary for selected menu record */ for( menu = 0 ; menu < numMenuS; menu++ ){ menuptr = menuArrayS[menu] ; for( entry = 0 ; entry < menuptr->numentries; entry++ ){ if( menu_item == menuptr->function[entry] ){ menuptr->enabled[entry] = FALSE ; return ; } if( menu_item == menuptr->function2[entry] ){ menuptr->enabled[entry] = FALSE ; return ; } } } } /* end TWdisableMenu() */ TWenableMenu( menu_item ) INT menu_item ; { INT menu ; /* counter */ INT entry ; /* counter */ MENUPTR menuptr ; /* temporary for selected menu record */ for( menu = 0 ; menu < numMenuS; menu++ ){ menuptr = menuArrayS[menu] ; for( entry = 0 ; entry < menuptr->numentries; entry++ ){ if( menu_item == menuptr->function[entry] ){ menuptr->enabled[entry] = TRUE ; return ; } if( menu_item == menuptr->function2[entry] ){ menuptr->enabled[entry] = TRUE ; return ; } } } } /* end TWenableMenu() */ TWgetPt( x, y ) INT *x, *y ; { BOOL press ; /* tells whether button has been pushed */ XEvent event ; /* describes button event */ INT xtemp, ytemp ; /* pixel location button was pushed */ long event_mask ; /* setup menus */ /* turn on event mask for main drawing window - known as drawS */ event_mask = ExposureMask | ButtonPressMask ; XSelectInput(dpyS,drawS,event_mask); /* now disable top menu so we cant get false clicks */ event_mask = NoEventMask ; XSelectInput(dpyS,menuS,event_mask); /* now look for button press */ press = FALSE ; while(!(press )){ press = XCheckTypedWindowEvent( dpyS,drawS,ButtonPress,&event ); if( press ){ /* now disable window so we can ignore extraneous clicks */ event_mask = ExposureMask ; XSelectInput(dpyS,drawS,event_mask); /* determine which menu entry has been selected */ xtemp = event.xbutton.x ; ytemp = event.xbutton.y ; /* account for inversion of y axis */ ytemp = infoS->winheight - ytemp ; /* now reverse scale of coordinates */ xtemp = (INT) ( (DOUBLE) xtemp / infoS->scaleFactor ) ; ytemp = (INT) ( (DOUBLE) ytemp / infoS->scaleFactor ) ; /* now apply data offset */ *x = xtemp - infoS->xoffset ; *y = ytemp - infoS->yoffset ; D( "TWgetPt", fprintf( stderr, "pt = (%d,%d)\n", *x, *y ) ) ; } } /* now again enable top menu so we can get clicks */ event_mask = ButtonPressMask ; XSelectInput(dpyS,menuS,event_mask); } /* end TWgetPt */ TWmessage( message ) char *message ; { if( persistenceS ){ if( message ){ strcpy( persistent_messageS, message ) ; } else { persistent_messageS[0] = EOS ; } } draw_persistent_message( message ) ; } /* end TWmessage */ TWmessagePersistence(flag) BOOL flag ; { persistenceS = flag ; if( flag ){ /* if turning on the flag again draw persistent message */ draw_persistent_message( NULL ) ; } } /* end TWmessagePersistence() */ static draw_persistent_message( non_persistent_message ) char *non_persistent_message ; { INT fwidth ; /* font width */ char *message ; /* message to output */ XClearWindow( dpyS, messageS ) ; XDrawString( dpyS, messageS, infoS->graphicContext[WHITE], POS,MENUYPOS, "MSG>", 4 ) ; if( non_persistent_message ){ message = non_persistent_message ; } else if( persistenceS && persistent_messageS[0] ){ message = persistent_messageS ; } else { message = NULL ; } if( message ){ fwidth = XTextWidth( fontinfoS, "MSG>", 4 ) + POS ; XDrawString( dpyS, messageS, infoS->graphicContext[WHITE], POS+fwidth,MENUYPOS,message,strlen(message)); } XFlush( dpyS ) ; } /* end draw_persistent_message() */ char *TWgetString( directions ) char *directions ; { BOOL press ; /* tells whether keyboard has been pushed */ BOOL finish ; /* tells whether we have received a return */ XEvent event ; /* describes button event */ long event_mask ; /* setup menus */ char buffer[LRECL] ; /* used for keyboard translation */ char curMsg[LRECL] ; /* current value of message window */ static char data[LRECL];/* current value of users input */ KeySym keysym ; /* return of keysym from user */ XComposeStatus status ; /* where a compose key was pressed */ INT strwidth ; /* width of string in pixels */ INT dataCount ; /* number of characters in user input */ INT cur_time ; /* the current time */ INT start_time ; /* the start or last activity time */ event_mask = KeyPressMask ; XSelectInput(dpyS,messageS,event_mask); TWmessage( directions ) ; /* now move pointer to line after directions to receive data */ strwidth = XTextWidth( fontinfoS, directions, strlen(directions)) ; /* now warp pointer to message window */ XWarpPointer( dpyS, None, messageS, 0, 0, 0, 0, strwidth+40, MENUYPOS ) ; XSetInputFocus( dpyS, messageS, RevertToPointerRoot, CurrentTime ) ; /* initialize string buffers */ data[0] = EOS ; dataCount = 0 ; /* now look for keyboard action */ finish = FALSE ; /* get the starting time for timeout */ Ytimer_elapsed( &start_time ) ; while(!(finish )){ press = XCheckTypedWindowEvent( dpyS,messageS,KeyPress,&event ); if( press ){ /* initialize buffer */ buffer[0] = EOS ; /* activity reset the timer */ Ytimer_elapsed( &start_time ) ; /* find what the user entered */ XLookupString( &(event.xkey), buffer,LRECL,&keysym, &status ); buffer[1] = EOS ; /* only get one character at a time */ D( "TWgetString",fprintf( stderr, "string:%s\n", buffer ) ) ; /* look to see if we got a return */ if( buffer[0] == RETURN ){ finish = TRUE ; } else { /* look for more data */ /* but first copy the data we have */ if( buffer[0] == BACKSPACE || buffer[0] == DELETE_CH ){ /* look for backspace or delete */ if( dataCount > 0 ){ dataCount-- ; } data[dataCount] = EOS ; } else { /* save data */ strcat( data, buffer ) ; dataCount += strlen( buffer ) ; } /* now echo to screen */ /* build current msg */ /* initialize curMsg */ curMsg[0] = EOS ; strcat( curMsg, directions ) ; strcat( curMsg, data ) ; TWmessage( curMsg ) ; } } else { /* check for no activity */ Ytimer_elapsed( &cur_time ) ; if( cur_time - start_time > message_timeoutS ){ TWmessage( "No activity timeout" ) ; data[0] = EOS ; break ; /* jump out of while loop */ } } } /* now again disable message window so we dont get false info */ event_mask = NoEventMask ; XSelectInput(dpyS,messageS,event_mask); XSetInputFocus( dpyS, PointerRoot, RevertToParent, CurrentTime ); /* clear message window */ TWmessage( NULL ) ; /* if no data was entered return NULL otherwise return data */ if( data[0] == EOS ){ return( NULL ) ; } else { return(data) ; } } /* end TWgetString() */ /* TWgetPt2 allows the user to get a point from either the keyboard */ /* or from the using the mouse */ /* returns TRUE if entered from keyboard, false from mouse */ BOOL TWgetPt2( x, y ) INT *x, *y ; { BOOL press ; /* tells whether button has been pushed */ BOOL ok ; /* whether keyboard input is ok */ BOOL method ; /* input is from keyboard or not? */ XEvent event ; /* describes button event */ long event_mask ; /* setup input */ char **tokens; /* for parsing keyboard data */ INT numtokens ; /* number of tokens in keyboard str */ char *reply ; /* answer from user */ /* turn on event mask for main drawing window - known as wS */ event_mask = ExposureMask | ButtonPressMask ; XSelectInput(dpyS,drawS,event_mask); /* also look for events in message window */ event_mask = KeyPressMask ; XSelectInput(dpyS,messageS,event_mask); /* now disable top menu so we cant get false clicks */ event_mask = NoEventMask ; XSelectInput(dpyS,menuS,event_mask); /* now look for either event - button press or keyboard */ press = FALSE ; while(!(press )){ /* check for user input from keyboard */ if( press=XCheckTypedWindowEvent(dpyS,messageS,KeyPress,&event)){ /* we have an event from the keyboard */ /* put event back on queue and call TWgetString */ XPutBackEvent( dpyS, &event ) ; ok = FALSE ; reply = TWgetString( "Pick or enter point:" ) ; while(!(ok)){ /* now we need to parse back reply */ tokens = Ystrparser( reply, ", \t\n", &numtokens ); if( numtokens == 2 ){ *x = atoi( tokens[0] ) ; *y = atoi( tokens[1] ) ; /* now again enable top menu so we can get clicks */ event_mask = ButtonPressMask ; XSelectInput(dpyS,menuS,event_mask); ok = TRUE ; method = TRUE ; } else { reply = TWgetString( "Invalid input - please enter again! eg. 10, 20"); } } /* end keyboard processing loop */ /* other wise - check mouse */ } else if( press = XCheckTypedWindowEvent( dpyS,drawS, ButtonPress,&event ) ){ /* we have an event from the pointer */ /* put event back on queue and call TWgetPt */ XPutBackEvent( dpyS, &event ) ; TWgetPt( x, y ) ; method = FALSE ; } /* otherwise continue to loop */ } /* end wait loop for user response */ /* now again disable message window so we dont get false info */ event_mask = NoEventMask ; XSelectInput(dpyS,messageS,event_mask); /* now disable window so we can ignore extraneous clicks */ event_mask = ExposureMask ; XSelectInput(dpyS,drawS,event_mask); return( method ) ; } /* end TWgetPt2 */ /* start receiving events concerning mouse tracking */ TWmouse_tracking_start() { long event_mask ; /* set events */ /* turn on event mask for main drawing window - known as wS */ event_mask = StructureNotifyMask | SubstructureNotifyMask | VisibilityChangeMask | ExposureMask | ButtonPressMask | PointerMotionMask ; XSelectInput(dpyS,drawS,event_mask); } /* end TWmouse_tracking_start */ /* get the current mouse position */ /* returns true if position has changed */ BOOL TWmouse_tracking_pt( x, y ) INT *x, *y ; { XEvent event ; /* describes event */ INT xtemp, ytemp ; /* current position of pointer */ BOOL changed ; /* whether position has changed */ static INT xoldL, yoldL; /* position from previous call */ xtemp = xoldL ; /* restore old point */ ytemp = yoldL ; /* restore old point */ while( XCheckTypedWindowEvent( dpyS,drawS, MotionNotify,&event ) ){ /* avoid to many events to screen wait 50 msec.*/ xtemp = event.xmotion.x ; ytemp = event.xmotion.y ; } /* end while loop */ if( xtemp == xoldL && ytemp == yoldL ){ /* nothing has changed */ changed = FALSE ; } else { /* position has changed */ changed = TRUE ; } xoldL = xtemp ; /* save current position for next call */ yoldL = ytemp ; /* account for inversion of y axis */ ytemp = infoS->winheight - ytemp ; /* now reverse scale of coordinates */ xtemp = (INT) ( (DOUBLE) xtemp / infoS->scaleFactor ) ; ytemp = (INT) ( (DOUBLE) ytemp / infoS->scaleFactor ) ; /* now apply data offset */ *x = xtemp - infoS->xoffset ; *y = ytemp - infoS->yoffset ; D( "TWmouse_tracking_pt", fprintf( stderr,"pt = (%d,%d)\n", *x, *y )); XFlush( dpyS ) ; return( changed ) ; } /* end TWmouse_tracking_pt */ BOOL TWmouse_tracking_end() { long event_mask ; /* set events */ XEvent event ; /* describes event */ if( XCheckTypedWindowEvent( dpyS, drawS, ButtonPress,&event ) ){ /* turn off motion notify events for mouse */ event_mask = StructureNotifyMask | SubstructureNotifyMask | VisibilityChangeMask | ExposureMask | ButtonPressMask ; XSelectInput(dpyS,drawS,event_mask); return( TRUE ) ; } else { return( FALSE ) ; } } /* end TWmouse_tracking_end */ /* check to see if main window has been covered by another window */ BOOL TWcheckExposure() { BOOL exposed ; /* tells whether window has been covered */ XEvent event ; /* describes event */ INT time ; /* current time */ static INT lasttimeL ; /* last time of exposure event */ exposed = FALSE ; /* XSync( dpyS, FALSE ) ;*/ /* allow program to catch up */ /* check if there was any exposed event activity */ while( XCheckTypedWindowEvent( dpyS, drawS, Expose, &event ) ){ /* if there is more than one expose event flush from queue */ /* look at count to find only last expose event */ if( event.xexpose.count == 0 ){ exposed = TRUE ; } } /* window managers sometimes send us too many exposure events */ /* therefore check time and make multiple exposures invalid */ if( exposed ){ (void) YcurTime( &time ) ; if( event.xexpose.send_event == True ){ /* if we got a TWforceRedraw always redraw screen */ lasttimeL = time ; D( "TWcheckExposure", fprintf( stderr,"Exposure:f @time = %d\n",time); ) ; if( exposed ){ draw_persistent_message( NULL ) ; } return( exposed ) ; } if( time - lasttimeL < TWsafe_wait_timeG ){ exposed = FALSE ; } else { lasttimeL = time ; } D( "TWcheckExposure", fprintf( stderr,"Exposure:%d @time = %d\n",exposed,time); ) ; } if( exposed ){ draw_persistent_message( NULL ) ; } return( exposed ) ; } /* end TWcheckExpose */ /* returns true if user has clicked in menu window */ /* flushes all remaining button presses in this window */ /* also sets entering and leaving window lighting for subwindows */ /* if we are using TWinterupt we which to turn off menu subwindows */ BOOL TWinterupt() { static INT last_timeL=0; /* the last time we interupted */ INT cur_time ; /* the current time since start of process */ BOOL press ; /* tells whether button has been pushed */ XEvent event ; /* describes button event */ /* now avoid looking for interuptions all the time */ /* it take too much time*/ Ytimer_elapsed( &cur_time ) ; if( cur_time - last_timeL < 1000 ){ return( FALSE ) ; } last_timeL = cur_time ; press = FALSE ; /* XSync( dpyS, FALSE ) ; */ /* allow program to catch up */ /* check if there is any mouse activity */ while( XCheckTypedWindowEvent( dpyS, menuS, ButtonPress, &event ) ){ /* if there is more than one button event flush from queue */ press = TRUE ; } set_window_lights( press ) ; return( press ) ; } /* end TWinterupt */ /* update windows if configuration changes */ TWcheckReconfig() { INT height ; /* height of current backing window */ XEvent event ; /* describes configuration event */ INT winwidth, winheight ; /* size of window */ BOOL redraw = FALSE ; /* whether to redraw or not */ height = infoS->winheight + 2 * MENUHEIGHT ; /* since all windows are children of backS only check backS */ while( XCheckTypedEvent( dpyS, ConfigureNotify, &event ) ){ if( event.xconfigure.window == backS ){ if( event.xconfigure.override_redirect ){ /* window manager is telling us to leave it alone */ continue ; } winheight = event.xconfigure.height ; winwidth = event.xconfigure.width ; if( winheight == height && winwidth == infoS->winwidth ){ /* nothing changed avoid the work */ continue ; } /* if window changes size need to send expose */ /* event so you know to redraw event - this is cause */ redraw = TRUE ; winheight -= 2 * MENUHEIGHT ; resize_windows( winwidth, winheight ) ; } } if( redraw ){ D( "TWcheckReconfig", { INT time ; (void) YcurTime( &time ) ; fprintf( stderr,"TWcheckReconfig redraw:@time = %d\n", time); } ) ; /* remove any exposure events */ /* ???? TWcheckExposure() ; TWforceRedraw() ; */ } } /* end TWcheckReconfig */ static resize_windows( winwidth, winheight ) INT winwidth, winheight ; { INT halfstep ; /* menu half spacing */ INT xpos ; /* position of menu */ INT i, j ; /* counters */ MENUPTR menuptr ; /* temporary for selected menu record */ /* change size of draw window */ XMoveResizeWindow( dpyS, drawS, 0, MENUHEIGHT, winwidth, winheight ) ; /* create a new pixmap */ /* off screen copy of the data */ /* free the old one first */ XFreePixmap( dpyS, pixmapS ) ; pixmapS = XCreatePixmap( dpyS, drawS, (unsigned)winwidth, (unsigned)winheight, XDefaultDepth(dpyS,screenS) ) ; /* change size of menu window */ XMoveResizeWindow( dpyS, menuS, 1, 1, winwidth, MENUHEIGHT ) ; /* change size of message window */ /* winy takes care of border */ XMoveResizeWindow( dpyS, messageS, 1, winheight + MENUHEIGHT, winwidth, MENUHEIGHT ) ; /* tell main draw routines what has happened */ TWsetDrawInfo( winheight, winwidth, pixmapS ) ; /* reposition the menu window titles */ /* calculate position of the menus based on equal spacing */ stepsizeS = winwidth / numMenuS ; halfstep = stepsizeS / 2 ; xpos = halfstep ; /* placement of first menu */ for( i=0;i< numMenuS; i++ ){ menuptr = menuArrayS[i] ; /* save where to draw menu title in menu window */ menuptr->xpos = halfstep - menuptr->pix_len / 2 ; /* fix top window */ XMoveResizeWindow( dpyS, menuptr->top_window, xpos - halfstep, 0, stepsizeS, MENUHEIGHT ) ; /* move the subwindows */ for( j=0; j< menuptr->numentries; j++ ){ XMoveResizeWindow( dpyS, menuptr->window[j], xpos - menuptr->width / 2, (j+1) * MENUHEIGHT, menuptr->width, MENUHEIGHT ) ; } xpos += stepsizeS ; } /* redraw menus and initialize message window */ TWdrawMenus() ; TWmessage( NULL ) ; } /* end TWcheckReconfig */ TWfreeMenuWindows() { INT i, j ; /* counters */ MENUPTR menuptr ; /* temporary for selected menu record */ for( i = 0; i < numMenuS ; i++ ){ /* pick window and menu for speed */ menuptr = menuArrayS[i] ; for( j = 0 ; j < menuptr->numentries; j++ ){ /* would nice to be able to use XDestroySubWindows */ /* but we would destroy the parents copy too. Therefore */ /* we must free window this way */ XDestroyWindow( dpyS, menuptr->window[j] ) ; } } /* turn off all event reporting to these windows */ XSelectInput(dpyS,drawS,NoEventMask) ; XSelectInput(dpyS,backS,NoEventMask) ; XSelectInput(dpyS,menuS,NoEventMask) ; XSelectInput(dpyS,messageS,NoEventMask) ; /* next flush event queue by calling XSync */ XSync( dpyS, FALSE ) ; } /* end TWfreeMenuWindow */ TWMENUPTR TWread_menus( filename ) char *filename ; { char buffer[LRECL], *bufferptr ; char **tokens ; /* for parsing menu file */ INT numtokens ; /* number of tokens on the line */ INT line ; /* count lines in input file */ INT item ; /* number of menu fields */ FILE *fp ; /* open file pointer */ TWMENUPTR menu_fields; /* array of menu information */ TWMENUPTR mptr; /* current menu item */ /* parse menu file */ line = 0 ; item = 0 ; fp = TWOPEN( filename, "r", ABORT ) ; while( bufferptr=fgets(buffer,LRECL,fp )){ /* parse file */ line ++ ; /* increment line number */ /* skip comments */ if( *bufferptr == COMMENT ){ continue ; } tokens = Ystrparser( bufferptr, ",\t\n", &numtokens ); if( numtokens == 0 ){ /* skip over empty lines */ continue ; } else if( strcmp( tokens[0], MENUKEYWORD ) == STRINGEQ){ /* look at first field for menu keyword */ /* there better be only two tokens on this line */ if( numtokens != 2 ){ sprintf( YmsgG, "Syntax error on line:%d\n", line ) ; M(ERRMSG, "TWread_menus", YmsgG ) ; } /* increment menu count */ item++ ; } else { /* menu item */ if( numtokens == 2 || numtokens == 5 ){ item++ ; } else { sprintf( YmsgG, "Problem parsing line:%d in menu file\n", line ) ; M( ERRMSG,"TWread_menus", YmsgG ) ; } } } if( item <= 0 ){ sprintf( YmsgG,"Couldn't find any menu data in file:%s\n", filename ) ; M( ERRMSG,"TWread_menus", YmsgG ) ; return( NULL ) ; } /* now allocate array */ menu_fields = YCALLOC( ++item, TWMENUBOX ) ; /* reread file building menus */ item = -1 ; line = 0 ; rewind( fp ) ; while( bufferptr=fgets(buffer,LRECL,fp )){ /* parse file */ line++ ; /* skip comments */ if( *bufferptr == COMMENT ){ continue ; } tokens = Ystrparser( bufferptr, ",\t\n", &numtokens ); if( numtokens == 0 ){ /* skip over empty lines */ continue ; } else if( strcmp( tokens[0], MENUKEYWORD ) == STRINGEQ){ mptr = &( menu_fields[++item] ) ; mptr->item = Ystrclone( tokens[1] ) ; mptr->bool_item = NULL ; mptr->bool_init = 0 ; mptr->menuNotItem = TRUE ; mptr->action_index = 0 ; mptr->action_indexb = 0 ; } else if( item >= 0 ){ /* avoid obvious errors */ if( numtokens == 2 || numtokens == 5 ){ mptr = &( menu_fields[++item] ) ; mptr->item = Ystrclone( tokens[0] ) ; mptr->menuNotItem = FALSE ; mptr->action_index = atoi( tokens[1] ) ; if( numtokens == 5 ){ /* also check the complement */ mptr->bool_item = Ystrclone( tokens[2] ) ; mptr->action_indexb = atoi( tokens[3] ) ; /* set initial state 1 means first entry set active */ mptr->bool_init = atoi( tokens[4] ) ; } else { /* number of tokens == 2 */ mptr->bool_item = NULL ; mptr->bool_init = 0 ; mptr->action_indexb = 0 ; } } else { sprintf( YmsgG, "Problem parsing line:%d in menu file\n", line ) ; M( ERRMSG,"TWread_menus", YmsgG ) ; } } else { sprintf( YmsgG, "Problem parsing line:%d in menu file\n", line ) ; M( ERRMSG,"TWread_menus", YmsgG ) ; } } /* end parsing loop */ TWCLOSE( fp ) ; #ifdef DEBUG debug_menus( menu_fields ) ; #endif /* DEBUG */ return( menu_fields ) ; } /* end TWread_menus */ #ifdef DEBUG #include static char *cap_item( sptr ) char *sptr ; { static char bufferL[LRECL] ; INT len ; /* string length */ INT j ; /* counter */ INT pos ; /* position in buffer */ /* always capitialize the item */ len = strlen( sptr ) ; pos = 0 ; /* beginning of string */ for( j = 0 ; j < len; j++ ){ if( sptr[j] == '.' ){ /* don't do anything */ } else if( sptr[j] == ' ' ){ bufferL[pos++] = '_' ; } else if( islower(sptr[j]) ){ bufferL[pos++] = toupper(sptr[j]) ; } else { /* in other cases just copy */ bufferL[pos++] = sptr[j] ; } } bufferL[pos] = EOS ; return( bufferL ) ; } /* end cap_item */ static debug_menus( menu_field ) TWMENUPTR menu_field ; { INT i ; /* counter */ INT count ; /* number of fields */ char label[LRECL] ; /* copy of the menu item */ FILE *fp ; /* file pointer */ TWMENUPTR mptr ; /* temporary pointer */ fp = TWOPEN( "menus.h", "w", ABORT ) ; count = 0 ; for( i=0 ; menu_field[i].item ; i++ ){ count++ ; } /* write out the define statements */ fprintf( fp, "\n/* TWmenu definitions */ \n" ) ; fprintf( fp, "#define TWNUMMENUS\t\t%d\n", count ) ; for( i=0 ; menu_field[i].item; i++ ){ mptr = &(menu_field[i]) ; if(mptr->menuNotItem){ continue ; } fprintf( fp, "#define %s\t\t%d\n", cap_item(mptr->item), mptr->action_index ) ; if( mptr->bool_item ){ fprintf( fp, "#define %s\t\t%d\n", cap_item(mptr->bool_item), mptr->action_indexb ) ; } } fprintf( fp, "\n\n" ) ; fprintf( fp, "static TWMENUBOX menuS[%d] = {\n", count+1 ) ; for( i=0 ; menu_field[i].item; i++ ){ mptr = &(menu_field[i]) ; fprintf( fp, " \"%s\",", mptr->item ) ; if( mptr->bool_item ){ fprintf( fp, "\"%s\",", mptr->bool_item ) ; } else { fprintf( fp, "0," ) ; } fprintf( fp, "%d,%d,%d,%d,\n", mptr->bool_init,mptr->menuNotItem, mptr->action_index, mptr->action_indexb ) ; } fprintf( fp, " 0,0,0,0,0,0\n" ) ; fprintf( fp, "} ;\n\n" ) ; TWCLOSE(fp) ; } /* end debug_dialog() */ #endif /* DEBUG */ #endif /* no graphics */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/message.c000066400000000000000000000151101305746555600212400ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: message.c DESCRIPTION:message processing routines The object of these routines is to allow the user flexibility in redirecting the output of messages to the screen as well as keeping track of program errors and warnings. CONTENTS: Ymessage_print( messageType, routine, messageString ) INT messageType ; char *routine, *messageString ; INT Ymessage_get_warncount() INT Ymessage_get_errorcount() Ymessage_warncount() Ymessage_errorcount() Ymessage_output( messageString ) char *messageString ; Ymessage_init( fileptr ) FILE *fileptr ; Ymessage_mode( mode ) INT mode ; Ymessage_flush() Ymessage_close() DATE: Jan 29, 1988 REVISIONS: Sep 30, 1988 - added incWarningCount & incErrorCount Jan 27, 1989 - changed msg to msgG so that use can tell it is global variable. Jan 29, 1989 - took \n out of printf statement Apr 27, 1989 - changed to Y prefix. May 3, 1989 - changed msgG to YmsgG to be consistent. Aug 8, 1989 - fixed problem with double write to to output file. Wed Jan 30 14:10:52 EST 1991 - now output warning messages to the screen also. Fri Feb 15 15:21:57 EST 1991 - added modes to message system. Modified names to make it easier. Thu Mar 7 01:27:48 EST 1991 - now always flush stdout. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) message.c version 3.6 3/7/91" ; #endif #include #include #include #include static INT errorCountS = 0; static INT warningCountS = 0; static FILE *foutS = NULL ; /* open output file */ static FILE *outS = NULL ; /* redirected out file */ static BOOL verboseS = FALSE ; static BOOL modeS = M_NORMAL ; static char message_bufS[LRECL] ; static char typeS[8] ; /* global variable definition */ char *YmsgG = message_bufS ; Ymessage_print( messageType, routine, messageString ) INT messageType ; char *routine ; char *messageString ; { FILE *out ; /* where to output result if verbose */ /* determine message type */ switch (messageType){ case MSG:typeS[0] = EOS; /* no need for an explanation */ out = stdout ; break ; case ERRMSG:sprintf(typeS,"ERROR"); out = stderr ; if( routine ){ /* error message should always have routine */ /* continuation of a message doesn't count */ errorCountS++; } break ; case WARNMSG:sprintf(typeS,"WARNING"); out = stderr ; if( routine ){ /* warning message should always have routine */ /* continuation of a message doesn't count as new */ /* warning message */ warningCountS++; } break ; case DBGMSG:sprintf(typeS,"DEBUG"); out = stdout ; break ; } if( foutS ){ if( messageString && routine ){ fprintf( foutS,"%s[%s]:%s",typeS,routine,messageString); if( verboseS || messageType == ERRMSG || messageType == WARNMSG ){ fprintf( out,"%s[%s]:%s",typeS,routine,messageString); } } else if( messageString ){ fprintf( foutS, "%s",messageString ); if( verboseS || messageType == ERRMSG || messageType == WARNMSG ){ fprintf( out, "%s",messageString ); } } } else { if( modeS == M_SILENT ){ if( messageType != ERRMSG && messageType != WARNMSG ){ /* eat the message in this case */ return ; } } /* no file installed send to screen */ if( messageString && routine ){ fprintf( out,"%s[%s]:%s",typeS,routine,messageString); } else if( messageString ){ fprintf( out, "%s",messageString ); } } } /* end message_print */ /* increment the static variable */ Ymessage_warn_count() { warningCountS++ ; } /* end message_warn_count */ /* increment the static variable */ Ymessage_error_count() { errorCountS++ ; }/* end Ymessage_error_count */ INT Ymessage_get_warncount() { return(warningCountS); } /*end Ymessage_get_warncount */ INT Ymessage_get_errorcount() { return(errorCountS); } /*end Ymessage_get_errorcount */ Ymessage_output( messageString ) char *messageString ; { if( verboseS ){ fprintf( outS, "%s", messageString ) ; } if( foutS ){ fprintf( foutS, "%s", messageString ) ; } } /* end message_output */ Ymessage_init( fileptr ) FILE *fileptr ; { foutS = fileptr ; } /* end Ymessage_init */ Ymessage_mode( mode ) INT mode ; { if( mode == M_VERBOSE ){ verboseS = TRUE ; outS = stdout ; modeS = M_VERBOSE ; } else if( mode == M_NORMAL ){ verboseS = FALSE ; outS = NULL ; modeS = M_NORMAL ; } else if( mode == M_SILENT ){ verboseS = FALSE ; outS = NULL ; modeS = M_SILENT ; } } /* end YverboseMessage */ BOOL Ymessage_get_mode() { return( modeS ) ; } /* end Ymessage_get_mode */ Ymessage_flush() { if( outS ){ fflush(outS) ; } if( foutS ){ fflush(foutS) ; } fflush( stdout ) ; } /* end Ymessage_flush */ Ymessage_close() { if( foutS ){ TWCLOSE(foutS) ; foutS = (FILE *)NULL; } if( outS ){ TWCLOSE(outS) ; outS = (FILE *)NULL; } } /* end Ymessage_close */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/mst.c000066400000000000000000000130611305746555600204220ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: mst.c DESCRIPTION:These routines find the minimum spanning tree of a net. USING PRIM'S ALGORITHM. CONTENTS: DATE: Jun 21, 1989 REVISIONS: Thu Oct 17 11:09:03 EDT 1991 - renamed functions according to convention. Added mst_color function. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) mst.c (Yale) version 1.5 1/24/92" ; #endif #include #include #include #include static INT numpinS ; /* allocation of memory */ static INT *nodeXS ; /* array of x locations for pins */ static INT *nodeYS ; /* array of y locations for pins */ static INT *lowcostS ; /* array of lowest cost for neighbor */ static INT *closestS ; /* array of closest neighbor for pin */ static INT countS ; /* number of pins for this net */ static INT colorS = TWRED ; /* default color is red */ #define SQUARE(a) ((a)*(a)) #define INF INT_MAX static cost(i,j) /* return the square of the Euclidian distance of 2 points */ INT i, j ; { if (i==j){ return INF; } return( SQUARE(nodeXS[i]-nodeXS[j])+SQUARE(nodeYS[i]-nodeYS[j]) ); } /* end cost */ Ymst_init( numpins ) INT numpins ; { numpinS = numpins ; nodeXS = YMALLOC( numpins, INT ) ; nodeYS = YMALLOC( numpins, INT ) ; lowcostS = YMALLOC( numpins+1, INT ) ; closestS = YCALLOC( numpins+1,INT ) ; countS = 0 ; } /* end Ymst_init() */ Ymst_free() { YFREE(nodeXS) ; YFREE(nodeYS) ; YFREE(closestS) ; YFREE(lowcostS) ; } /* end Ymst_free() */ Ymst_clear() { countS = 0 ; } /* end Yclear_mst() */ Ymst_addpt( x, y ) INT x, y ; { if( countS >= numpinS ){ fprintf( stderr, "Out of space - update number of pins for MST\n"); return ; } nodeXS[countS] = x ; nodeYS[countS] = y ; countS++ ; } /* end Ymst_addpt() */ Ymst_draw() { INT mincost ; /* minimum cost for pin */ INT closest_pt ; /* closest neighbor for pin */ INT i ; /* a counter */ INT j ; /* a counter */ INT k ; /* a counter */ INT c ; /* temp for cost */ for( i = 1 ; i < countS; i++) { closestS[i] = 0 ; lowcostS[i] = cost( 0,i ) ; } for( i = 1; i < countS; i++) { mincost = lowcostS[1] ; k = 1 ; for( j = 2 ; j < countS ; j++ ){ if( lowcostS[j] < mincost ) { mincost = lowcostS[j] ; k = j ; } } closest_pt = closestS[k] ; TWdrawLine( i, nodeXS[k], nodeYS[k], nodeXS[closest_pt], nodeYS[closest_pt], colorS, NULL ) ; lowcostS[k] = INF; for( j = 1 ; j < countS ; j++ ){ if( ( c = cost(k,j) ) < lowcostS[j] && lowcostS[j] < INF ){ lowcostS[j] = c; closestS[j] = k; } } } /* end for( i = 1;... */ } /* end Ymst_draw() */ Ymst_enumerate( x1, y1, x2, y2, startFlag ) INT *x1, *y1, *x2, *y2 ; BOOL startFlag ; { INT mincost ; /* minimum cost for pin */ INT closest_pt ; /* closest neighbor for pin */ INT j ; /* a counter */ INT k ; /* a counter */ INT c ; /* temp for cost */ static INT i ; /* keep track of the edge */ if( startFlag ){ for( i = 1 ; i < countS; i++) { closestS[i] = 0 ; lowcostS[i] = cost( 0,i ) ; } i = 1; } else { if( ++i >= countS ){ return ; /* no more edges left */ } } mincost = lowcostS[1] ; k = 1 ; for( j = 2 ; j < countS ; j++ ){ if( lowcostS[j] < mincost ) { mincost = lowcostS[j] ; k = j ; } } closest_pt = closestS[k] ; *x1 = nodeXS[k] ; *y1 = nodeYS[k] ; *x2 = nodeXS[closest_pt] ; *y2 = nodeYS[closest_pt] ; lowcostS[k] = INF; for( j = 1 ; j < countS ; j++ ){ if( ( c = cost(k,j) ) < lowcostS[j] && lowcostS[j] < INF ){ lowcostS[j] = c; closestS[j] = k; } } } /* end Ymst_enumerate() */ Ymst_color( color ) { colorS = color ; } /* end Ymst_color */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/mytime.c000066400000000000000000000071701305746555600211270ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* -------------------------------------------------------------------------- FILE: mytime.c DESCRIPTION:better random seed from system time. CONTENTS: unsigned Yrandom_seed() DATE: Feb 07, 1989 REVISIONS: Apr 27, 1989 - changed to Y prefix. Aug 25, 1989 - changed algorithm to use less system calls. Dec 17, 1989 - use the version in SC as default. Apr 01, 1991 - added SYS5 (A/UX) support (RAWeier) Oct 07, 1991 - fix warning in Gnu gcc (RAWeier) Dec 09, 1991 - industrial users say gettimeofday is more "universal" and improves portability (RAWeier) --------------------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) mytime.c version 3.8 12/15/91" ; #endif #include /* NOTE to user on foreign machines: if below does not compile, you */ /* may use the alternate random seed generator at some penalty for */ /* randomness but it should not matter due to the robustness of the */ /* random number generator itself. Just use #define ALTERNATE */ /* #define ALTERNATE */ #ifndef ALTERNATE #ifdef VMS #include #include #else #include #include #endif unsigned Yrandom_seed() { UNSIGNED_INT m , time1 , time2 ; struct timeval tp ; gettimeofday(&tp,0) ; time1 = (UNSIGNED_INT) tp.tv_usec ; time1 <<= 22 ; time2 = (tp.tv_usec & 0x003FFFFF) ; m = time1 | time2 ; return(m>>1); } #else /* ALTERNATE */ /* returns a random seed from system clock */ unsigned Yrandom_seed() { UNSIGNED_INT seed ; long t ; INT hsum ; INT shift ; char buffer[LRECL], *name = buffer ;; /* get time since Jan 1, 1970 in seconds */ t = time((long *) 0) ; /* convert to a string */ sprintf( buffer, "%d", t ) ; /* now use hash function to get a number 0..INT_MAX */ /* don't initialize hsum use garbage if possible */ for (shift=1 ;*name; name++){ hsum = hsum + *name< #include #include #include #include #include #ifdef HPUX #undef NBPG #include #endif /* memory errors */ #define heap_error_base 0x40060000 #define heap_bad_block (heap_error_base + 1) #define heap_no_mem (heap_error_base + 2) #define heap_ok 0 #ifdef MEM_DEBUG #include /* ----------------------------------------------------------------- These two unusual definitions MEM_DEBUG1 and MEM_DEBUG2 add arguments to memory user routines so that we can pass the file and line number from the preprocessor. ----------------------------------------------------------------- */ #define MEM_DEBUG1 ,file,line #define MEM_DEBUG2 char *file ; int line ; #define ALLOC_NAME_SIZE 40 #else #define MEM_DEBUG1 #define MEM_DEBUG2 #endif /* MEM_DEBUG */ /* conditional compile for the memory manager */ /* if MEMORYMAN is not defined use system malloc calloc etc. */ #ifdef MEMORYMAN #define systype "bsd4.2" /* *-------------------------------------------------------------- * C MEMORY MANAGEMENT SYSTEM * Description : These Routines replace malloc/calloc * & free calls. AVOID deficiencies in * APOLLO heap management routines. * * CODED BY : Bill Swartz *-------------------------------------------------------------- */ #define mp_block_cnt 256 #define region_mask 0xFFFF8000 #define region_overhead 8 #define DFL_REGION_SIZE (4095 * 1024) #define expected_size (256 * 1024) #define waste_allowed 28 #define FOREVER 1 #define block_overhead (sizeof(header_t) + sizeof(trailer_t)) #define double_word_mask 0xFFFFFFFC #define char_p char * typedef struct { INT size; } header_t; typedef struct { INT all; } status_t; typedef struct block_type { header_t head; union { struct { struct block_type *link; struct block_type *back; } zero_case; INT data; } case_of_two; } block_t, *block_p; typedef INT region_head_t, *region_head_p; typedef struct { INT size; } trailer_t, *trailer_p; typedef struct { block_t avail; block_p alloc_rover; region_head_p highest_region; INT cnt_blks; INT max_blks; } zone_t; static zone_t zoneS ; static status_t statuS; static BOOL heapNotStartedS = TRUE; static INT totalAllocationS = 0 ; static BOOL debugFlagS = FALSE ; static INT inUseS = 0 ; static INT regionSizeS = DFL_REGION_SIZE ; static INT max_usedS = 0 ; #ifdef MEM_DEBUG /* keep an linked list of allocated memory */ typedef struct mem_obj { char name[ALLOC_NAME_SIZE] ; char *ptr_p ; struct mem_obj *next ; struct mem_obj *prev ; } MEMOBJ, *MEMOBJPTR ; static MEMOBJ name_sentinelS ; static MEMOBJPTR name_listS = &name_sentinelS ; #endif /* MEM_DEBUG */ /* ++++++++++++++++++ HEAP MANAGEMENT ROUTINES ++++++++++++++ */ /* ---------heap_dispose--------- */ static status_t heapDispose (ptr) char_p ptr; { status_t st; trailer_p tail; block_p headPtr; block_p check; block_p lower; block_p higher; block_p temp; long l ; long *i ; /* Begin procedure heap dispose. */ headPtr = (block_p) ((INT) ptr - sizeof(header_t)); inUseS += headPtr->head.size ; tail = (trailer_p) ( ((INT)headPtr) - headPtr->head.size - sizeof(trailer_t)); if ((headPtr->head.size > 0) || (headPtr->head.size != tail->size)) { st.all = heap_bad_block; return (st); } else if( debugFlagS ) { /* set the old memory to -1 */ headPtr = (block_p) ((INT) ptr - sizeof(header_t)); /* find number of words; - 2 accounts for header and trailer */ l = ABS( headPtr->head.size ) / sizeof(long) - 2 ; for(i=(long *) ptr;l>0;i++, l--){ *i=(long)-1; } } headPtr->head.size *= -1; tail = (trailer_p) ( ((INT)headPtr) - sizeof(trailer_t)); if (tail->size > 0) { check = (block_p) ( ((INT)headPtr) - tail->size); higher = check->case_of_two.zero_case.link; lower = check->case_of_two.zero_case.back; higher->case_of_two.zero_case.back = lower; lower->case_of_two.zero_case.link = higher; check->head.size += headPtr->head.size; headPtr = check; } check = (block_p) ( ((INT)headPtr) + headPtr->head.size); if (check->head.size > 0) { if (zoneS.alloc_rover == (block_p) &(check->head.size)) { zoneS.alloc_rover = (block_p) &(headPtr->head.size); } higher = check->case_of_two.zero_case.link; lower = check->case_of_two.zero_case.back; higher->case_of_two.zero_case.back = lower; lower->case_of_two.zero_case.link = higher; headPtr->head.size += check->head.size; } tail = (trailer_p) ( ((INT)headPtr) + headPtr->head.size - sizeof(trailer_t)); tail->size = headPtr->head.size; headPtr->case_of_two.zero_case.link = zoneS.avail.case_of_two.zero_case.link; headPtr->case_of_two.zero_case.back = (block_p) &(zoneS.avail); temp = (block_p) &(headPtr->head); zoneS.avail.case_of_two.zero_case.link->case_of_two.zero_case.back = temp ; zoneS.avail.case_of_two.zero_case.link = temp ; #ifdef MEM_DEBUG { MEMOBJPTR mem_p ; /* this is brain dead for now */ for( mem_p = name_listS->next; mem_p != name_listS; mem_p = mem_p->next ){ if( mem_p->ptr_p == ptr ){ /* delete this from memory */ mem_p->prev->next = mem_p->next ; mem_p->next->prev = mem_p->prev ; heapDispose( mem_p ) ; break ; } } } #endif /* end MEM_DEBUG */ st.all = heap_ok; return (st); } /* End of procedure heap dispose. */ /* ---------- Utility Routines ---------- */ static status_t allocateRegion (min_size) INT min_size; { typedef INT *tag_p; status_t st; block_p head; trailer_p tail; INT allocation; INT pageSize; INT i; INT *memory; /* Begin procedure allocate region. */ #ifndef SYS5 pageSize = getpagesize() ; #else /* SYS5 */ pageSize = NBPG ; #endif /* SYS5 */ if( min_size < expected_size ){ min_size = expected_size ; } allocation = min_size + 2*sizeof(INT); allocation += pageSize - (allocation % pageSize) ; totalAllocationS += allocation ; head = (block_p) sbrk(0) ; sprintf( YmsgG, "Alternate MEMORY MANagement system invoked - allocation:%d bytes\n", allocation ) ; M( MSG, NULL, YmsgG ) ; if( debugFlagS ){ fprintf( stderr, "Memory debug switch on\n") ; fprintf( stderr, "old starting memory address:%0x Page size = %d\n", head,pageSize) ; } head = (block_p) sbrk(allocation) ; if( debugFlagS ){ fprintf( stderr, "new starting memory address:%0x with allocation:%d bytes\n", head, allocation) ; if( !( heapNotStartedS) ){ fprintf( stderr, "current memory request = %d bytes approx. %d pages\n", min_size,min_size/pageSize) ; fprintf( stderr, "total user memory allocated = %d bytes approx. %d pages\n", inUseS,inUseS/pageSize) ; } fprintf( stderr, "new memory space = %d pages of %d bytes\n", totalAllocationS / pageSize, pageSize) ; fprintf( stderr,"total current allocation = %d\n\n",totalAllocationS ) ; } /* head = (block_p) malloc(allocation) */ ; if ( !(head) || head == (block_p) -1) { st.all = heap_no_mem ; return( st ) ; } if( debugFlagS ){ /* initialize all bytes of memory to 1 to catch bugs */ memory = (INT *) head ; for( i=0;isize = *zoneS.highest_region; tail = (trailer_p) ((INT) head + allocation - sizeof(INT)); head->head.size = tail->size = -allocation; head = (block_p) ((INT) head + sizeof(INT)); st = heapDispose (head); zoneS.alloc_rover = zoneS.avail.case_of_two.zero_case.link; st.all = heap_ok; return (st); } /* End procedure allocate region. */ /* -------- heap_init -------- */ static status_t heapInit (initial_size) INT initial_size; { status_t st; block_p block; INT allocation; /* Begin procedure heap init. */ /* initialize zone record */ zoneS.avail.head.size = 0 ; zoneS.avail.case_of_two.zero_case.link = &(zoneS.avail) ; zoneS.avail.case_of_two.zero_case.back = &(zoneS.avail) ; zoneS.alloc_rover = &(zoneS.avail) ; zoneS.highest_region = NULL ; zoneS.cnt_blks = 0 ; zoneS.max_blks = 0 ; #ifdef MEM_DEBUG name_listS->next = name_listS ; name_listS->prev = name_listS ; #endif /* MEM_DEBUG */ if (initial_size > 0) { st = allocateRegion (initial_size); if (st.all != heap_ok){ return (st); } else { heapNotStartedS = FALSE; } } st.all = heap_ok; return (st); } /* End of procedure heap init. */ /* -------- heap_new --------- */ static status_t heapNew (ptr, req_size MEM_DEBUG1 ) char_p *ptr; INT req_size; MEM_DEBUG2 { status_t st; INT excess; INT allocation; INT block_size; block_p new_block; block_p check; trailer_p trailer; region_head_p region; /* Begin procedure heap new. */ if (req_size <= 0) { *ptr = NULL; st.all = heap_ok; return (st); } else if (heapNotStartedS){ heapInit(regionSizeS); } block_size = (req_size + 3 + block_overhead) & double_word_mask; check = zoneS.alloc_rover; do { if (check->head.size < block_size) { check = check->case_of_two.zero_case.link; } else { excess = check->head.size - block_size; zoneS.alloc_rover = check->case_of_two.zero_case.link; if (excess < waste_allowed) { check->case_of_two.zero_case.back->case_of_two.zero_case.link = check->case_of_two.zero_case.link; check->case_of_two.zero_case.link->case_of_two.zero_case.back = check->case_of_two.zero_case.back; block_size = check->head.size; } else { check->head.size = excess; trailer = (trailer_p) ((INT) check + excess - sizeof(trailer_t)); trailer->size = excess; check = (block_p) ((INT) check + excess); } check->head.size = -block_size; trailer = (trailer_p) ((INT) check + block_size - sizeof(trailer_t)); trailer->size = -block_size; *ptr = (char_p) &(check->case_of_two.data); #ifdef MEM_DEBUG { INT len ; char alloc_name[BUFSIZ] ; MEMOBJPTR name_data ; if( file ){ sprintf( alloc_name, "%s:%d", file, line ) ; len = strlen( alloc_name ) ; if( len < ALLOC_NAME_SIZE ){ /* allocate space for record info but don't put in tree */ statuS = heapNew (&name_data, sizeof(MEMOBJ), NULL, 0 ) ; if (statuS.all!=heap_ok){ errno = statuS.all ; kill(getpid(),SIGUSR1); } strcpy( name_data->name, alloc_name ) ; name_data->ptr_p = *ptr ; name_data->next = name_listS->next ; name_listS->next->prev = name_data ; name_listS->next = name_data ; name_data->prev = name_listS ; } else { fprintf( stderr, "Alloc name:%s too long to store\n",alloc_name ) ; } } } #endif /* MEM_DEBUG */ inUseS += block_size ; if( inUseS > max_usedS ) max_usedS = inUseS ; st.all = heap_ok; return (st); } if (check == zoneS.alloc_rover) { st = allocateRegion (block_size); if( inUseS > max_usedS ) max_usedS = inUseS ; if (st.all != heap_ok) return (st); check = zoneS.alloc_rover; } } while (FOREVER); } /* End procedure heap new. */ VOID Ydump_mem() { #ifdef MEM_DEBUG FILE *fp ; MEMOBJPTR mem_p ; static INT dump_noL = 0 ; char filename[LRECL] ; INT sum_allocated ; INT size ; sum_allocated = 0 ; sprintf( filename, "mem.data.%d", ++dump_noL ) ; fp = TWOPEN( filename, "w", ABORT ) ; fprintf( fp, "Address:amount_allocated file:line_number\n" ) ; for( mem_p = name_listS->next; mem_p != name_listS; mem_p = mem_p->next ){ size = YcheckMemObj(mem_p->ptr_p) ; fprintf( fp, "%x:%d %s\n", mem_p->ptr_p, size, mem_p->name ) ; sum_allocated += size ; } fprintf( fp, "-----------------------------------------------------------\n"); fprintf( fp, "Total allocation:%d\n", sum_allocated ) ; TWCLOSE( fp ) ; #else /* MEM_DEBUG */ fprintf( stderr, "Ydump_mem() is not available. Use libycad.mem-d.a\n" ) ; #endif /* MEM_DEBUG */ } /* end Ydump_mem() */ /* ++++++++++++++++++ END HEAP MANAGEMENT ROUTINES ++++++++++++++ */ /* SUBSTITION CALLS FOR C RUN TIME LIBRARY */ VOID Ysafe_free(ptr MEM_DEBUG1 ) VOIDPTR ptr; MEM_DEBUG2 { if( !( ptr ) ){ fprintf( stderr, "WARNING[safe_free]:pointer = nil. Ignoring safe_free.\n") ; return ; } statuS = heapDispose (ptr); if (statuS.all != heap_ok){ errno = statuS.all ; kill(getpid(),SIGUSR1); } } VOID Ysafe_cfree(ptr MEM_DEBUG1 ) VOIDPTR ptr; MEM_DEBUG2 { if( !( ptr ) ){ fprintf(stderr, "WARNING[safe_cfree]:pointer = nil. Ignoring safe_cfree.\n") ; return ; } statuS = heapDispose (ptr); if (statuS.all!=heap_ok){ errno = statuS.all ; kill(getpid(),SIGUSR1); } } char *Ysafe_malloc(bytes MEM_DEBUG1 ) INT bytes; MEM_DEBUG2 { char *ptr; char *i; if (bytes<5) { bytes = 8; } statuS = heapNew (&ptr, bytes MEM_DEBUG1 ); if (statuS.all!=heap_ok){ errno = statuS.all ; kill(getpid(),SIGUSR1); } return(ptr); } char *Ysafe_calloc(num_entries, bytes MEM_DEBUG1 ) INT num_entries; INT bytes; MEM_DEBUG2 { char *ptr; long *i; long k,l; k = bytes*num_entries; if (k<5) { k = 8; } statuS = heapNew (&ptr, k MEM_DEBUG1 ); if (statuS.all!=heap_ok){ errno = statuS.all ; kill(getpid(),SIGUSR1); } l = (k+3)>>2; for(i=(long *)ptr;l>0;i++, l--){ *i=(long)0; } return(ptr); } char *Ysafe_realloc(ptr, bytes MEM_DEBUG1 ) VOIDPTR ptr; INT bytes; MEM_DEBUG2 { char *ptr2; INT oldSize; INT i; block_p headPtr; trailer_p tail; /* allocate new memory */ ptr2 = Ysafe_malloc(bytes MEM_DEBUG1 ); /* get current size of ptr */ headPtr = (block_p) ((INT) ptr - sizeof(header_t)); tail = (trailer_p) ( ((INT)headPtr) - headPtr->head.size - sizeof(trailer_t)); if ((headPtr->head.size > 0) || (headPtr->head.size != tail->size)) { errno = heap_bad_block ; kill(getpid(),SIGUSR1); } /* copy only the smaller amount of two blocks */ oldSize = - (headPtr->head.size) ; if( oldSize < bytes ){ bytes = oldSize ; } for (i=0; ihead.size - sizeof(trailer_t)); if ((headPtr->head.size > 0) || (headPtr->head.size != tail->size)) { return(-1) ; } return(-headPtr->head.size - block_overhead) ; } /* end checkMemObj */ /* checkDebug call checkMemObj so it can be used in debugger */ INT YcheckDebug( where ) VOIDPTR where ; /* must be integer to work in dbx */ { INT size ; if( (size = YcheckMemObj( (char *) where )) == -1 ){ fprintf( stderr, "Memory has been damaged\n" ) ; return( 0 ) ; } else { return( size ) ; } } /* end checkDebug */ /* getListSize(ptr,offset) - returns the size of a linked-list */ /* returns size in bytes. returns -1 if invalid object */ /* example. getListSize(netPtr,&(netPtr->next) ) ; */ INT YgetListSize(ptr, offsetPtr) char *ptr ; /* pointer to beginning of list structure */ char *offsetPtr ; /* pointer to "next" field within structure */ { block_p headPtr; trailer_p tail; INT recordCount = 0 ; INT memInUse = 0 ; INT offset ; INT limit ; /* max number of records */ INT *intPtr ; INT temp ; /* first calculate offset of next field */ offset = offsetPtr - ptr ; /* calculate limit to detect circular link list */ /* the max number of records = MaxMemory/sizeof(record) /* need current size of ptr for calculation */ headPtr = (block_p) ((INT) ptr - sizeof(header_t)); tail = (trailer_p) ( ((INT)headPtr) - headPtr->head.size - sizeof(trailer_t)); if ((headPtr->head.size > 0) || (headPtr->head.size != tail->size)) { return(-1) ; } if( headPtr->head.size ){ limit = - totalAllocationS / headPtr->head.size ; } else { return(-1) ; } while( ptr ) { /* perform check while pointer is not null */ headPtr = (block_p) ((INT) ptr - sizeof(header_t)); tail = (trailer_p) ( ((INT)headPtr) - headPtr->head.size - sizeof(trailer_t)); if ((headPtr->head.size > 0) || (headPtr->head.size != tail->size)) { if( debugFlagS ){ fprintf( stderr, "ERROR[getListSize]:record has corrupted data\n") ; } return(-1) ; } memInUse += - headPtr->head.size ; /* check for circular linked list */ if( recordCount > limit) { fprintf( stderr, "Detected a circular linked list\n") ; return(-1) ; } /* update pointer */ /* calculate addresss of next field */ intPtr = (INT *) (ptr + offset) ; /* next line does indirect addressing - contents of */ /* field is put in temp. Note we use char point but */ /* we need all four bytes of the next field for new pointer */ temp = *intPtr ; ptr = (char *) temp ; recordCount++ ; } return(memInUse) ; } /* debugMemory - turns on memory check debug messages and */ /* memory to all 1's to detect access violations. */ VOID YdebugMemory( flag ) BOOL flag ; { debugFlagS = flag ; } /* *-------------------------------------------------------------- * END OF C MEMORY MANAGEMENT SYSTEM *-------------------------------------------------------------- */ #else /* *-------------------------------------------------------------- * BEGIN NORMAL C MEMORY MANAGEMENT SYSTEM *-------------------------------------------------------------- */ /* use standard calls to malloc, calloc, etc */ char *Ysafe_malloc(size) INT size; { char *p; /*extern char *malloc() ;*/ if ((p = malloc(size)) == (char *) 0) { errno = heap_no_mem ; kill(getpid(),SIGUSR1); } return p; } char *Ysafe_realloc(obj, size) VOIDPTR obj; INT size; { char *p; /* extern char *realloc() ;*/ if ((p = realloc(obj, size)) == (char *) 0) { errno = heap_no_mem ; kill(getpid(),SIGUSR1); } return p; } char *Ysafe_calloc(num, size) INT size, num; { char *p; /*extern char *calloc() ;*/ if ((p = calloc(num,size)) == (char *) 0) { errno = heap_no_mem ; kill(getpid(),SIGUSR1); } return p; } /* when not testing memory just call system free */ VOID Ysafe_free(ptr) VOIDPTR ptr; { free(ptr); return; } VOID Ysafe_cfree(ptr) VOIDPTR ptr; { cfree(ptr); return; } /* ***********DUMMY ROUTINES TO RESOLVE GLOBALS **************** */ /* see above for normal use */ INT YgetCurMemUse() { return(0) ; } INT YgetMaxMemUse() { return(0) ; } INT YcheckMemObj(ptr) char *ptr ; { return(0) ; } INT YgetListSize(ptr, offsetPtr) char *ptr ; /* pointer to beginning of list structure */ char *offsetPtr ; /* pointer to "next" field within structure */ { return(0) ; } VOID YdebugMemory( flag ) INT flag ; { return ; } INT YcheckDebug( where ) VOIDPTR where ; { return ( INT_MAX ) ; } /* end checkDebug */ VOID Yinit_memsize( memsize ) INT memsize ; { return ; } /* end Yinit_memsize */ VOID Ydump_mem() { } /* end Ydump_mem() */ /* *-------------------------------------------------------------- * END NORMAL C MEMORY MANAGEMENT SYSTEM *-------------------------------------------------------------- */ #endif /* print memory error in the same style as perror and psignal */ VOID Ypmemerror( s ) char *s ; { /* first print user message if available */ if( s ){ fprintf( stderr, "%s:", s ) ; } switch(errno){ case heap_ok: fprintf(stderr, "Memory ok - Problem in memory management logic.\n" ) ; break; case heap_bad_block: fprintf(stderr, "Memory block was found to be corrupted.\n" ) ; break; case heap_no_mem: fprintf(stderr, "No memory available to allocate.\n" ) ; break; default: fprintf(stderr, "Error = %0x Unrecognized error code.\n",errno ) ; } } /* end Ypmemerror */ /* ******* memory convenience functions ******* */ /* ALLOCATE an array [lo..hi] of the given size not initialized */ char *Yvector_alloc( lo, hi, size MEM_DEBUG1 ) INT size, lo, hi ; MEM_DEBUG2 { char *array_return ; array_return = (char *) Ysafe_malloc((unsigned) (hi-lo+1)*size MEM_DEBUG1 ) ; if( array_return ){ return( array_return - size * lo ) ; } return( NIL(char *) ) ; } /* end Yvector_alloc */ /* ALLOCATE an array [lo..hi] of the given size initialized to zero */ char *Yvector_calloc( lo, hi, size MEM_DEBUG1 ) INT size, lo, hi ; MEM_DEBUG2 { char *array_return ; array_return = (char *) Ysafe_calloc((unsigned) (hi-lo+1),size MEM_DEBUG1 ) ; if( array_return ){ return( array_return - size * lo ) ; } return( NIL(char *) ) ; } /* end Yvector_calloc */ /* REALLOCATE an array [lo..hi] of the given size no initialization */ char *Yvector_realloc( array_orig, lo, hi, size MEM_DEBUG1 ) VOIDPTR array_orig ; INT size, lo, hi ; MEM_DEBUG2 { char *adj_array ; /* put back the offset */ char *array_return ; /* the new offset */ adj_array = ((char *) array_orig) + lo * size ; array_return = (char *) Ysafe_realloc( adj_array, (unsigned) (hi-lo+1)*size MEM_DEBUG1 ) ; if( array_return ){ return( array_return - size * lo ) ; } return( NIL(char *) ) ; } /* end Yvector_realloc */ VOID Yvector_free( array, lo, size MEM_DEBUG1 ) VOIDPTR array ; INT lo, size ; MEM_DEBUG2 { Ysafe_free( ((char *)array) + lo * size MEM_DEBUG1 ) ; } /* end Yvector_free */ /* ************************* TEST ROUTINES ******************************** */ #ifdef TEST typedef struct { INT bogus_dude ; DOUBLE narly ; char *awesome ; } MEMDATA, *MEMDATAPTR ; main() { MEMDATAPTR array ; MEMDATAPTR vector ; char *string, *Ystrclone() ; YdebugMemory( TRUE ) ; Yinit_memsize( 1024 ) ; /* allocate an array 0..9 */ array = YMALLOC( 10, MEMDATA ) ; fprintf( stderr, "Memory size :%d\n", YgetCurMemUse() ) ; /* allocate an array 1..10 */ vector = YVECTOR_MALLOC( 1, 10, MEMDATA ) ; fprintf( stderr, "Memory size :%d\n", YgetCurMemUse() ) ; /* clone this string */ string = Ystrclone( "Droog" ) ; fprintf( stderr, "Memory size :%d\n", YgetCurMemUse() ) ; /* look at mem.data at this point */ Ydump_mem() ; /* free all the memory */ YFREE( array ) ; YFREE( string ) ; YVECTOR_FREE( vector, 1 ) ; fprintf( stderr, "Memory size :%d\n", YgetCurMemUse() ) ; fprintf( stderr, "Memory max size :%d\n", YgetMaxMemUse() ) ; Ydump_mem() ; exit(0) ; }/* end main() */ #endif /* TEST */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/path.c000066400000000000000000000136531305746555600205620ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: path.c DESCRIPTION:routine for correctly resolving pathnames on system especially ~ and ../ in names. CONTENTS: char *Yfixpath(pathname, fileNotDir ) char *pathname; BOOL fileNotDir; DATE: Jan 25, 1989 - major rewrite of version 1.0 REVISIONS: Sep 15, 1989 - replaced which with my own version. Oct 20, 1990 - pathname should be bufsize since users path may be very long. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) path.c version 3.8 10/23/90" ; #endif #include #include #include #include #include #undef LRECL #define LRECL BUFSIZ static char *getpath (); /* it is up to user to free memory */ char *Yfixpath(given_path, fileNotDir ) /* fix a path to get rid of .. */ char *given_path; BOOL fileNotDir; /* tells whether path is file or directory */ { INT i ; /* token counter */ INT numtokens ; /* number of tokens on line */ char pathname[LRECL] ; /* copy of given_path */ char cur_dir[LRECL] ; /* current working directory */ char temp[LRECL] ; /* temporary buffer */ char *usrpath ; /* the users environment path */ char *getenv() ; /* get the users environment path */ char *result ; /* the final result */ char *rest ; /* the rest of the string */ char *user ; /* the user */ char *Yrelpath() ; /* get relative path */ char **tokens ; /* tokenizer */ /* get the current working directory */ getcwd( cur_dir, LRECL ) ; /* make a copy for strtok is destructive */ strcpy( pathname, given_path ) ; switch( pathname[0] ){ case '~': /* look for ~/ construct */ if( pathname[1] == '/' ){ /* use login as user */ user = NULL ; /* skip over ~/ */ rest = pathname + 2 ; } else { /* get user from string */ user = strtok( pathname," ~//,\n" ) ; /* skip over ~ */ rest = strtok( NULL," ~\n" ) ; } /* call get path to get user path */ strcpy( temp, getpath(user) ); /* copy the rest of the string to result */ strcat( temp, "/" ) ; strcat( temp, rest ) ; result = Ystrclone( temp ) ; break ; case '.': result = Yrelpath( cur_dir, pathname ) ; break ; default: /* no work to be done */ result = pathname ; break ; } /* end switch */ if( fileNotDir ){ if( YfileExists( result ) ){ /* we are done */ return(result); } /* otherwise continue below */ } else { /* a directory */ if( YdirectoryExists( result ) ){ /* we are done */ return(result); } /* otherwise continue below */ } /* now that that has failed try looking in user's path */ /* take last part of file name to search */ tokens = Ystrparser( pathname, " //,\t\n", &numtokens ); /* temp is the name to search for in user path */ strcpy( temp, tokens[numtokens-1] ) ; usrpath = getenv( "PATH" ) ; /* make copy for destructive Ystrparser */ strcpy( pathname, usrpath ) ; tokens = Ystrparser( pathname, ":\t\n", &numtokens ); for( i = 0; i < numtokens; i++ ){ /* use directory to look for file */ strcpy( cur_dir, tokens[i] ) ; strcat( cur_dir, "/" ) ; strcat( cur_dir, temp ) ; /* check to see if file exist with this pathname */ if( YfileExists( cur_dir ) ){ result = Ystrclone( cur_dir ) ; return( result ) ; } } /* at this point we didn't find anything in user's path */ /* return what we are given */ return( given_path ) ; } #include struct passwd *getpwnam(); char *getlogin(); static char *getpath(user) /* get path of home directory */ register char *user; { register char *who; struct passwd *pass; if( !(user) || *(user) == '/'){ who = getlogin(); } else { who = user; } if (pass = getpwnam(who)){ return(pass->pw_dir); } else { return(user); } } #ifdef TEST /* include date.o object for link */ main( argc , argv ) INT argc ; char *argv[] ; { char *Yfixpath() ; /* fix a path to get rid of .. */ if( argc == 2 ){ fprintf( stderr, "given file:%s\n", argv[1] ) ; fprintf( stderr, "resolved pathname:%s\n", Yfixpath(argv[1],TRUE) ) ; } else { fprintf( stderr, "Error[syntax]: a.out pathName\n" ) ; exit(1) ; } exit(0) ; } #endif /* TEST */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/plot.c000066400000000000000000000253671305746555600206110ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: plot.c DESCRIPTION:Plot routines for Cricket Graph. CONTENTS: DATE: Feb 13, 1988 REVISIONS: Jan 29, 1989 - changed msg to YmsgG. Feb 01, 1989 - move all graphic routines to graphics.c Mar 30, 1989 - changed tile datastructure. Apr 29, 1990 - added message.h Fri Jan 18 18:38:36 PST 1991 - fixed to run on AIX. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) plot.c version 1.6 12/9/91" ; #endif #include #include #include #include #include #include #include #define MAXARGS 20 typedef struct { char fileName[LRECL] ; FILE *fp ; BOOL headPrintedAlready ; BOOL graphFlushed ; } YPLOTTYPE, *YPLOTPTR ; static YPLOTTYPE gfileS[MAXARGS] ; static INT gfilenoS = 0 ; static BOOL graphFilesS = TRUE ; static INT findType(); Yplot_control( toggle ) BOOL toggle ; { graphFilesS = toggle ; } /* end YgraphControl */ /* graph init uses variable number of arguments */ Yplot_init( int dval, ... ) { va_list ap ; char *graphName; YPLOTPTR gptr ; va_start(ap, dval) ; if( !(graphFilesS) ){ /* don't do anything if flag is not set */ va_end(ap) ; return ; } while( graphName = va_arg( ap, char * ) ){ /* save graph file name */ gptr = &(gfileS[gfilenoS++]) ; sprintf( gptr->fileName,"%s",graphName ) ; gptr->fp = TWOPEN( graphName, "w", ABORT ) ; gptr->headPrintedAlready = FALSE ; gptr->graphFlushed = TRUE ; } va_end(ap) ; } /* graph init uses variable number of arguments */ Yplot_heading( int dval, ... ) { va_list ap ; char *gName, *varName ; YPLOTPTR gptr ; INT i ; FILE *fp ; va_start(ap, dval) ; if( !(graphFilesS) ){ /* don't do anything if flag is not set */ va_end(ap) ; return ; } /* first argument is always graph file name */ if( !(gName = va_arg( ap, char * ) )){ M(ERRMSG,"GRAPH","problem with first argument\n" ) ; va_end(ap) ; return ; } else { /* find matching file */ for( i=0;i= gfilenoS ){ sprintf( YmsgG, "couldn't find file %s name in opened file list\n" ) ; M(ERRMSG,"GRAPH", YmsgG ) ; return ; } } gfileS[i].headPrintedAlready = TRUE ; while( varName = va_arg( ap, char * ) ){ fprintf( fp, "%s\t", varName ) ; } fprintf( fp, "\n" ) ; va_end(ap) ; } Yplot_close() { INT i ; if( !(graphFilesS) ){ /* don't do anything if flag is not set */ return ; } for( i = 0; i= gfilenoS ){ sprintf( YmsgG, "couldn't find file %s name in opened file list\n" ) ; M(ERRMSG,"GRAPH", YmsgG ) ; return ; } } /* GRAPH( graphFileName, xVarformat, xVar, yVarformat, yVars... ) */ /* second argument is control for xvariable */ if( !(control = va_arg( ap, char * ) )){ M(ERRMSG,"GRAPH","problem with third argument\n" ) ; va_end(ap) ; return ; } /* need to make copy of format since scanner is destructive */ sprintf( copyformatS,"%s",control ) ; tokenBuf = Ystrparser( copyformatS," \n\t\\", &numtokens ) ; if( !(type = findType(tokenBuf,0)) ){ M(ERRMSG,"GRAPH","Unknown control type.\n" ) ; va_end(ap) ; return ; } /* only print if graph has previously been flushed */ /* now that we have type we can get third element */ switch( type ){ case INT_TYPE: gint = va_arg( ap, INT ) ; if( gfileS[i].graphFlushed ){ fprintf( fp, tokenBuf[0], gint ) ; fprintf( fp, "\t" ) ; } break ; case CHAR_TYPE: #ifdef linux gchar = (char) va_arg( ap, int ) ; #else gchar = va_arg( ap, char ) ; #endif if( gfileS[i].graphFlushed ){ fprintf( fp, tokenBuf[0], gchar ) ; fprintf( fp, "\t" ) ; } break ; case STRG_TYPE: gstr = va_arg( ap, char * ) ; if( gfileS[i].graphFlushed ){ fprintf( fp, tokenBuf[0], gstr ) ; fprintf( fp, "\t" ) ; } break ; case DOUB_TYPE: gdoub = va_arg( ap, DOUBLE ) ; if( gfileS[i].graphFlushed ){ fprintf( fp, tokenBuf[0], gdoub ) ; fprintf( fp, "\t" ) ; } break ; } gfileS[i].graphFlushed = FALSE ; /* fourth argument is control for yvariable */ if( !(format = va_arg( ap, char * ) )){ M(ERRMSG,"GRAPH","problem with third argument\n" ) ; va_end(ap) ; return ; } /* need to make copy of format since scanner is destructive */ sprintf( copyformatS,"%s",format ) ; tokenBuf = Ystrparser( copyformatS," \n\t\\", &numtokens ) ; for( i = 0; i< numtokens; i++ ){ if( !(type = findType(tokenBuf,i)) ){ M(ERRMSG,"GRAPH","Unknown control type.\n" ) ; va_end(ap) ; return ; } switch( type ){ case INT_TYPE: gint = va_arg( ap, INT ) ; fprintf( fp, tokenBuf[i], gint ) ; break ; case CHAR_TYPE: #ifdef linux gchar = (char) va_arg( ap, int ) ; #else gchar = va_arg( ap, char ) ; #endif fprintf( fp, tokenBuf[i], gchar ) ; break ; case STRG_TYPE: gstr = va_arg( ap, char * ) ; fprintf( fp, tokenBuf[i], gstr ) ; break ; case DOUB_TYPE: gdoub = va_arg( ap, DOUBLE ) ; fprintf( fp, tokenBuf[i], gdoub ) ; break ; } fprintf( fp, "\t" ) ; } va_end(ap) ; } Yplot_flush( gName ) char *gName ; { INT i ; if( !(graphFilesS) ){ /* don't do anything if flag is not set */ return ; } if( gName ){ for( i=0;i= gfilenoS ){ sprintf( YmsgG, "couldn't find file %s name in opened file list\n" ) ; M(ERRMSG,"GRAPH", YmsgG ) ; return ; } } else { /* if null flush all files */ for( i=0; i< gfilenoS ; i++ ){ if(!(gfileS[i].graphFlushed)){ /* only flush if we have to */ fprintf( gfileS[i].fp, "\n" ) ; fflush( gfileS[i].fp ) ; gfileS[i].graphFlushed = TRUE ; } } } } /* end GRAPHFLUSH */ static INT findType( control, number ) char **control ; INT number ; { char *formatChar ; formatChar = control[number] ; if( formatChar ){ if( strchr(formatChar,'d') ){ return( INT_TYPE ) ; } else if( strchr(formatChar,'f') ){ return( DOUB_TYPE ) ; } else if( strchr(formatChar,'e') ){ return( DOUB_TYPE ) ; } else if( strchr(formatChar,'s') ){ return( STRG_TYPE ) ; } else if( strchr(formatChar,'c') ){ return( CHAR_TYPE ) ; } } return( NULL_TYPE ) ; } /* end findType */ #ifdef TEST main() { INT i ; /* counter */ DOUBLE f ; /* function value */ INT y ; /* integer function value */ /* first initialize two graphs */ Yplot_init( 0, "graph1", "graph_kroy", NULL ) ; /* ------------------------------------------------------------- Now set the heading for the graph. YgraphHeading can be call multiple times but first time will be what is output to the graph file. Remember the Nulls at end. ---------------------------------------------------------------- */ for( i = 1; i <= 10; i++ ){ /* set the first graph heading. It is good to keep heading with */ /* output so it is easy to read the arguments to Ygraph */ Yplot_heading( 0, "graph1", "x_axis", "f(x)", "y2", NULL ) ; /* ------------------------------------------------------------- Ygraph has the following format: Ygraph( filename, x format, x varible, y format, y variables... ------------------------------------------------------------- */ f = (DOUBLE) i ; y = i * i ; Yplot( 0, "graph1", "%d", i, "%4.2le %d", f, y ) ; /* now after each graph has been finished flush data */ Yplot_flush( "graph1" ) ; /* now output another graph */ Yplot_heading( 0, "graph_kroy", "iter", "Temperature", NULL ) ; Yplot( 0, "graph_kroy", "%4.2le", (DOUBLE) i, "%d", 3 * i ) ; Yplot_flush( "graph_kroy" ) ; } /* When we are done with the graph close them */ Yplot_close() ; exit(0) ; } #endif /* TEST */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/program.c000066400000000000000000000123601305746555600212670ustar00rootroot00000000000000/* * Copyright (C) 1988-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: program.c DESCRIPTION:miscellaneous program initialization functions CONTENTS: YinitProgram(char *, char *, INT (*function) ) YexitPgm(int) char *YgetProgName() DATE: Jan 29, 1988 REVISIONS: May 04, 1988 - updated initProgram to include introTextFunction. Added remove_lblanks, directoryExists functions. Sep 26, 1988 - split into three files for archive. Sep 29, 1988 - removed argument from introTextfunction. Jan 25, 1989 - added error for nonzero status for exitPgm. Jan 27, 1989 - changed msg to YmsgG so user knows its global. Apr 27, 1989 - changed to Y prefix. May 8, 1990 - removed \n from message format. Oct 4, 1990 - added Ytimer_start to initialization. Fri Feb 15 15:38:11 EST 1991 - renamed message functions and added timer. Fri Feb 22 23:39:39 EST 1991 - added newline character at exit. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) program.c version 3.8 3/4/92" ; #endif #include #include #include static char programName[LRECL]; static char progVersion[LRECL]; static char progDate[LRECL]; /* ----------------------------------------------------------------- Program control routines initProgram gets the date of compile of program introTextFunction always uses YmsgG (actually a global note G suffix ). The user may perform various initialization in introTextFunction. Returns string with program name, version, and compile date. ----------------------------------------------------------------- */ char *YinitProgram(name,version,introTextFunction) char *name ; char *version ; VOID (*introTextFunction)() ; { char *date , *getCompileDate() ; Ytimer_start() ; /* start the elapsed timer */ sprintf(programName,"%s",name); sprintf(progVersion,"%s",version); if ( date = getCompileDate() ){ sprintf(progDate,"%s",date); } else { sprintf(progDate,"unknown") ; } sprintf( YmsgG, "%s version:%s date:%s", programName,progVersion,progDate) ; /* call the users intro text if available */ /* Intro Text function may use YmsgG as a global variable */ if( introTextFunction ){ (*introTextFunction)() ; } return( YmsgG ) ; } /* end initProgram */ /* exit program gracefully */ YexitPgm(status) INT status ; { INT errorCount, warningCount, mode ; char message[LRECL] , *name ; warningCount = Ymessage_get_warncount() ; errorCount = Ymessage_get_errorcount() ; if( status != 0 && errorCount == 0 ){ /* if we have an error status but no recorded error record error*/ errorCount++ ; } mode = Ymessage_get_mode() ; if( errorCount != 0 || mode != M_SILENT ){ /* make sure we see errors */ Ymessage_mode( M_VERBOSE ) ; } if( name = YgetProgName() ){ if( errorCount ){ sprintf(message,"\n%s terminated abnormally with %d error[s] and %d warning[s]\n\n", name,errorCount,warningCount) ; } else { sprintf(message,"\n%s terminated normally with no errors and %d warning[s]\n\n", name,warningCount) ; } } else { M(WARNMSG,"exitPgm","Unable to get program name. Probably initProgram not used.\n") ; sprintf(message,"Program terminated abnormally with %d error[s] and %d warning[s]\n\n", errorCount,++warningCount) ; } M(MSG,NULL,message) ; /* now write debug file if desired */ YdebugWrite() ; Ymessage_close(); /* Added by Tim, 5/4/11 */ exit(status) ; } /* end exitPgm */ char *YgetProgName() { return(programName); } /*---------------end program control routines --------------------- */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/project.c000066400000000000000000000110331305746555600212620ustar00rootroot00000000000000/* * Copyright (C) 1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /*----------------------------------------------------------------- FILE: project.c DESCRIPTION:Overlap and projection of rectangles. CONTENTS: DATE: Tue Oct 29 15:02:21 EST 1991 REVISIONS: ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) project.c (Yale) version 1.1 11/20/91" ; #endif #include #include static INT xspaceS = 0 ; static INT yspaceS = 0 ; Yproject_space( xspace, yspace ) INT xspace, yspace ; { xspaceS = xspace ; yspaceS = yspace ; } /* end Yproject_space() */ /* function returns whether one cell projects onto another */ INT YprojectX( tile1_left, tile1_right, tile2_left, tile2_right ) INT tile1_left, tile1_right, tile2_left, tile2_right ; { /* ----------------------------------------------------- First check case 2nd tile larger than first complete overlap */ if( tile2_left <= tile1_left && tile1_right <= tile2_right ){ return( OVERLAP1 ) ; /* ----------------------------------------------------- Check if an edge of tile two is encompassed by tile 1 Second check left edge of tile2 : tile1_left <= tile2_left < tile1_right + xspaceS */ } else if( tile1_left<=tile2_left&&tile2_left #include /* initialize queue */ YinitQueue( queue, node ) YQUEUE *queue ; char *node ; { YQUEUEPTR temp ; queue->top_of_queue = temp = YMALLOC( 1, YQUEUEBOX ) ; temp->next = NULL ; queue->bot_of_queue = temp ; temp->data = node ; } /* end YinitQueue */ /* top queue return the element at top of the queue */ char *YtopQueue( queue ) YQUEUE *queue ; { YQUEUEPTR temp ; char *data ; if( temp = queue->top_of_queue ){ data = temp->data ; queue->top_of_queue = temp->next ; YFREE( temp ) ; return( data ) ; } else { /* queue is empty */ return( NULL ) ; } } /* end YtopQueue */ /* add a vertex to the end of the queue */ Yadd2Queue( queue, node ) YQUEUE *queue ; char *node ; { if( queue->top_of_queue ){ queue->bot_of_queue->next= YMALLOC( 1, YQUEUEBOX ) ; queue->bot_of_queue = queue->bot_of_queue->next ; queue->bot_of_queue->next = NULL ; queue->bot_of_queue->data = node ; } else { YinitQueue( queue, node ) ; } } /* end Yadd2Queue */ /* check status of the queue */ YQUEUEPTR YqueueNotEmpty( queue ) YQUEUE *queue ; { return( queue->top_of_queue ) ; } /* debug function to dump the contents of the queue */ YdumpQueue( queue ) YQUEUE *queue ; { YQUEUEPTR temp ; fprintf( stderr,"Queue:" ) ; if( temp = queue->top_of_queue ){ for( ;temp; temp=temp->next ){ #if SIZEOF_VOID_P == 64 fprintf( stderr,"%ld ", (INT)temp->data ) ; #else fprintf( stderr,"%d ", (INT)temp->data ) ; #endif } fprintf( stderr,"\n" ) ; } else { /* queue is empty */ fprintf( stderr,"empty.\n" ) ; } } /* end YdumpQueue */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/quicksort.c000066400000000000000000000147131305746555600216500ustar00rootroot00000000000000/* * Copyright (C) 1983 Berkeley * Copyright (C) 1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char SccsId[] = "@(#) quicksort.c version 3.3 3/6/92" ; #endif /* modified version of @(#)qsort.c 4.2 (Berkeley) 3/9/83 */ #include static INT qsz; /* size of each record */ static INT thresh; /* THRESHold in chars */ static INT mthresh; /* MTHRESHold in chars */ static INT (*compare_fun)(); /* comparison function */ static qst(); #define compar(a,b) ( (*compare_fun)(a,b) ) #define THRESH 4 /* threshold for insertion */ #define MTHRESH 6 /* threshold for median */ VOID Yquicksort(base, n, size, compare ) char *base; INT n; INT size; INT (*compare)() ; { register char c, *i, *j, *lo, *hi; char *min, *max; if (n <= 1) return; compare_fun = compare ; qsz = size; thresh = qsz * THRESH; mthresh = qsz * MTHRESH; max = base + n * qsz; if (n >= THRESH) { qst(base, max); hi = base + thresh; } else { hi = max; } /* * First put smallest element, which must be in the first THRESH, in * the first position as a sentinel. This is done just by searching * the first THRESH elements (or the first n if n < THRESH), finding * the min, and swapping it into the first position. */ for (j = lo = base; (lo += qsz) < hi; ) if (compar(j, lo) > 0) j = lo; if (j != base) { /* swap j into place */ for (i = base, hi = base + qsz; i < hi; ) { c = *j; *j++ = *i; *i++ = c; } } if (n == 2) return; /* * With our sentinel in place, we now run the following hyper-fast * insertion sort. For each remaining element, min, from [1] to [n-1], * set hi to the index of the element AFTER which this one goes. * Then, do the standard insertion sort shift on a character at a time * basis for each element in the frob. */ for (min = base; (hi = min += qsz) < max; ) { while ((hi -= qsz) >= base && compar(hi, min) > 0) /* void */; if ((hi += qsz) != min) { for (lo = min + qsz; --lo >= min; ) { c = *lo; for (i = j = lo; (j -= qsz) >= hi; i = j) *i = *j; *i = c; } } } } /* * qst: * Do a quicksort * First, find the median element, and put that one in the first place as the * discriminator. (This "median" is just the median of the first, last and * middle elements). (Using this median instead of the first element is a big * win). Then, the usual partitioning/swapping, followed by moving the * discriminator into the right place. Then, figure out the sizes of the two * partions, do the smaller one recursively and the larger one via a repeat of * this code. Stopping when there are less than THRESH elements in a partition * and cleaning up with an insertion sort (in our caller) is a huge win. * All data swaps are done in-line, which is space-losing but time-saving. * (And there are only three places where this is done). */ static qst(base, max) char *base, *max; { register char c, *i, *j, *jj; register INT ii; char *mid, *tmp; INT lo, hi; /* * At the top here, lo is the number of characters of elements in the * current partition. (Which should be max - base). * Find the median of the first, last, and middle element and make * that the middle element. Set j to largest of first and middle. * If max is larger than that guy, then it's that guy, else compare * max with loser of first and take larger. Things are set up to * prefer the middle, then the first in case of ties. */ lo = max - base; /* number of elements as chars */ do { mid = i = base + qsz * ((lo / qsz) >> 1); if (lo >= mthresh) { j = (compar((jj = base), i) > 0 ? jj : i); if (compar(j, (tmp = max - qsz)) > 0) { /* switch to first loser */ j = (j == jj ? i : jj); if (compar(j, tmp) < 0) j = tmp; } if (j != i) { ii = qsz; do { c = *i; *i++ = *j; *j++ = c; } while (--ii); } } /* * Semi-standard quicksort partitioning/swapping */ for (i = base, j = max - qsz; ; ) { while (i < mid && compar(i, mid) <= 0) i += qsz; while (j > mid) { if (compar(mid, j) <= 0) { j -= qsz; continue; } tmp = i + qsz; /* value of i after swap */ if (i == mid) { /* j <-> mid, new mid is j */ mid = jj = j; } else { /* i <-> j */ jj = j; j -= qsz; } goto swap; } if (i == mid) { break; } else { /* i <-> mid, new mid is i */ jj = mid; tmp = mid = i; /* value of i after swap */ j -= qsz; } swap: ii = qsz; do { c = *i; *i++ = *jj; *jj++ = c; } while (--ii); i = tmp; } /* * Look at sizes of the two partitions, do the smaller * one first by recursion, then do the larger one by * making sure lo is its size, base and max are update * correctly, and branching back. But only repeat * (recursively or by branching) if the partition is * of at least size THRESH. */ i = (j = mid) + qsz; if ((lo = j - base) <= (hi = max - i)) { if (lo >= thresh) qst(base, j); base = i; lo = hi; } else { if (hi >= thresh) qst(i, max); max = j; } } while (lo >= thresh); } graywolf-0.1.4+20170307gite1bf319/src/Ylib/radixsort.c000066400000000000000000000536161305746555600216500ustar00rootroot00000000000000/*- BSD copyright says: * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static char SccsId[] = "@(#) radixsort.c (Yale) version 1.4 4/18/92" ; #endif #include #include #define RADIX_PREFIX 4 /* radixsort.c, radixsort.h: linear-per-byte in-memory string sort Daniel J. Bernstein, brnstnd@nyu.edu; Keith Bostic, bostic@ucbvax.berkeley.edu. No dependencies. Requires malloc, free, bcopy, bzero. Can use -DUCHAR_MAX. 10/5/91 DJB: Made c static, added ctr. 7/23/91 DJB: Baseline. radixsort/DJB 3.0. See top for BSD copyright. No known patent problems. Documentation in radixsort.3, portions based on BSD documentation. History: I discovered adaptive distribution sort in 1987. (I haven't published a paper on it---it's too trivial for that---though I did mention it in a letter to Knuth.) It grew out of a suggestion quoted in Knuth's section on quicksort et al., volume 3, page 128: ``John McCarthy has suggested setting K \approx (u + v)/2, if all keys are known to lie between u and v.'' What's the biggest problem with MSD radix sort? You can waste lots of time considering ranges of keys that don't even exist! In distribution sort, however, you usually start by finding the minimum and maximum keys. Here McCarthy's suggestion pops in. To sort a pile of floating-point numbers, find their minimum and maximum, divide the interval evenly into n subintervals, and split the numbers into piles by interval just as in MSD radix sort. Just as in quicksort, stop splitting when a pile can be sorted efficiently by a small-scale method. That's adaptive distribution sort, and it turns out to be hellishly fast for sorting floating-point data. The credit really belongs with McCarthy---I only generalized from 2 to n. Adaptive distribution sort can be applied to strings, too: find the first character where two strings in the pile differ, and distribute on that character. There's no fine line between adaptive distribution sort and MSD radix sort, but in any case you get a big speed boost from sorting small piles by a small-scale method. See especially Knuth, exercise 5.2.5-10. Computer scientists should note that this method is linear in the number of bytes being sorted. Sometime in 1989, as I recall, I saw a notice that someone had discovered an o(n log n) method of sorting n integers. The method depended on all sorts of weid bit manipulations and was utterly impractical. As the integers had to be short anyway, MSD radix sort worked in O(n) time. My guess is that most computer scientists don't learn about MSD radix sort (and hence don't know that sorting is linear-per-byte) because it's widely seen as having too big a constant factor to be practical. This radixsort() is a constructive proof that the opposite is true. I ended up sending this code to Berkeley. Keith Bostic cleaned it up, fixed a few bugs, added a shell sort for the small case, and did several helpful optimizations. radixsort() will be part of BSD 4.4. I took back his version and modified it to what you see below. Among other things, I ported it from ANSI C back to the rest of the world, cleaned up some of the comments, added a proof that part of the method actually works, added the radixsort5(), radixsort7(), and radixsort3() variants, restored the original indentation, fixed an overly conservative estimate of the necessary stack size, and plugged a memory leak. */ #define blob unsigned char /* technically, shouldn't be typedefed */ /* KB says: * __rspartition is the cutoff point for a further partitioning instead * of a shellsort. If it changes check __rsshell_increments. Both of * these are exported, as the best values are data dependent. */ #ifndef NPARTITION #define NPARTITION 40 #endif int __rspartition = NPARTITION; int __rsshell_increments[] = { 4, 1, 0, 0, 0, 0, 0, 0 }; /* KB says: * Shellsort (diminishing increment sort) from Data Structures and * Algorithms, Aho, Hopcraft and Ullman, 1983 Edition, page 290; * see also Knuth Vol. 3, page 84. The increments are selected from * formula (8), page 95. Roughly O(N^3/2). */ static void shellsort(p,index,n,tr) register blob **p; register blob *tr; register int index; register int n; { register blob ch; register blob *s1; register blob *s2; register int incr; register int *incrp; register int t1; register int t2; incrp = __rsshell_increments; while (incr = *incrp++) for (t1 = incr;t1 < n;++t1) for (t2 = t1 - incr;t2 >= 0;) { s1 = p[t2] + index; s2 = p[t2 + incr] + index; while ((ch = tr[*s1++]) == tr[*s2] && ch) ++s2; if (ch > tr[*s2]) { s1 = p[t2]; p[t2] = p[t2 + incr]; p[t2 + incr] = s1; t2 -= incr; } else break; } } /* KB says: * Stackp points to context structures, where each structure schedules a * partitioning. Radixsort exits when the stack is empty. * * If the buckets are placed on the stack randomly, the worst case is when * all the buckets but one contain (npartitions + 1) elements and the bucket * pushed on the stack last contains the rest of the elements. In this case, * stack growth is bounded by: * * limit = (nelements / (npartitions + 1)) - 1; * * This is a very large number, 52,377,648 for the maximum 32-bit signed int. * * By forcing the largest bucket to be pushed on the stack first, the worst * case is when all but two buckets each contain (npartitions + 1) elements, * with the remaining elements split equally between the first and last * buckets pushed on the stack. In this case, stack growth is bounded when: * * for (partition_cnt = 0; nelements > npartitions; ++partition_cnt) * nelements = * (nelements - (npartitions + 1) * (nbuckets - 2)) / 2; * * The bound is: * * limit = partition_cnt * (nbuckets - 1); * * This is a much smaller number, 4590 for the maximum 32-bit signed int. Note inserted by DJB: About time I proved this... Fix the number of buckets, b. Any given pile of n elements is split into m stack piles and b - m small-scale piles which immediately disappear. We ignore the case where the pile is split into only one pile of its original size---any pile will be split into smaller piles eventually. Say the stack is left with piles of sizes p_1 ... p_m, each at least P + 1, none equal to n, while x elements, for some x from 0 to m'P, are in small-scale piles. (Here P is the cutoff.) We must have p_1 + ... + p_m + x = n. Depending on the other (p,x) constraints chosen, we define s(n) as the maximum stack size for n elements. As the subpile distributions are independent, clearly s(n) = max_m max_(p,x) max {s(p_1),s(p_2) + 1,...,s(p_m) + m - 1} over all valid m and (p,x). In particular, if m > 0 then we must have n > p_1 >= P + 1, so if n <= P + 1 then the maximum is (vacuously) 0. So s(n) is monotone increasing for n <= P + 1. An easy induction shows that s(n) is in fact 0 for all n < 2P + 2. Clearly s(n) is monotone: for n >= P + 2 we choose m = 1, p_1 = n - 1, and x = 0, and we see s(n) >= s(p_1) = s(n - 1). For m = 0, the maximum always equals 0, and for m = 1, the maximum always equals a previous s(p_1), so we have s(n) = max { max_{k=2} max_(p,x) max s(p_j) + j - 1 }. For convenience we define t(n) = max_{m>=2} max_(p,x) max s(p_j) + j - 1. Fix n. Fix m >= 2. Consider a (p,x) achieving the maximum value of max s(p_j) + j - 1. Since p_1 >= P + 1, we have p_2 <= n - P - 1. If x isn't 0, we can move an element from one of the small-scale piles to stack pile p_2, under either of the constraints in question. This increases p_2---hence does not decrease s(p_2)---without affecting the other s(p_j). Hence there is a (p,x) with smaller x also achieving the maximum. So consider a (p,0) achieving the maximum, and say max s(p_j) + j - 1 is achieved at j = i. If we exchange p_i and p_j while meeting the constraints, we must not be at a higher maximum; in particular, s(p_i) + j - 1 <= s(p_i) + i - 1, so j <= i. Restrict attention the the case without constraints, NC. The choice of j is unrestricted, so in particular m <= i and hence i = m. Thus t(n) equals max_{m>=2} s(p_m) + m - 1. Since all p_j are at least P + 1, we have p_m + (P + 1)(m - 1) <= p_m + ... + p_1 = n p_m <= n - (P + 1)(m - 1) s(p_m) <= s(n - (P + 1)(m - 1)) t(n) <= max_{m>=2} s(n - (P + 1)(m - 1)) + m - 1 (NC), and it is easy to see that for n >= (P + 1)m, we can choose p_m as n - (P + 1)(m - 1) >= P + 1 and all other p_j = P + 1, so that the bound is achieved: t(n) = max_{m>=2} s(n - (P + 1)(m - 1)) + m - 1 for n/(P + 1) >= m. (NC) For 2 <= n/(P + 1) < b, we can choose m anywhere between 2 and f = floor(n/(P + 1)) inclusive. Now s(n) = max { max s(k), max_{2<=m= P + 1. (NC) Now consider the push-largest-pile-first constraint, FC. This requires that p_1 >= p_j for all j. Hence we cannot swap p_1 with p_i. However, if i is not 1 then we can swap p_j with p_i for all j > 1, hence j <= i for all j between 2 and m, hence i is m. Thus the maximum is achieved either at i = 1 or at i = m, and we have t(n) = max_{m>=2} max_(p,0) max { s(p_m) + m - 1, s(p_1) }. (FC) Take a p vector achieving the maximum of max { s(p_m) + m - 1, s(p_1) }, with m fixed. Suppose some p_j for j between 2 and m - 1 inclusive is larger than P + 1. (This is vacuous for m = 2.) Then we can subtract one from p_j and add one to p_1, preserving the constraint and not decreasing the maximum. Hence the maximum is achieved somewhere with all p_j = P + 1 for 2 <= j < m, i.e., p_1 + p_m + (P + 1)(m - 2) = n. (FC) Furthermore, p_1 >= p_m. Hence 2p_1 >= n - (P + 1)(m - 2), and p_1 can range from ceiling((n - (P + 1)(m - 2))/2) up to n - (P + 1). Similarly, 2p_m <= n - (P + 1)(m - 2), so p_m can range from P + 1 up to floor((n - (P + 1)(m - 2))/2). The global maximum of these quantities simultaneously equals the global maximum of them individually, so if all bounds can be achieved then t(n) = max_{m>=2} max { s(n - (P + 1)), s(floor((n - (P + 1)(m - 2))/2)) + m - 1 }. (FC) This can be achieved if n - (P + 1) >= ceiling((n - (P + 1)(m - 2))/2) and, equivalently, P + 1 <= floor((n - (P + 1)(m - 2))/2), since in that case we can choose both p_1 and p_m as stated. These reduce after some simple manipulation to n >= (P + 1)m, i.e., m <= floor(n/(P + 1)). For other m it is not possible to choose any valid p_i (exercise). We'd like to show inductively that for all n >= 2P + 2 we have s(n) = u(n) with u(n) = max_{m>=2} s(floor((n - (P + 1)(m - 2))/2)) + m - 1. (FC,*) To do this we need only show that the other terms of the maximum do not ``get in the way,'' i.e., that u(n) >= s(n - (P + 1)) and u(n) >= s(k) for k < n. The second half is easy: s(k) = u(k), which is at most u(n) by monotonicity of s. The first half also follows from the induction: s(n) = max_m s(floor((n - (P + 1)(m - 2))/2)) + m - 1 s(n - (P + 1)) = u(n - (P + 1)) = max_{m>=2} s(floor((n - (P + 1) - (P + 1)(m - 2))/2)) + m - 1 <= max_{m>=2} s(floor((n - (P + 1)(m - 2))/2)) + m - 1 = u(n) (FC) again by the monotonicity of s. This proves (FC,*). For small n, i.e., floor(n/(P + 1)) = f with 2 <= f <= b, we can choose m = f, so s(n) is at least s(floor((n - (P + 1)(f - 2))/2)) + f - 1. The floor term is at most P + 1, so s(n) >= f - 1. Furthermore, s in the constrained case is at most s in the unconstrained case, so s(n) = f - 1. For larger n, by similar logic, the maximum is attained at m = b, so we finally have s(n) = floor(n/(P + 1)) - 1 for n < (b + 1)(P + 1) s(n) = s(floor((n - (P + 1)(b - 2))/2)) + b - 1 otherwise (FC) As in the first case s(n) is always bounded by b - 1, we can calculate a bound on s(n) by repeatedly setting n to floor(n - (P + 1)(b - 2))/2) until it is under 2P + 2 (so that s(n) = 0), counting the number of iterations necessary, and multiplying by b - 1. And that's what we wanted to prove. */ #ifndef UCHAR_MAX /* XXX: we aren't even giving a chance for a definition! */ #define UCHAR_MAX 256 #endif #define NBUCKETS (UCHAR_MAX + 1) typedef struct { blob **bot; int index; int n; } context; #define STACKPUSH { \ stackp->bot = p; \ stackp->n = n; \ stackp->index = index; \ ++stackp; \ } #define STACKPOP { \ if (stackp == stack) \ break; \ --stackp; \ bot = stackp->bot; \ n = stackp->n; \ index = stackp->index; \ } /* KB says: * This uses a simple sort as soon as a bucket crosses a cutoff point, * rather than sorting the entire list after partitioning is finished. * This should be an advantage. Note from DJB: The original comment read ``There is no strong evidence that this is an advantage.'' Depressing. Here's what I wrote in response: Of course it's an advantage: it has to be, I coded it that way. :-) Seriously, I just coded the sort that way since I was following Knuth's description of MSD to the hilt. As you can imagine, though, doing the sort this way saves just a bit of paging of the index array. It also means that the simple sort doesn't have to worry about crossing past already-determined boundaries---for an average 2x gain. Trust me, it's an advantage. */ int Yradixsort5(l1,n,endchar,tab,indexstart) blob **l1; register int n; unsigned int endchar; /* could use blob, but chars are unsafe with prototypes */ blob *tab; int indexstart; { register int i; register int index; register int t1; register int t2; register blob **l2; register blob **p; register blob **bot; register blob *tr; context *stack; context *stackp; static int c[NBUCKETS + 1]; static int *ctr[NBUCKETS + 1]; int max; blob ltab[NBUCKETS]; /* local (default) table */ if (n <= 1) return 0; /* Allocate the stack. */ t1 = (__rspartition + 1) * (NBUCKETS - 2); for (i = 0,t2 = n;t2 > __rspartition;i += NBUCKETS - 1) t2 = (t2 - t1)/2; /* could go negative! but that's okay */ if (!i) stack = stackp = 0; else if (!(stack = stackp = YMALLOC(i, context) )) return -1; /* KB says: * There are two arrays, one provided by the user (l1), and the * temporary one (l2). The data is sorted to the temporary stack, * and then copied back. The speedup of using index to determine * which stack the data is on and simply swapping stacks back and * forth, thus avoiding the copy every iteration, turns out to not * be any faster than the current implementation. */ if (!(l2 = YMALLOC( n, blob *))) { YFREE(stackp); return -1; } /* KB says: * tr references a table of sort weights; multiple entries may * map to the same weight; EOS char must have the lowest weight. */ if (tab) tr = tab; else { t2 = endchar; for (t1 = 0;t1 < t2;++t1) ltab[t1] = t1 + 1; ltab[t2] = 0; for (t1 = t2 + 1;t1 < NBUCKETS;++t1) ltab[t1] = t1; tr = ltab; } for (t1 = 0;t1 < NBUCKETS;++t1) ctr[t1] = c + tr[t1]; /* First sort is entire pile. */ bot = l1; index = indexstart; for (;;) { /* Clear the bucket count array. XXX: This isn't portable to */ /* machines where the byte representation of int 0 isn't all */ /* zeros. :-) */ bzero((char *)c,sizeof(c)); /* Compute number of items that sort to the same bucket for this index. */ p = bot; i = n; while (--i >= 0) ++*ctr[(*p++)[index]]; /* KB says: * Sum the number of characters into c, dividing the temp stack * into the right number of buckets for this bucket, this index. * c contains the cumulative total of keys before and included in * this bucket, and will later be used as an index to the bucket. * c[NBUCKETS] contains the total number of elements, for determining * how many elements the last bucket contains. At the same time, we * find the largest bucket so it gets pushed first. */ t2 = __rspartition; max = t1 = 0; for (i = 0;i <= NBUCKETS;++i) { if (c[i] > t2) { t2 = c[i]; max = i; } t1 = c[i] += t1; } /* Partition the elements into buckets; c decrements through the */ /* bucket, and ends up pointing to the first element of the bucket. */ i = n; while (--i >= 0) { --p; l2[--*ctr[(*p)[index]]] = *p; } /* Copy the partitioned elements back to the user stack. */ bcopy(l2,bot,n * sizeof(blob *)); ++index; /* KB says: * Sort buckets as necessary; don't sort c[0], it's the * EOS character bucket, and nothing can follow EOS. */ for (i = max;i;--i) { if ((n = c[i + 1] - (t1 = c[i])) < 2) continue; p = bot + t1; if (n > __rspartition) STACKPUSH else shellsort(p,index,n,tr); } for (i = max + 1;i < NBUCKETS;++i) { if ((n = c[i + 1] - (t1 = c[i])) < 2) continue; p = bot + t1; if (n > __rspartition) STACKPUSH else shellsort(p,index,n,tr); } /* Break out when stack is empty */ STACKPOP } YFREE(l2); if( stack ) YFREE(stack); return 0; } int Yradixsort_pref(l1,n) blob **l1; register int n; { return Yradixsort5(l1,n,EOS,NULL,RADIX_PREFIX); } int Yradixsort4(l1,n,endchar,tab) blob **l1; register int n; unsigned int endchar; blob *tab; { return Yradixsort5(l1,n,endchar,tab,0); } int Yradixsort(l1,n,tab,endchar) blob **l1; register int n; blob *tab; unsigned int endchar; { return Yradixsort5(l1,n,endchar,tab,0); } int Yradixsort3(l1,n,endchar) blob **l1; register int n; unsigned int endchar; { return Yradixsort5(l1,n,endchar,(blob *) 0,0); } /* BSD sccs says: static char sccsid[] = "@(#)radixsort.c 5.7 (Berkeley) 2/23/91"; but this is (heavily) modified. */ /* build a prefix for the string. returns where to add to the string */ char *Yradix_prefix( buffer, num ) char *buffer ; INT num ; { buffer[0] = (char) ((num >> 24) & 0x000000FF) ; buffer[1] = (char) ((num >> 16) & 0x000000FF) ; buffer[2] = (char) ((num >> 8) & 0x000000FF) ; buffer[3] = (char) num & 0x000000FF ; buffer[4] = EOS ; return( buffer+4 ) ; } /* end Yradix_prefix() */ /* given a prefix string returns the number (prefix) at the start */ INT Yradix_number( buffer ) char *buffer ; { unsigned int num ; unsigned int temp ; temp = ( ((unsigned int) buffer[0]) << 24) & 0xFF000000 ; num = temp ; temp = ( ((unsigned int) buffer[1]) << 16) & 0x00FF0000 ; num |= temp ; temp = ( ((unsigned int) buffer[2]) << 8) & 0x0000FF00 ; num |= temp ; temp = ( ((unsigned int) buffer[3]) ) & 0x000000FF ; num |= temp ; return( num ) ; } /* end INT Yradix_number() */ char *Yradix_suffix( buffer ) char *buffer ; { return( buffer+4 ) ; } /* end Yradix_suffix() */ char *Yradix_pref_clone( buffer ) char *buffer ; { INT i, len ; char *new_string ; len = strlen( buffer + 4 ) + 4 + 1 ; new_string = YMALLOC( len, char ) ; for( i = 0 ; i < len ; i++ ){ new_string[i] = buffer[i] ; } return( new_string ) ; } /* end Yradix_pref_clone() */ #ifdef TEST #define NUM_ALLOC 10 typedef struct { char sort_weight[15] ; int weight ; } INFO, *INFOPTR ; main() { INFOPTR *array ; INFOPTR aptr ; INT i, num ; char buffer[20] ; char *bufferptr ; char *sort_field ; Yset_random_seed( Yrandom_seed() ) ; array = YMALLOC( NUM_ALLOC, INFOPTR ) ; for( i = 0 ; i < NUM_ALLOC ; i++ ){ aptr = array[i] = YMALLOC( 1, INFO ) ; aptr->weight = Yacm_random() ; /* store the original place in the prefix of the sort field */ /* Yradix_prefix returns back the new start of the string */ sort_field = Yradix_prefix( aptr->sort_weight, i ) ; sprintf( sort_field, "%10d", aptr->weight ) ; fprintf( stderr, "array[%d] = %d\n", i, aptr->weight ) ; } Yradixsort_pref( array, NUM_ALLOC ) ; fprintf( stderr, "\nAfter the sort:\n" ) ; for( i = 0 ; i < NUM_ALLOC ; i++ ){ aptr = array[i] ; num = Yradix_number( aptr->sort_weight ) ; fprintf( stderr, "array[%d] = %10d (originally array[%d])\n", i, aptr->weight, num ) ; } num = array[0]->weight ; fprintf( stderr, "number = %d\n", num ) ; bufferptr = Yradix_prefix( buffer, num ) ; fprintf( stderr, "prefix = %s\n", bufferptr ) ; num = Yradix_number( buffer ) ; fprintf( stderr, "number = %d\n", num ) ; } /* end main() */ #endif /* TEST */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/rand.c000066400000000000000000000070701305746555600205460ustar00rootroot00000000000000/* * Copyright (C) 1988-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: rand.c DESCRIPTION:mimimum standard random number generator function. This random generator replaces the poor Berkeley 4.2 random generator using generators discussed in the Communications of the ACM. See articles by L'Ecuyer and Park/Miller in June 1988 and October 1988 resp. CONTENTS: INT acm_random() set_random_seed(int) DATE: Oct 27, 1988 REVISIONS: Mar 21, 1989 - added get current value of random variable. Now we can restart TimberWolf with same seed. Tue Apr 7 09:37:53 EDT 1992 - now you don't need to initialize random number generator if you don't care. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) rand.c version 3.8 4/7/92" ; #endif #include #include static INT randVarS = 1 ; /* random number */ #define A_RAND 16807 /* good generator multiplier */ #define M_RAND 2147483647 /* 2 ** 31 - 1 */ #define Q_RAND 127773 /* m / a */ #define R_RAND 2836 /* m mod a */ /* returns a random number in [0..2**31 - 1] */ INT Yacm_random() { register INT k_rand ; k_rand = randVarS / Q_RAND ; randVarS = A_RAND * (randVarS - k_rand * Q_RAND) - (k_rand * R_RAND) ; if( randVarS < 0 ){ randVarS += M_RAND ; } return( randVarS ) ; } /* end acm_random */ Yset_random_seed( seed ) INT seed ; { seed = ABS(seed) ; if( seed == 0 ){ seed++ ; } randVarS = seed ; } /* end set_random_seed */ INT Yget_random_var() { return( randVarS ) ; } /* end get_random_var */ #ifdef TEST /* test whether generator works correctly. */ main() { INT n, randnum ; Yset_random_seed( 1 ) ; for( n = 1; n <= 10000; n++ ){ randnum = Yacm_random() ; } printf( "The final value is randnum:%d\n", randnum ) ; printf( "It should be 1043618065 if everything is correct.\n" ) ; printf( "See article.\n\n" ) ; } #endif /* TEST */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/rbtree.c000066400000000000000000001156441305746555600211140ustar00rootroot00000000000000/* * Copyright (C) 1990-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /*----------------------------------------------------------------- FILE: rbtree.c DESCRIPTION:Red-black Binary tree routines. CONTENTS: DATE: Mar 30, 1990 REVISIONS: Apr 19, 1990 - Added Yrbtree_dump() Apr 28, 1990 - Added Yrbtree_free and Yrbtree_interval. Oct 4, 1990 - rewrote to make Yrbtree_interval and enumerate work with more that one tree. Oct 10, 1990 - added Yrbtree_size. Oct 22, 1990 - added user_delete function to rbtree_delete. Nov 02, 1990 - added Yrbtree_interval_free function -RAW Tue Jan 15 02:13:35 EST 1991 - fixed problem with rbtree_interval. Fri Feb 8 16:31:34 EST 1991 - fixed voidptr type casts Sat Feb 23 04:59:18 EST 1991 - added debug. Apr 01, 1991 - maintain tree size instead of recounting -RAW Thu Apr 18 00:41:37 EDT 1991 - fixed missing message.h and spelling error. Apr 19, 1991 - added Yrbtree_verify for debugging -RAW Sun Apr 28 14:03:44 EDT 1991 - fixed problem with Yrbtree_interval using wrong comparison function. Moved comparison function initialization to proper place. Mon Aug 12 15:55:51 CDT 1991 - removed offset argument to initialization of tree in order to eliminate compiler problems. Thu Oct 10 17:28:21 EDT 1991 - added rbtree_resort and copy. Thu Oct 17 11:19:18 EDT 1991 - added rbtree_pred and rbtree_rev_list ( reverse list ) 10/18/91 - Changed startFlag from INT to BOOL for gcc -RAW Tue Oct 29 15:00:58 EST 1991 - added two search routines which keep track where you are in the tree. Mon Dec 9 15:34:09 EST 1991 - now deck datastructures are associated with each tree so that memory can be freed correctly. Sun Dec 15 02:39:26 EST 1991 - added example program for beginners. Sun Jan 19 17:31:34 EST 1992 - added Yrbtree_deleteCurrentInterval, Yrbtree_deleteCurrentEnumerate, and fixed Yrbtree_search_closest. Fri Feb 7 16:47:57 EST 1992 - added Yrbtree_interval_size. Wed Feb 26 03:55:15 EST 1992 - fixed problem with successor routines when passed nilS. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) rbtree.c (Yale) version 3.38 4/18/92" ; #endif #define YTREE_H_DEFS #include #include #include #include /* define macros for easier reading of the code */ #define comp_f( a, b ) ( (*comp_func)(a,b) ) #define BLACK 0 #define RED 1 typedef struct bin_tree { struct bin_tree *left ; struct bin_tree *right ; struct bin_tree *parent ; VOIDPTR data ; BOOL color ; } BINTREE, *BINTREEPTR ; typedef struct tree { BINTREEPTR root ; /* the root of the tree */ INT (*compare_func)() ; /* how to compare two keys */ INT size; /* current size of tree */ BINTREEPTR intervalPtr; /* current position in interval search */ BINTREEPTR searchPtr; /* current position in search */ BINTREEPTR enumeratePtr; /* current position in enumeration */ YDECKPTR enumerateDeck; /* enumerate pointer deck */ YDECKPTR intervalDeck; /* interval pointer deck */ } YTREEBOX, *YTREEPTR ; #include /* ***************** STATIC VARIABLE DEFINITIONS ******************* */ static INT treeSizeS ; /* the size of a tree */ static BINTREE sentinelS ; /* build a sentinel */ static BINTREEPTR nilS ; /* pointer to sentinel */ static BINTREE recalc_sentinelS ; /* build a recalculate flag */ static BINTREEPTR recalcS ; /* pointer to recalc flag */ /* ***************** STATIC FUNCTION DEFINITIONS ******************* */ static BINTREEPTR tree_search( P2(YTREEPTR tree, char *key) ) ; static BINTREEPTR tree_suc( P1(BINTREEPTR ptr) ) ; static BINTREEPTR tree_pred( P1(BINTREEPTR ptr) ) ; static left_rotate( P2(YTREEPTR tree, BINTREEPTR x) ) ; static right_rotate( P2(YTREEPTR tree, BINTREEPTR x) ) ; static tree_free( P1(BINTREEPTR ptr) ) ; static free_tree_and_data( P2(BINTREEPTR ptr, VOID (*userDelete)() ) ) ; static tree_delete( P3(YTREEPTR tree, BINTREEPTR z, VOID (*userDelete)() ) ) ; static tree_dump( P4(YTREEPTR tree,BINTREEPTR ptr, VOID (*print_key)(),INT printTab) ) ; YTREEPTR Yrbtree_init( compare_func ) INT (*compare_func)() ; /* user specifies key function */ { YTREEPTR tree ; /* the current tree being built */ /* initialize nilS */ nilS = &sentinelS ; nilS->parent = NIL(BINTREEPTR) ; nilS->right = NIL(BINTREEPTR) ; nilS->left = NIL(BINTREEPTR) ; nilS->data = NIL(VOIDPTR) ; nilS->color = BLACK ; recalcS = &recalc_sentinelS ; tree = (YTREEPTR) YMALLOC( 1, YTREEBOX ) ; tree->root = nilS ; tree->compare_func = compare_func ; tree->enumerateDeck = NIL(YDECKPTR); tree->intervalDeck = NIL(YDECKPTR) ; tree->intervalPtr = NIL(BINTREEPTR) ; tree->searchPtr = NIL(BINTREEPTR) ; tree->enumeratePtr = NIL(BINTREEPTR) ; tree->size = 0; return( tree ) ; } /* Yrbtree_init */ /* used internally in this routine */ static BINTREEPTR tree_search( tree, key ) YTREEPTR tree ; char *key ; { INT (*comp_func)() ; /* current compare function */ BINTREEPTR ptr ; /* current node in the tree */ INT k ; /* test condition [-1,0,1] */ ptr = tree->root ; comp_func = tree->compare_func ; while( ptr != nilS && (k = comp_f( ptr->data, key )) ){ if( k > 0 ){ ptr = ptr->left ; } else { ptr = ptr->right ; } } return( ptr ) ; } /* end tree_search */ /* the global version */ VOIDPTR Yrbtree_search( tree, key ) YTREEPTR tree ; VOIDPTR key ; { INT (*comp_func)() ; /* current compare function */ BINTREEPTR ptr ; /* current node in the tree */ INT k ; ptr = tree->root ; comp_func = tree->compare_func ; while( ptr != nilS && (k = comp_f( ptr->data, key )) ){ if( k > 0 ){ ptr = ptr->left ; } else { ptr = ptr->right ; } } tree->searchPtr = ptr; /* save new current position */ if( ptr != nilS ){ return( ptr->data ) ; } return( NIL(VOIDPTR) ) ; } /* end Yrbtree_search */ VOIDPTR Yrbtree_search_closest( tree, key, func ) YTREEPTR tree ; VOIDPTR key ; INT func ; { INT (*comp_func)() ; /* current compare function */ BINTREEPTR ptr ; /* current node in the tree */ BINTREEPTR closest_ptr ; /* current closest match in the tree */ BINTREEPTR suc, pred ; /* successor and predecessor for closest_ptr */ INT dist1, dist2 ; /* distance using predecessor functions */ INT k ; ptr = tree->root ; comp_func = tree->compare_func ; closest_ptr = NIL(BINTREEPTR) ; while( ptr != nilS && (k = comp_f( ptr->data, key )) ){ closest_ptr = ptr ; /* save the closest match so far */ if( k > 0 ){ ptr = ptr->left ; } else { ptr = ptr->right ; } } if( ptr == nilS ){ /* in the case of no exact match return closest */ if( closest_ptr ){ switch( func ){ case SEARCH_CLOSEST_NOP: break ; case SEARCH_CLOSEST_BELOW: dist1 = comp_f( closest_ptr->data, key ) ; if( dist1 > 0 ){ pred = tree_pred( closest_ptr ) ; if( pred != nilS ){ /* take predecessor */ closest_ptr = pred ; } } break ; case SEARCH_CLOSEST_ABOVE: dist1 = comp_f( closest_ptr->data, key ) ; if( dist1 < 0 ){ suc = tree_suc( closest_ptr ) ; if( suc != nilS ){ /* take successor */ closest_ptr = suc ; } } break ; case SEARCH_CLOSEST: /* ---------------------------------------------------------- * See which one is closer - current pointer, predecessor * or sucessor. ---------------------------------------------------------- */ dist1 = comp_f( closest_ptr->data, key ) ; pred = tree_pred( closest_ptr ) ; if( pred != nilS ){ dist2 = comp_f( pred->data, key ) ; if( ABS(dist2) < ABS(dist1) ){ /* predecessor is closer */ closest_ptr = pred ; dist1 = dist2 ; } } suc = tree_suc( closest_ptr ) ; if( suc != nilS ){ dist2 = comp_f( suc->data, key ) ; if( ABS(dist2) < ABS(dist1) ){ /* take sucessor only if it is better */ closest_ptr = suc ; } } break ; } /* end switch( func )... */ ptr = closest_ptr ; } else { /* there is nothing in the tree */ return( NIL(VOIDPTR) ) ; } } tree->searchPtr = ptr; /* save new current position */ return( ptr->data ) ; } /* end Yrbtree_search_closest */ VOIDPTR Yrbtree_min( tree ) YTREEPTR tree ; { BINTREEPTR ptr ; /* current node in the tree */ if ( tree->root == nilS ) { return( NIL(VOIDPTR) ); } for( ptr = tree->root; ptr->left != nilS ; ptr = ptr->left ) ; tree->searchPtr = ptr; /* save new current position */ if( ptr != nilS ){ return( ptr->data ) ; } return( NIL(VOIDPTR) ) ; } /* end Yrbtree_min */ VOIDPTR Yrbtree_max( tree ) YTREEPTR tree ; { BINTREEPTR ptr ; /* current node in the tree */ if ( tree->root == nilS ) { return( NIL(VOIDPTR) ); } for( ptr = tree->root; ptr->right != nilS ; ptr = ptr->right ) ; tree->searchPtr = ptr; /* save new current position */ if( ptr != nilS ){ return( ptr->data ) ; } return( NIL(VOIDPTR) ) ; } /* end Yrbtree_min */ static BINTREEPTR tree_suc( ptr ) BINTREEPTR ptr ; { BINTREEPTR y ; /* a temporary pointer */ if( ptr == nilS ){ return( nilS ) ; } if( ptr->right != nilS ){ for( ptr = ptr->right; ptr->left != nilS ; ptr = ptr->left ) ; return( ptr ) ; } for( y = ptr->parent; y != nilS && ptr == y->right; y = y->parent ){ ptr = y ; } return( y ) ; } /* end tree_suc */ static BINTREEPTR tree_pred( ptr ) BINTREEPTR ptr ; { BINTREEPTR y ; /* a temporary pointer */ if( ptr == nilS ){ return( nilS ) ; } if( ptr->left != nilS ){ /* find the rightmost of the left pointer */ for( ptr = ptr->left; ptr->right != nilS ; ptr = ptr->right ) ; return( ptr ) ; } /* otherwise we have to back up to the parent */ for( y = ptr->parent; y != nilS && ptr == y->left; y = y->parent ){ ptr = y ; } return( y ) ; } /* end tree_pred */ VOIDPTR Yrbtree_suc( tree, data ) YTREEPTR tree ; VOIDPTR data ; { BINTREEPTR ptr ; /* a temporary pointer */ BINTREEPTR suc ; /* a temporary pointer */ ptr = tree_search( tree, data ) ; suc = tree_suc( ptr ) ; if( suc != nilS ){ return( suc->data ) ; } return( NIL(VOIDPTR) ) ; } /* end Yrbtree_suc */ VOIDPTR Yrbtree_search_suc( tree ) YTREEPTR tree ; { BINTREEPTR ptr ; /* current node in the tree */ /* find successor to current position in tree set by Yrbtree_search */ ptr = tree->searchPtr; /* get old current position */ ptr = tree_suc( ptr ) ; tree->searchPtr = ptr; /* save new current position */ if( ptr != nilS ){ return( ptr->data ) ; } return( NIL(VOIDPTR) ) ; } /* end Yrbtree_search_suc */ VOIDPTR Yrbtree_search_pred( tree ) YTREEPTR tree ; { BINTREEPTR ptr ; /* current node in the tree */ /* Find predecessor to current position in tree set by Yrbtree_search or Yrbtree_interval */ ptr = tree->searchPtr; /* get old current position */ ptr = tree_pred( ptr ) ; tree->searchPtr = ptr; /* save new current position */ if( ptr != nilS ){ return( ptr->data ) ; } return( NIL(VOIDPTR) ) ; } /* end Yrbtree_search_pred */ static left_rotate( tree, x ) YTREEPTR tree ; BINTREEPTR x ; { BINTREEPTR y ; /* a temporary pointer */ y = x->right ; /* set y */ x->right = y->left ; /* Turn y's left subtreee in x's right */ if( y->left != nilS ){ y->left->parent = x ; } y->parent = x->parent ; /* link x's parent to y */ if( x->parent == nilS ){ tree->root = y ; } else if( x == x->parent->left ){ x->parent->left = y ; } else { x->parent->right = y ; } y->left = x ; /* put x on y's left */ x->parent = y ; } /* left_rotate */ static right_rotate( tree, x ) YTREEPTR tree ; BINTREEPTR x ; { BINTREEPTR y ; /* a temporary pointer */ y = x->left ; /* set y */ x->left = y->right ; /* Turn y's right subtreee in x's left */ if( y->right != nilS ){ y->right->parent = x ; } y->parent = x->parent ; /* link x's parent to y */ if( x->parent == nilS ){ tree->root = y ; } else if( x == x->parent->right ){ x->parent->right = y ; } else { x->parent->left = y ; } y->right = x ; /* put x on y's right */ x->parent = y ; } /* right_rotate */ /* ----------------------------------------------------------------- * Delete a node in the tree by using actual pointer. Also frees * user data if necessary. ----------------------------------------------------------------- */ static tree_delete( tree, z, userDelete ) YTREEPTR tree ; BINTREEPTR z ; VOID (*userDelete)(); { BINTREEPTR w ; /* a temporary pointer */ BINTREEPTR x ; /* a temporary pointer */ BINTREEPTR y ; /* a temporary pointer */ /* we must delete the user data first so to avoid copy problem later */ if (userDelete) { (*userDelete)( z->data ) ; } /* now begin deletion process */ /* determine which node to splice out */ if( z->left == nilS || z->right == nilS ){ y = z ; } else { y = tree_suc( z ) ; } /* let x be the non-nil child of y or nil if y has no children */ if( y->left != nilS ){ x = y->left ; } else { x = y->right ; } /* splice out y */ x->parent = y->parent ; if( y->parent == nilS ){ /* y is the root - x becomes new root */ tree->root = x ; } else if( y == y->parent->left ){ y->parent->left = x ; } else { y->parent->right = x ; } /* if the successor of z was spliced out copy content */ if( y != z ){ z->data = y->data ; } /* now take care of the red black attributes */ if( y->color == BLACK ){ while( x != tree->root && x->color == BLACK ){ if( x == x->parent->left ){ w = x->parent->right ; if( w->color == RED ){ w->color = BLACK ; x->parent->color = RED ; left_rotate( tree, x->parent ) ; w = x->parent->right ; } if( w->left->color == BLACK && w->right->color == BLACK ){ w->color = RED ; x = x->parent ; } else { if( w->right->color == BLACK ){ w->left->color = BLACK ; w->color = RED ; right_rotate( tree, w ) ; w = x->parent->right ; } w->color = x->parent->color ; x->parent->color = BLACK ; w->right->color = BLACK ; left_rotate( tree, x->parent ) ; x = tree->root ; } } else { /* right side case */ w = x->parent->left ; if( w->color == RED ){ w->color = BLACK ; x->parent->color = RED ; right_rotate( tree, x->parent ) ; w = x->parent->left ; } if( w->right->color == BLACK && w->left->color == BLACK ){ w->color = RED ; x = x->parent ; } else { if( w->left->color == BLACK ){ w->right->color = BLACK ; w->color = RED ; left_rotate( tree, w ) ; w = x->parent->left ; } w->color = x->parent->color ; x->parent->color = BLACK ; w->left->color = BLACK ; right_rotate( tree, x->parent ) ; x = tree->root ; } } /* end right side case */ } /* end while loop */ x->color = BLACK ; } /* end test on y's color */ /* now safe to free y */ YFREE(y); tree->size --; } /* end tree_delete */ VOID Yrbtree_insert( tree, data ) YTREEPTR tree ; VOIDPTR data ; { BINTREEPTR x ; /* a temporary pointer */ BINTREEPTR y ; /* a temporary pointer */ BINTREEPTR z ; /* a temporary pointer */ BINTREEPTR nil ; /* a temporary pointer */ BINTREEPTR ptr ; /* a temporary pointer */ INT (*comp_func)() ; /* current compare function */ if(!(data)){ M( ERRMSG, "Yrbtree_insert","No data given\n" ) ; return ; } /* first perform an normal insertion into the binary tree */ comp_func = tree->compare_func ; y = nilS ; x = YMALLOC( 1, BINTREE ) ; x->data = data ; x->left = nilS ; x->right = nilS ; /* find the place where we want to deposit the data */ for( ptr = tree->root; ptr != nilS ; ){ y = ptr ; /* save the place for the insert */ if( comp_f( data, ptr->data ) < 0 ){ ptr = ptr->left ; } else { ptr = ptr->right ; } } /* now set the parent field of x */ x->parent = y ; if( y == nilS ){ tree->root = x ; } else if( comp_f( data, y->data ) < 0 ){ y->left = x ; } else { y->right = x ; } /* now fix up the tree so it is a red black tree */ x->color = RED ; while( x != tree->root && x->parent->color == RED ){ if( x->parent == x->parent->parent->left ){ y = x->parent->parent->right ; if( y->color == RED ){ x->parent->color = BLACK ; y->color = BLACK ; x->parent->parent->color = RED ; x = x->parent->parent ; } else { if( x == x->parent->right ){ x = x->parent ; left_rotate( tree, x ) ; } x->parent->color = BLACK ; x->parent->parent->color = RED ; right_rotate( tree, x->parent->parent ) ; } } else { y = x->parent->parent->left ; if( y->color == RED ){ x->parent->color = BLACK ; y->color = BLACK ; x->parent->parent->color = RED ; x = x->parent->parent ; } else { if( x == x->parent->left ){ x = x->parent ; right_rotate( tree, x ) ; } x->parent->color = BLACK ; x->parent->parent->color = RED ; left_rotate( tree, x->parent->parent ) ; } } } tree->root->color = BLACK ; tree->size ++; } /* Yrbtree_insert */ /* enumerate all the data. First time call with startFlag=TRUE */ /* next times call with startFlag=FALSE. */ VOIDPTR Yrbtree_enumerate( tree, startFlag ) YTREEPTR tree ; BOOL startFlag; { BINTREEPTR ptr ; /* remember where we are */ if( startFlag ){ for( ptr = tree->root; ptr != nilS && ptr->left != nilS; ptr = ptr->left ) ; } else { /* find successor to current ptr */ ptr = tree->enumeratePtr; /* get old current position */ /* find successor to current ptr */ if( ptr == recalcS ){ /* calculate from the beginning */ return( Yrbtree_enumerate( tree, TRUE )) ; } else { ptr = tree_suc( ptr ) ; } } tree->enumeratePtr = ptr; /* save new current position */ if( ptr != nilS ){ return( ptr->data ) ; } return( NIL(VOIDPTR) ) ; } /* end Yrbtree_enumerate */ /* inverse of enumerate. Start at max of tree and work backwords */ /* next times call with startFlag=FALSE. */ VOIDPTR Yrbtree_revlist( tree, startFlag ) YTREEPTR tree ; BOOL startFlag; { BINTREEPTR ptr ; /* remember where we are */ if( startFlag ){ /* find the maximum in the tree */ for( ptr = tree->root;ptr != nilS && ptr->right != nilS; ptr = ptr->right ) ; } else { ptr = tree->enumeratePtr; /* get old current position */ /* find successor to current ptr */ if( ptr == recalcS ){ /* calculate from the beginning */ return( Yrbtree_revlist( tree, TRUE )) ; } else { ptr = tree_pred( ptr ) ; } } tree->enumeratePtr = ptr; /* save new current position */ if( ptr != nilS ){ return( ptr->data ) ; } return( NIL(VOIDPTR) ) ; } /* end Yrbtree_revlist */ /* Push the current enumeration pointer. This is useful */ /* for recursive enumeration */ VOID Yrbtree_enumeratePush ( tree ) YTREEPTR tree; { if (!(tree->enumerateDeck)) { tree->enumerateDeck = Ydeck_init(); } Ydeck_push( tree->enumerateDeck,tree->enumeratePtr); } /* pops the current enumeration pointer. This is useful */ /* for recursive enumeration */ VOID Yrbtree_enumeratePop ( tree ) YTREEPTR tree; { if (!(tree->enumerateDeck)) { M(ERRMSG,"Yrbtree_enumeratePop","There has been no push\n"); } if ( Ydeck_size(tree->enumerateDeck) <= 0 ) { M(ERRMSG,"Yrbtree_enumeratePop","Imbalance of push/pop\n"); } tree->enumeratePtr = (BINTREEPTR) Ydeck_pop(tree->enumerateDeck); } /* end Yrbtree_enumeratePop() */ /* delete a node in the tree by using the key */ BOOL Yrbtree_delete( tree, key, userDelete ) YTREEPTR tree ; VOIDPTR key ; VOID (*userDelete)(); { BINTREEPTR z ; /* a temporary pointer */ z = tree_search( tree, key ) ; if( z == nilS ){ /* didn't find data in the tree */ return( FALSE ) ; } tree_delete( tree, z, userDelete ) ; return( TRUE ) ; } /* end Yrbtree_delete() */ BOOL Yrbtree_deleteCurrentInterval( tree, userDelete ) YTREEPTR tree ; VOID (*userDelete)(); { BINTREEPTR z ; /* a temporary pointer */ BINTREEPTR w ; /* a temporary pointer */ if( (z = tree->intervalPtr) && z != nilS ){ /* ----------------------------------------------------------------- * Perform operations to insure that interval enumerate works * after delete. Lucky since predecessor does not get mangled * in a tree delete operation. ----------------------------------------------------------------- */ w = tree_pred( z ) ; if( w != nilS ){ tree->intervalPtr = w ; /* ok to use predecessor */ } else { /* this is the case where we delete min in tree */ /* need to recalculate */ tree->intervalPtr = recalcS ; } /* ----------------------------------------------------------------- * Now we can delete the rbtree pointer. ----------------------------------------------------------------- */ tree_delete( tree, z, userDelete ) ; return( TRUE ) ; } else { return( FALSE ) ; } } /* end Yrbtree_deleteCurrentInterval() */ BOOL Yrbtree_deleteCurrentEnumerate( tree, userDelete ) YTREEPTR tree ; VOID (*userDelete)(); { BINTREEPTR z ; /* a temporary pointer */ BINTREEPTR w ; /* a temporary pointer */ if( (z = tree->enumeratePtr) && z != nilS ){ /* ----------------------------------------------------------------- * Perform operations to insure that interval enumerate works * after delete. Lucky since predecessor does not get mangled * in a tree delete operation. ----------------------------------------------------------------- */ w = tree_pred( z ) ; if( w != nilS ){ tree->enumeratePtr = w ; /* ok to use predecessor */ } else { /* this is the case where we delete min in tree */ /* need to recalculate */ tree->enumeratePtr = recalcS ; } /* ----------------------------------------------------------------- * Now we can delete the rbtree pointer. ----------------------------------------------------------------- */ tree_delete( tree, z, userDelete ) ; return( TRUE ) ; } else { return( FALSE ) ; } } /* end Yrbtree_deleteCurrentEnumerate() */ static tree_dump( tree, ptr, print_key, printTab ) YTREEPTR tree ; BINTREEPTR ptr ; VOID (*print_key)() ; INT printTab ; { INT i ; if( ptr != nilS ){ printTab+=4; tree_dump( tree, ptr->right, print_key, printTab ) ; /* print level */ fprintf( stderr, " " ) ; for( i = 1; i < printTab; i++ ){ fprintf( stderr, " " ) ; } (*print_key)( ptr->data ) ; if( ptr->color == BLACK ){ fprintf( stderr, ":black\n" ) ; } else { fprintf( stderr, ":red\n" ) ; } tree_dump( tree, ptr->left, print_key, printTab ) ; } } /* end Ytree_dump */ VOID Yrbtree_dump( tree, print_key ) YTREEPTR tree ; VOID (*print_key)() ; { if( tree ){ Yrbtree_verify(tree); tree_dump( tree, tree->root, print_key, 1 ) ; } } /* end Ytree_dump */ VOIDPTR Yrbtree_interval( tree, low_key, high_key, startFlag ) YTREEPTR tree ; VOIDPTR low_key, high_key ; BOOL startFlag; { BINTREEPTR ptr ; /* remember where we are */ static INT (*comp_func)() ; /* current compare function */ BINTREEPTR y ; /* remember where we are */ comp_func = tree->compare_func ; if( startFlag ){ /* find where we would put low_key if we were to put */ /* it in the tree */ y = nilS ; for( ptr = tree->root; ptr != nilS; ){ y = ptr ; /* save the place for the proposed insert */ if( comp_f( low_key, ptr->data ) <= 0 ){ ptr = ptr->left ; } else { ptr = ptr->right ; } } /* now see if we need to find successor */ if( y != nilS ){ ptr = y ; if( comp_f( low_key, ptr->data ) > 0 ){ /* find successor to current ptr */ ptr = tree_suc( ptr ) ; } } } else { /* find successor to current ptr */ ptr = tree->intervalPtr; /* get old current pointer */ if( ptr == recalcS ){ /* calculate from the beginning */ return( Yrbtree_interval( tree, low_key, high_key, TRUE )) ; } else { ptr = tree_suc( ptr ) ; } } /* is pointer in interval? */ if( ptr != nilS && comp_f( ptr->data, high_key ) > 0 ){ ptr = nilS ; } tree->intervalPtr = ptr; /* save new current position */ if( ptr != nilS ){ return( ptr->data ) ; } return( NIL(VOIDPTR) ) ; } /* end Ytree_interval */ INT Yrbtree_interval_size( tree, low_key, high_key ) YTREEPTR tree ; VOIDPTR low_key, high_key ; { static INT (*comp_func)() ; /* current compare function */ INT size ; /* number of element in interval */ BINTREEPTR ptr ; /* remember where we are */ BINTREEPTR y ; /* remember where we are */ comp_func = tree->compare_func ; size = 0 ; /* ----------------------------------------------------------------- * Find where we would put low_key if we were to put it in the tree. ----------------------------------------------------------------- */ for( y = nilS, ptr = tree->root; ptr != nilS; ){ y = ptr ; /* save the place for the proposed insert */ if( comp_f( low_key, ptr->data ) <= 0 ){ ptr = ptr->left ; } else { ptr = ptr->right ; } } /* now see if we need to find successor */ if( y != nilS ){ ptr = y ; if( comp_f( low_key, ptr->data ) > 0 ){ /* find successor to current ptr */ ptr = tree_suc( ptr ) ; } } /* is pointer in interval? */ if( ptr != nilS && comp_f( ptr->data, high_key ) > 0 ){ ptr = nilS ; } while( ptr && ptr != nilS ){ size++ ; ptr = tree_suc( ptr ) ; /* is pointer in interval? */ if( ptr != nilS && comp_f( ptr->data, high_key ) > 0 ){ ptr = nilS ; } } return( size ) ; } /* end Ytree_interval_size() */ /* Push the current interval pointer. This is useful */ /* for recursive intervals */ VOID Yrbtree_intervalPush ( tree ) YTREEPTR tree; { if (!(tree->intervalDeck)) { tree->intervalDeck = Ydeck_init(); } Ydeck_push(tree->intervalDeck,tree->intervalPtr); } /* Pop the current interval pointer. This is useful */ /* for recursive intervals */ VOID Yrbtree_intervalPop ( tree ) YTREEPTR tree; { if (!(tree->intervalDeck)) { M(ERRMSG,"Yrbtree_intervalPop","There has been no push\n"); } if ( Ydeck_size(tree->intervalDeck) <= 0 ) { M(ERRMSG,"Yrbtree_intervalPop","Imbalance of push/pop\n"); } tree->intervalPtr = (BINTREEPTR) Ydeck_pop(tree->intervalDeck); } /* end Yrbtree_intervalPop() */ VOID Yrbtree_interval_free( tree, low_key, high_key, userDelete ) YTREEPTR tree ; VOIDPTR low_key, high_key ; VOID (*userDelete)(); { VOIDPTR data ; for (data = Yrbtree_interval( tree, low_key, high_key, TRUE); data; data = Yrbtree_interval( tree, low_key, high_key, FALSE) ) { Yrbtree_deleteCurrentInterval( tree, userDelete ) ; } } /* end Yrbtree_interval_free() */ static tree_free( ptr ) BINTREEPTR ptr ; { if( ptr->left != nilS ){ tree_free( ptr->left ) ; } if( ptr->right != nilS ){ tree_free( ptr->right ) ; } if( ptr != nilS ){ YFREE( ptr ) ; } } /* end tree_free */ static free_tree_and_data( ptr, userDelete ) BINTREEPTR ptr ; VOID (*userDelete)(); { if( ptr->left != nilS ){ free_tree_and_data( ptr->left,userDelete ) ; } if( ptr->right != nilS ){ free_tree_and_data( ptr->right,userDelete ) ; } if( ptr != nilS ){ (*userDelete)( ptr->data ); /* free tree nodes and data */ YFREE( ptr ) ; } } /* end tree_free */ VOID Yrbtree_free( tree, userDelete ) YTREEPTR tree ; VOID (*userDelete)(); { if( tree ){ Yrbtree_empty( tree,userDelete ) ; YFREE( tree ); } } /* end Yrbtree_free */ VOID Yrbtree_empty( tree, userDelete ) YTREEPTR tree ; VOID (*userDelete)(); { if( tree ){ if (tree->root != nilS) { /* does tree need to be emptied? */ if (userDelete) { free_tree_and_data(tree->root,userDelete); /* free tree and data */ } else { tree_free(tree->root); /* free tree nodes only */ } tree->root = nilS ; /* tree is now empty */ } /* end if tree->root */ } /* end if tree */ tree->size = 0; /* free decks associated with tree if they exist */ if( tree->enumerateDeck ){ Ydeck_free( tree->enumerateDeck, NULL ) ; tree->enumerateDeck = NIL(YDECKPTR) ; } if( tree->intervalDeck ){ Ydeck_free( tree->intervalDeck, NULL ) ; tree->intervalDeck = NIL(YDECKPTR) ; } } /* end Yrbtree_empty() */ INT Yrbtree_size( tree ) YTREEPTR tree ; { INT size; if( tree ){ if ( tree->size >= 0 ) { return( tree->size ) ; } M(ERRMSG,"Yrbtree_size","Bogus rbTree size\n"); } else { M(ERRMSG,"Yrbtree_size","NULL rbTree pointer\n"); } return (-1); } /* end Yrbtree_size */ INT (*Yrbtree_get_compare( tree ))() YTREEPTR tree; { return ( tree->compare_func ); } INT Yrbtree_verify(tree) YTREEPTR tree ; { INT count; INT rc; BINTREEPTR ptr; /* exercise tree pointers */ rc = TRUE; count = 0; if ( YcheckDebug(tree) < sizeof(YTREEBOX) ) { M(ERRMSG,"Yrbtree_verify","tree memory is corrupt\n"); rc = FALSE; } /* get first item in tree */ for( ptr = tree->root; ptr != nilS && ptr->left != nilS; ptr = ptr->left ) ; /* walk tree */ for ( ; ptr != nilS; ptr = tree_suc( ptr ) ) { if ( YcheckDebug(ptr) < sizeof(BINTREE) ) { M(ERRMSG,"Yrbtree_verify","tree node memory is corrupt\n"); rc = FALSE; } count ++; } /* if tree is corrupt, we may still get out of loop */ /* check the size field */ if ( count != Yrbtree_size(tree) ) { M(ERRMSG,"Yrbtree_verify","Bogus rbTree. Data structure is corrupt\n"); rc = FALSE; } return ( rc ); } VOID Yrbtree_resort( tree, compare_func ) YTREEPTR tree ; INT (*compare_func)() ; /* user specifies key function */ { BINTREEPTR ptr ; /* remember where we are */ YTREEPTR new_tree ; /* the new tree being built */ new_tree = Yrbtree_init( compare_func ) ; /* first find the leftmost pointer */ for( ptr=tree->root;ptr!=nilS && ptr->left != nilS; ptr=ptr->left ) ; /* now enumerate all the members of the tree in order */ for( ; ptr && ptr != nilS ; ptr = tree_suc( ptr ) ) { if( ptr != nilS ){ /* build new tree */ Yrbtree_insert( new_tree, ptr->data ) ; } } /* free the data in the old tree */ Yrbtree_empty( tree, NULL ) ; /* now copy over tree data */ tree->root = new_tree->root ; tree->size = new_tree->size ; tree->intervalPtr = NIL(BINTREEPTR) ; tree->enumeratePtr = NIL(BINTREEPTR) ; tree->searchPtr = NIL(BINTREEPTR) ; tree->compare_func = compare_func ; /* now free new tree */ YFREE( new_tree ) ; } /* end Yrbtree_resort */ YTREEPTR Yrbtree_copy( tree, compare_func ) YTREEPTR tree ; INT (*compare_func)() ; /* user specifies key function */ { BINTREEPTR ptr ; /* remember where we are */ YTREEPTR new_tree ; /* the new tree being built */ new_tree = Yrbtree_init( compare_func ) ; /* first find the leftmost pointer */ for( ptr=tree->root;ptr!=nilS && ptr->left != nilS; ptr=ptr->left ) ; /* now enumerate all the members of the tree in order */ for( ; ptr && ptr != nilS ; ptr = tree_suc( ptr ) ) { if( ptr != nilS ){ /* build new tree */ Yrbtree_insert( new_tree, ptr->data ) ; } } return( new_tree ) ; } /* end Yrbtree_resort */ #ifdef TEST /* ################################################################## TEST OF TREE ROUTINES ################################################################## */ typedef struct { INT str_len ; char *name ; } DATA, *DATAPTR ; static compare_string( key1, key2 ) DATAPTR key1, key2 ; { return( strcmp( key1->name, key2->name ) ) ; } /* end compare */ static compare_len( key1, key2 ) DATAPTR key1, key2 ; { return( key1->str_len - key2->str_len ) ; } /* end compare_len */ static VOID print_data( data ) DATAPTR data ; { fprintf( stderr, "%s:%d ", data->name, data->str_len ) ; } /* end print_data() */ static VOID free_data( data ) DATAPTR data ; { YFREE( data->name ) ; YFREE( data ) ; } /* end print_data() */ static char *make_data( string ) char *string ; { DATAPTR data ; data = YMALLOC( 1, DATA ) ; data->str_len = strlen(string) + 1 ; data->name = YMALLOC( data->str_len, char ) ; strcpy( data->name, string ) ; return( (char *) data ) ; } /* end make_data */ main() { YTREEPTR tree1 ; DATAPTR data ; static char buffer1[LRECL] ; static char buffer2[LRECL] ; INT count ; DATA key1, key2 ; key1.name = buffer1 ; key2.name = buffer2 ; fprintf( stderr, "Initial memory:%d\n", YgetCurMemUse() ) ; tree1 = Yrbtree_init( compare_string ) ; Yrbtree_insert( tree1, make_data("the" ) ) ; Yrbtree_insert( tree1, make_data("silver" ) ) ; Yrbtree_insert( tree1, make_data("fox" ) ) ; Yrbtree_insert( tree1, make_data("jumped" ) ) ; Yrbtree_insert( tree1, make_data("over" ) ) ; Yrbtree_insert( tree1, make_data("the" ) ) ; Yrbtree_insert( tree1, make_data("moon" ) ) ; Yrbtree_verify(tree1) ; fprintf( stderr, "Output the initial tree\n" ) ; for( data=(DATAPTR)Yrbtree_enumerate(tree1,TRUE); data; data=(DATAPTR)Yrbtree_enumerate(tree1,FALSE)){ fprintf( stderr, "key:%s\n", data->name ) ; } fprintf( stderr, "\nLook for jumped...\n" ) ; strcpy( key1.name, "jumped" ) ; data = (DATAPTR) Yrbtree_search( tree1, &key1 ) ; Yrbtree_verify(tree1) ; if( data ){ fprintf( stderr, "key:%s\n", data->name ) ; } Yrbtree_dump( tree1, print_data ) ; fprintf( stderr, "\nDelete jumped...\n" ) ; strcpy( key2.name, "jumped" ) ; Yrbtree_delete( tree1, &key2, free_data ) ; Yrbtree_verify(tree1) ; Yrbtree_dump( tree1, print_data ) ; for( data=(DATAPTR)Yrbtree_enumerate(tree1,TRUE); data; data=(DATAPTR)Yrbtree_enumerate(tree1,FALSE)){ fprintf( stderr, "key:%s\n", data->name ) ; } fprintf( stderr, "\nInsert takeover and try to delete history...\n" ); Yrbtree_insert( tree1, make_data("takeover" ) ) ; strcpy( key1.name, "history" ) ; if( Yrbtree_delete( tree1, &key1, free_data ) ){ fprintf( stderr, "found history\n" ) ; } else { fprintf( stderr, "didn't find history\n" ) ; } strcpy( key1.name, "fox" ) ; Yrbtree_delete( tree1, &key1, free_data ) ; fprintf( stderr, "\nNow show result...\n" ); for( data=Yrbtree_enumerate(tree1,TRUE); data; data=Yrbtree_enumerate(tree1,FALSE)){ fprintf( stderr, "key:%s\n", data->name ) ; } fprintf( stderr, "\nNow find interval 'over' to 'the'\n" ); strcpy( key1.name, "over" ) ; strcpy( key2.name, "the" ) ; for( data=Yrbtree_interval(tree1,&key1,&key2,TRUE); data; data=Yrbtree_interval(tree1,&key1,&key2,FALSE)){ fprintf( stderr, "key:%s\n", data->name ) ; } fprintf( stderr, "The interval size is:%d\n", Yrbtree_interval_size( tree1, &key1, &key2 ) ) ; fprintf( stderr, "\nInsert zoo and delete the two the's...\n" ); Yrbtree_insert( tree1, make_data("zoo" ) ) ; strcpy( key1.name, "the" ) ; strcpy( key2.name, "the" ) ; for( data=Yrbtree_interval(tree1,&key1,&key2,TRUE); data; data=Yrbtree_interval(tree1,&key1,&key2,FALSE)){ fprintf( stderr, "key:%s\n", data->name ) ; Yrbtree_deleteCurrentInterval( tree1, free_data ) ; } fprintf( stderr, "\nNow dump the tree\n" ); Yrbtree_dump( tree1, print_data ) ; fprintf( stderr, "\nInsert two airplanes and then delete...\n" ); Yrbtree_insert( tree1, make_data("airplane" ) ) ; Yrbtree_insert( tree1, make_data("airplane" ) ) ; fprintf( stderr, "\nLook for airplanes\n" ); Yrbtree_dump( tree1, print_data ) ; /* now delete them */ strcpy( key1.name, "airplane" ) ; strcpy( key2.name, "airplane" ) ; for( data=Yrbtree_interval(tree1,&key1,&key2,TRUE); data; data=Yrbtree_interval(tree1,&key1,&key2,FALSE)){ fprintf( stderr, "key:%s\n", data->name ) ; Yrbtree_deleteCurrentInterval( tree1, free_data ) ; } Yrbtree_dump( tree1, print_data ) ; fprintf( stderr, "The interval size is:%d\n", Yrbtree_interval_size( tree1, &key1, &key2 ) ) ; fprintf( stderr, "\nDelete third sorted element in the tree\n" ); for( count = 0, data=Yrbtree_enumerate(tree1,TRUE); data; data=Yrbtree_enumerate(tree1,FALSE)){ if( ++count == 3 ){ Yrbtree_deleteCurrentEnumerate( tree1, free_data ) ; } } Yrbtree_dump( tree1, print_data ) ; fprintf( stderr, "\nUse a new comparison function sort by length\n" ); Yrbtree_resort( tree1, compare_len ) ; fprintf( stderr, "\nAgain dump the tree\n" ); Yrbtree_dump( tree1, print_data ) ; fprintf( stderr, "\nNow free tree\n" ); Yrbtree_free( tree1, free_data ) ; fprintf( stderr, "Final memory:%d\n", YgetCurMemUse() ) ; exit(0) ; } #endif /* TEST */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/relpath.c000066400000000000000000000100701305746555600212530ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: relpath.c DESCRIPTION:Calculate the path of a file relative to a given known file. You can access any file in that directory and below. CONTENTS: char *Yrelpath( known_path, rel_path ) char *known_path, *rel_path ; DATE: Apr 18, 1989 REVISIONS: May 8, 1989 - updated to handle ../../ constructs. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) relpath.c version 3.2 8/28/90" ; #endif #include #include #include char *Yrelpath( known_path, rel_path ) char *known_path, *rel_path ; /* known path and relative path to it */ { char known_fpath[LRECL] ; /* full path of known obj */ char *ptr ; /* used to replace obj with relative path */ char *result ; /* resulting path */ char *Yfixpath(), *strrchr(), *strcat() ; INT up ; /* keeps count of backtracking up dir tree */ /* make a copy of path */ strcpy( known_fpath, known_path ) ; /* look for ./ constructs */ up = 0 ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - First look for ./ or directory local files. That is if known path is :/twolf6/bills/tw/pgms/test and rel_path :./src result should be:/twolf6/bills/tw/pgms/test/src - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - */ if( strncmp( rel_path,"./", 2 ) == STRINGEQ ){ /* back up the directory tree */ /* update rel_path by skipping over ./ */ rel_path += 2 ; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Next look for ../ or higher directory files. That is if known path is :/twolf6/bills/tw/pgms/test and rel_path :../src result should be:/twolf6/bills/tw/pgms/src - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* now look for multiple ../../ skip over leading . */ while( strncmp( rel_path,"../", 3 ) == STRINGEQ ){ up++ ; /* back up the directory tree */ /* update rel_path by skipping over ../ */ rel_path += 3 ; } /* now find matching slashes in known path */ /* find last backslash */ for( ; up > 0 ; up-- ){ if( ptr = strrchr( known_fpath, '/' )){ *ptr = EOS ; } else { return( NULL ) ; /* problem */ } } if( known_fpath ){ strcat( known_fpath, "/" ) ; strcat( known_fpath, rel_path ) ; result = (char *) Ystrclone(known_fpath); return( result ) ; } return( NULL ) ; } /* end Yrelpath */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/set.c000066400000000000000000000172401305746555600204150ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: set.c DESCRIPTION:This file contains the set utility routines. The set members of the set are integers in a range [lowerLimit..upperLimit]. The routines add & subtract members from the set efficiently. Multiple sets may be handled simultaneously. The complexity of the routines are as follows. Yset_init : O(n) Yset_free : O(n) Yset_member : O(1) Yset_add : O(1) Yset_enumerate : O(1) Yset_empty : O(1) Yset_size : O(1) Yset_comp : O(n) The Yset_empty gets its speed by incrementing the value of in_set. Since all tests for membership check a match of this value, all members of set can be deleted at once. NOTE: These set routines are best suited for applications where you need to enumerate the members of the set and the set is bounded by an integer. In other applications, they may not be as suitable. CONTENTS: DATE: Apr 10, 1989 - original coding. REVISIONS: Dec 4, 1989 added YsetSize and made Yenumerate a macro. Apr 18, 1990 - now Yset_init allocates the memory for a set. Apr 19, 1990 - added YcompSet May 8, 1990 - fixed error messages. Fri Feb 15 15:36:27 EST 1991 - renamed the set functions. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) set.c version 3.8 12/15/91" ; #endif #include #include #include #include /* initialize set */ YSETPTR Yset_init( lowerLimit, upperLimit ) INT lowerLimit, upperLimit ; { INT i ; INT sizeSet ; YSETPTR set ; set = YMALLOC( 1, YSET ) ; ASSERTNRETURN( set, "Yset_init", "Ran out of memory\n" ) ; /* make sure set limits are correct */ if( lowerLimit > upperLimit ){ M( ERRMSG, "Yset_init", "Set limits are in error\n" ) ; return ; } sizeSet = upperLimit - lowerLimit + 1 ; set->set = YMALLOC( sizeSet, YSETLISTPTR ) ; for( i=0;iset[i] = YCALLOC( 1, YSETLISTBOX ); } /* subtract off lower limit to make all */ /* accesses of array easier */ set->set -= lowerLimit ; set->lowerLimit = lowerLimit ; set->upperLimit = upperLimit ; set->size = sizeSet ; set->in_set = 1 ; set->cardinality = 0 ; set->list = NULL ; return( set ) ; } /* end Yset_init */ Yset_free( set ) YSETPTR set ; { INT i ; INT sizeSet ; /* add back offset to free array */ set->set += set->lowerLimit ; sizeSet = set->size ; for( i=0;iset[i] ) ; } YFREE( set->set ) ; YFREE( set ) ; } /* end Yset_free */ /* test whether a node is member of a set */ BOOL Yset_member( set, node ) YSETPTR set ; INT node ; { if( node >= set->lowerLimit && node <= set->upperLimit ){ if( set->set[node]->member == set->in_set ){ return( TRUE ) ; } else { return( FALSE ) ; } } else { M( ERRMSG, "MEMBER", "value of node is out of bounds of set\n" ) ; return( FALSE ) ; } } /* end Yset_member */ /* add a node to the set */ /* returns TRUE if this a new member of set FALSE if already a member */ BOOL Yset_add( set, node ) YSETPTR set ; INT node ; { YSETLISTPTR temp ; if( node >= set->lowerLimit && node <= set->upperLimit ){ if( set->set[node]->member == set->in_set ){ return( FALSE ) ; } set->set[node]->member = set->in_set ; set->cardinality++ ; /* connect the doubly linked list */ if( temp = set->list ){ /* hook to old list */ set->list = set->set[node] ; set->list->next = temp ; /* fix back link of temp */ temp->prev = set->list ; } else { set->list = set->set[node] ; /* terminate new list */ set->list->next = NULL ; } set->list->node = node ; /* store data */ set->list->prev = NULL ; /* terminate backward list */ } else { M( ERRMSG, "ADD2SET", "value of node is out of bounds of set\n") ; return( FALSE ) ; } return( TRUE ) ; } /* end Yset_add */ /* delete a node from the set */ Yset_delete( set, node ) YSETPTR set ; INT node ; { YSETLISTPTR delptr ; ASSERTNRETURN( node >= set->lowerLimit && node <= set->upperLimit, "Yset_delete", "node out of range\n") ; delptr = set->set[node] ; ASSERTNRETURN( delptr->member == set->in_set, "Yset_delete", "node has already been deleted\n" ) ; if( delptr->next ){ if( delptr->prev ){ /* node to remove is in middle */ delptr->prev->next = delptr->next ; delptr->next->prev = delptr->prev ; } else { /* node to remove is first in the list */ set->list = delptr->next ; delptr->next->prev = SETNULL ; } } else { /* node is at end of list */ if( delptr->prev ){ /* node is at end and more than one member exists */ delptr->prev->next = SETNULL ; } else { /* saveNode is only member in the list */ set->list = SETNULL ; } } /* now update boolean flag */ delptr->member = FALSE ; /* update count */ if( -- (set->cardinality) < 0 ){ set->cardinality = 0 ; } } /* end Yset_delete */ /* To clear set we only need to update in_set number and to null list */ Yset_empty( set ) YSETPTR set ; { set->in_set++ ; set->list = NULL ; set->cardinality = 0 ; } /* end Yset_empty */ /* Set complementation */ Yset_comp( set ) YSETPTR set ; { INT i ; /* counter */ INT lower ; /* lower bound on set */ INT upper ; /* upper bound on set */ INT member ; /* member match */ YSETLISTPTR *setarray ; /* set is an array of YLISTBOXes */ lower = set->lowerLimit ; upper = set->upperLimit ; member = set->in_set ; setarray = set->set ; for( i = lower ; i <= upper; i++ ){ /* perform complementation on the set */ if( setarray[i]->member == member ){ setarray[i]->member = 0 ; } else { setarray[i]->member = 1 ; } } /* now fix the linked list by emptying the set and adding to set */ set->in_set = 1 ; set->list = NULL ; set->cardinality = 0 ; for( i = lower ; i <= upper; i++ ){ if( setarray[i]->member ){ Yset_add( set, i ) ; } } } /* end Yset_comp */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/stat.c000066400000000000000000000153221305746555600205740ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: stat.c DESCRIPTION:utility routines to calculate min, max, mean, and variance. CONTENTS: DOUBLE Ystat_min( array, number_ele, size_ele ) char *array ; INT num_ele, INT size_ele ; DOUBLE Ystat_max( array, number_ele, size_ele ) char *array ; INT num_ele, INT size_ele ; DOUBLE Ystat_mean( array, number_ele, size_ele ) char *array ; INT num_ele, INT size_ele ; DOUBLE Ystat_var( array, number_ele, size_ele, mean ) char *array ; INT num_ele, INT size_ele ; DOUBLE mean ; DATE: Mar 7, 1989 REVISIONS: Sun Apr 21 21:21:58 EDT 1991 - renamed to Ystat_ ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) stat.c (Yale) version 3.3 4/21/91" ; #endif #include /* Given an array of number_elements of size_element, calculate min */ DOUBLE Ystat_min( array, number_elements, size_element ) char *array ; INT number_elements ; INT size_element ; { INT i ; DOUBLE min = DBL_MAX ; SHORT *sarray ; INT *iarray ; DOUBLE *darray ; switch( size_element ){ case 1: for( i=0;i max ){ max = (DOUBLE) array[i] ; } } break ; case 2: sarray = (SHORT *) array ; for( i=0;i max ){ max = (DOUBLE) sarray[i] ; } } break ; case 4: iarray = (INT *) array ; for( i=0;i max ){ max = (DOUBLE) iarray[i] ; } } break ; case 8: darray = (DOUBLE *) array ; for( i=0;i max ){ max = darray[i] ; } } break ; default: fprintf( stderr, "Unsupported element size:%d\n", size_element ) ; } return(max); } /* end Ystat_max */ /* Given an array of number_elements of size size_ele, calculate mean */ DOUBLE Ystat_mean( array, number_elements, size_element ) char *array ; INT number_elements ; INT size_element ; { INT i ; DOUBLE sum = 0.0 ; SHORT *sarray ; INT *iarray ; DOUBLE *darray ; switch( size_element ){ case 1: for( i=0;i 1 ){ var = (sum2 - number_elements * mean * mean)/(number_elements-1) ; return(ABS(var)); } else if( number_elements == 1 ){ return( 0.0 ) ; } else { fprintf( stderr, "ERROR:number of elements zero\n" ) ; return( 0.0 ) ; } } /* end Ystat_variance */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/stats.c000066400000000000000000000150361305746555600207610ustar00rootroot00000000000000/* * Copyright (C) 1990-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: stats.c DESCRIPTION:Get runtime statistics in UNIX. CONTENTS: Yprint_stats( fdat ) FILE fdat ; DOUBLE Ycpu_time() DATE: May 5, 1990 REVISIONS: Oct 4, 1990 - added elaspse time for the mips machine. Fri Jan 25 15:44:46 PST 1991 - added AVOID conditional compile for HPUX. Wed Feb 26 03:56:25 EST 1992 - added date for reference. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) stats.c version 3.8 2/26/92" ; #endif #include #ifdef VMS #define AVOID #endif #ifdef HPUX #define AVOID #endif #ifdef SYS5 #define AVOID #endif #ifndef AVOID #include #include #include #endif /* AVOID */ /* print out the statistics of the program to the given file */ void Yprint_stats( fout ) FILE *fout ; { #ifndef AVOID char hostname[256] ; char *timestring ; INT text ; INT data ; INT vm_used ; INT vm_limit ; INT vm_soft_limit ; INT elapsed_time ; DOUBLE user ; DOUBLE systemTime ; DOUBLE scale ; DOUBLE run_time ; char *YcurTime(); /* Forward declaration */ struct rusage rusage ; struct rlimit rlp ; caddr_t p ; caddr_t sbrk() ; /*********************************************************** * Get the hostname ***********************************************************/ gethostname(hostname, 256) ; hostname[255] = EOS ; /* just in case */ /*********************************************************** * Get the brk() value ***********************************************************/ p = sbrk(0) ; vm_used = ((INT) p) / 1024.0 + 0.5 ; /*********************************************************** * Get virtual memory limits ***********************************************************/ getrlimit(RLIMIT_DATA, &rlp) ; vm_limit = rlp.rlim_max / 1024.0 + 0.5 ; vm_soft_limit = rlp.rlim_cur / 1024.0 + 0.5 ; /*********************************************************** * get usage stats ***********************************************************/ getrusage(RUSAGE_SELF, &rusage) ; user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec / 1.0e6 ; systemTime = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec/1.0e6 ; scale = (user + systemTime) * 100.0 ; if (scale == 0.0) { scale = 0.001 ; } /* now get elapsed time */ Ytimer_elapsed( &elapsed_time ) ; /* time is in milliseconds */ run_time = ( (DOUBLE) elapsed_time) / 1000.0 ; fprintf(fout, "\n\n") ; fprintf(fout, "Runtime Statistics\n") ; fprintf(fout, "-------------------------\n") ; fprintf(fout, "Machine name: %s\n", hostname) ; // This tends to segfault. Don't know why (Tim, 10/14/08) // fprintf(fout, "Date : %s\n\n", YcurTime(0)) ; timestring = YcurTime(0); fprintf(fout, "Date : %s\n\n", timestring) ; fprintf(fout, "User time:%6.1f seconds\n", user) ; fprintf(fout, "System time:%6.1f seconds\n", systemTime) ; fprintf(fout, "Elapsed time:%6.1f seconds\n\n", run_time) ; text = rusage.ru_ixrss / scale + 0.5 ; data = (rusage.ru_idrss + rusage.ru_isrss) / scale + 0.5 ; fprintf(fout, "Average resident text size = %5dK\n", text) ; fprintf(fout, "Average resident data+stack size = %5dK\n", data) ; fprintf(fout, "Maximum resident size = %5dK\n", rusage.ru_maxrss/2) ; fprintf(fout, "Virtual memory size = %5dK\n", vm_used) ; fprintf(fout, "Virtual memory limit = %5dK (%dK)\n", vm_soft_limit, vm_limit) ; if( YgetMaxMemUse() ){ fprintf(fout, "Maximum heap size = %5d\n", YgetMaxMemUse() ) ; fprintf(fout, "Current heap size = %5d\n", YgetCurMemUse() ) ; } fprintf(fout, "\nMajor page faults = %d\n", rusage.ru_majflt) ; fprintf(fout, "Minor page faults = %d\n", rusage.ru_minflt) ; fprintf(fout, "Swaps = %d\n\n", rusage.ru_nswap) ; fprintf(fout, "Input blocks = %d\n", rusage.ru_inblock) ; fprintf(fout, "Output blocks = %d\n\n", rusage.ru_oublock) ; fprintf(fout, "Context switch (voluntary) = %d\n", rusage.ru_nvcsw) ; fprintf(fout, "Context switch (involuntary) = %d\n", rusage.ru_nivcsw) ; #else fprintf(fout,"Usage statistics not available\n") ; #endif } /* end Yprint_stats */ /* ==================================================================== */ DOUBLE Ycpu_time() { #ifndef AVOID struct rusage rusage; double user, systemTime; getrusage(RUSAGE_SELF, &rusage); user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec/1.0e6; systemTime = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec/1.0e6; return( user+systemTime ) ; #else return 0.0; #endif } /* end Ycpu_time */ /* ==================================================================== */ /* #define TEST */ #ifdef TEST /* test whether code works correctly. */ main() { Yprint_stats( stdout ) ; exit(0) ; } #endif graywolf-0.1.4+20170307gite1bf319/src/Ylib/string.c000066400000000000000000000115161305746555600211300ustar00rootroot00000000000000/* * Copyright (C) 1988-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: string.c DESCRIPTION:miscellaneous string utility functions CONTENTS: char **Ystrparser(char *,char *,int) char *Ystrclone(char *) char *str_tok(char *,char *) char *Yremove_lblanks( char * ) DATE: Jan 29, 1988 REVISIONS: May 04, 1988 - updated initProgram to include introTextFunction. Added remove_lblanks, directoryExists functions. Sep 26, 1988 - broke utils.c into three for archive. May 3, 1989 - added Yprefix and change name of scanner for Dahe. Aug 13, 1990 - modified Yremove_lblanks to understand tab characters too. Tue Oct 23 01:32:34 EDT 1990 - removed definition of Ysafe_free. Wed Apr 17 23:37:19 EDT 1991 - fixed logic problem with Yremove_lblanks. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) string.c version 3.8 2/29/92" ; #endif #include #include #include extern char *str_tok( P2( char *str, char *delimiters ) ) ; /* ----------------------------------------------------------------- String routines */ /* Ystrclone - clone a string - user must free memory when done */ char *Ystrclone(str) char *str ; { if( str ){ /* first check for null pointer */ if( *str ){ /* first check allow dereference */ return( (char *) strcpy( YMALLOC(strlen(str)+1, char), str ) ) ; } } return(NULL) ; } /* end strclone */ char **Ystrparser(str,dels,numtokens) char *str; char *dels ; /* delimiters */ INT *numtokens ; /* pass back number of tokens */ { static char *tokenBuf[LRECL] ; /* impossible to have more tokens */ /* than length of input line length */ INT index = 0 ; /* use str_tok to strip away delimiters */ /* first call to str_tok requires the string reference */ tokenBuf[index] = str_tok(str,dels) ; while( tokenBuf[index] ){ /* subsequent calls to str_tok doesn't requires the string ref */ /* str_tok remembers place in string */ tokenBuf[++index] = str_tok(NULL,dels) ; } /* return number of tokens and token buffer */ *numtokens = index ; return(tokenBuf) ; } /* end Ystrparser */ #ifndef apollo /* SYS5 string command str_tok - a string tokenizer */ char *str_tok(str,dels) char *str ; /* input string */ char *dels ; /* delimiters of string */ { static char *p, /* current place in string */ *token ; /* substring */ if( str ){ /* check if new string */ p = str ; } /* remove leading delimiters */ while( *p && strchr(dels,*p) ){ ++p ; } /* test for EOS */ if( *p ){ token = p++ ; /* mark beginning of token */ /* find end of token */ while( *p ){ if( strchr(dels,*p) ){ break ; } else { ++p ; } } /* mark end of string */ if( *p ){ *p++ = EOS ; } return(token) ; } /* no valid delimiters found */ return(NULL) ; } /* end str_tok */ #endif /* Yremove_lblanks - remove leading blanks from a string */ /* including tabs */ char *Yremove_lblanks( bufferptr ) char *bufferptr ; { for( ;bufferptr && *bufferptr;bufferptr++){ if( *bufferptr != ' ' && *bufferptr != '\t' ){ break ; } } return(bufferptr); } /* ---------------end string ------------------------------------- */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/system.c000066400000000000000000000063501305746555600211460ustar00rootroot00000000000000/* * Copyright (C) 1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: system.c DESCRIPTION:system routines DATE: Apr 26, 1990 REVISIONS: May 12, 1990 - added move file and getenv. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) system.c version 3.4 8/28/90" ; #endif #include #include INT Ysystem( program, abortFlag, exec_statement, abort_func ) char *program ; BOOL abortFlag ; char *exec_statement ; INT (*abort_func)() ; { INT status ; /* return status from program */ if( status = system( exec_statement ) ){ /* get status from exit routine */ status = (status & 0x0000FF00) >> 8 ;/* return code in 2nd byte */ /* now determine the program */ sprintf( YmsgG, "Program %s returned with exit code:%d\n",program, status ); M( ERRMSG, NULL, YmsgG ) ; if( abort_func ){ (*abort_func)() ; } if( abortFlag ){ YexitPgm( PGMFAIL ) ; /* exit the program */ } return( status ) ; } return( 0 ) ; } /* end Ysystem */ YcopyFile( sourcefile, destfile ) char *sourcefile, *destfile ; { sprintf( YmsgG, "/bin/cp %s %s", sourcefile, destfile ) ; Ysystem( "Ylib/YcopyFile", ABORT, YmsgG, NULL ) ; } /* end Ycopyfile */ YmoveFile( sourcefile, destfile ) char *sourcefile, *destfile ; { sprintf( YmsgG, "/bin/mv %s %s", sourcefile, destfile ) ; Ysystem( "Ylib/YmoveFile", ABORT, YmsgG, NULL ) ; } /* end Ycopyfile */ Yrm_files( files ) char *files ; { sprintf( YmsgG, "/bin/rm -rf %s", files ) ; Ysystem( "Ylib/Yrm_files", NOABORT, YmsgG, NULL ) ; } /* end Ycopyfile */ char *Ygetenv( env_var ) char *env_var ; { char *getenv() ; return( (char *) getenv( env_var ) ) ; } /* end Ygetenv */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/time.c000066400000000000000000000051301305746555600205530ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: time.c DESCRIPTION:This file contains a time utility routine which returns an ASCII string with time and date. CONTENTS: char *YcurTime( time_in_sec ) INT *time_in_sec ; DATE: Oct 23, 1988 REVISIONS: Apr 27, 1989 - changed to Y prefix and added time in seconds. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) time.c version 3.3 8/28/90" ; #endif #include #include #ifdef THINK_C #define TIME_T time_t #else #define TIME_T long #endif char *YcurTime( time_in_sec ) INT *time_in_sec ; { /* get current time - return ASCII string with time and date */ TIME_T t ; char *ptr ; char *nptr ; t = time((TIME_T *) 0) ; /* return time in seconds since Jan 1, 1970 if requested */ if( time_in_sec ){ *time_in_sec = t ; } /* get time and remove newline char */ for( nptr = ptr = ctime(&t) ;*nptr;nptr++ ){ if( *nptr == '\n' ){ *nptr = EOS ; } } return( ptr ) ; } /* end curTime */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/timer.c000066400000000000000000000071001305746555600207340ustar00rootroot00000000000000/* * Copyright (C) 1990-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: timer.c DESCRIPTION:create a timer for a process. CONTENTS: Ytimer_start() Ytimer_elapsed( time_elapsed ) INT *time_elapsed ; DATE: Oct 04, 1990 REVISIONS: Apr 01, 1991 - added SYS5 (A/UX) support (RAWeier) ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) timer.c version 4.3 10/25/91" ; #endif #include #include #ifdef SYS5 #include #else /* SYS5 */ #include #endif /* SYS5 */ static INT base_timeS = 0 ; /* the time in seconds at the start */ static INT milli_timeS ; /* the millisecond part of the start */ /* initialize the timer */ Ytimer_start() { #ifdef SYS5 struct tms tp ; times(&tp); base_timeS = (INT) tp.tms_cstime + (INT) tp.tms_cutime; #else /* SYS5 */ struct timeb tp ; ftime(&tp) ; base_timeS = (INT) tp.time ; milli_timeS = (INT) tp.millitm ; #endif /* SYS5 */ } /* end Ytimer_start */ /* this is the time elapsed since the timer start in milliseconds */ Ytimer_elapsed( time_elapsed ) INT *time_elapsed ; { #ifdef SYS5 struct tms tp; #else /* SYS5 */ struct timeb tp; #endif /* SYS5 */ INT time_offset ; if( base_timeS == 0 ){ /* start was not called */ *time_elapsed = 0 ; return ; } #ifdef SYS5 times(&tp); time_offset = (INT) tp.tms_cutime + (INT) tp.tms_cstime; time_offset -= base_timeS; *time_elapsed = time_offset * (1000/60); /* 1/60 sec to milisec */ #else /* SYS5 */ ftime(&tp) ; /* now add the current time */ time_offset = (INT) tp.time ; /* now subtract the start time */ time_offset -= base_timeS ; /* now multiply by 1000 to change to milliseconds */ time_offset *= 1000 ; /* now add the current millisecond time */ time_offset += (INT) tp.millitm ; /* now subtract the start millisecond time */ time_offset -= milli_timeS ; /* return the answer */ *time_elapsed = time_offset ; #endif /* SYS5 */ } /* end Ytimer_elapsed */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/trans.c000066400000000000000000000317701305746555600207550ustar00rootroot00000000000000/* * Copyright (C) 1990-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: trans.c DESCRIPTION:translation routines Ytranslate(l,b,r,t, orient) INT *l, *b, *r, *t, orient ; Ytranslatef(l,b,r,t, orient) DOUBLE *l, *b, *r, *t, orient ; Yinv_orient( orient ) int orient ; DATE: Aug 08, 1990 - from TimberWolfMC. REVISIONS: Wed Jan 30 14:11:50 EST 1991 - added Ytrans_init and and YtranslateC for left justifying rotations. Sat Nov 23 21:07:47 EST 1991 - added boundary translation functions. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) trans.c version 1.5 3/6/92" ; #endif #define YTRANS_DEFS #include #include #include /* ***************************************************************** translate rotation of cells ----------------------------------------------------------------- */ VOID Ytranslate(l,b,r,t, orient) INT *l, *b, *r, *t, orient ; { INT temp ; switch( orient ){ case 0 : break ; case 1 : /* mirror around x - axis */ temp = *t ; *t = - *b ; *b = - temp ; break ; case 2 : /* mirror around y - axis */ temp = *r ; *r = - *l ; *l = - temp ; break ; case 3 : /* rotate 180 */ temp = *t ; *t = - *b ; *b = - temp ; temp = *r ; *r = - *l ; *l = - temp ; break ; case 4 : /* mirror x and then rot 90 */ temp = *l ; *l = - *t ; *t = - temp ; temp = *r ; *r = - *b ; *b = - temp ; break ; case 5 : /* mirror x and then rot -90 */ temp = *r ; *r = *t ; *t = temp ; temp = *l ; *l = *b ; *b = temp ; break ; case 6 : /* rotate 90 degrees */ temp = *l ; *l = - *t ; *t = *r ; *r = - *b ; *b = temp ; break ; case 7 : /* rotate - 90 degrees */ temp = *t ; *t = - *l ; *l = *b ; *b = - *r ; *r = temp ; break ; } /* end switch */ } /* end function translate */ /* ***************************************************************** translate rotation of DOUBLE (cell weights) ----------------------------------------------------------------- */ VOID Ytranslatef(l,b,r,t, orient) DOUBLE *l, *b, *r, *t ; INT orient ; { DOUBLE temp ; switch( orient ){ case 0 : break ; case 1 : /* mirror around x - axis */ temp = *t ; *t = *b ; *b = temp ; break ; case 2 : /* mirror around y - axis */ temp = *r ; *r = *l ; *l = temp ; break ; case 3 : /* rotate 180 */ temp = *t ; *t = *b ; *b = temp ; temp = *r ; *r = *l ; *l = temp ; break ; case 4 : /* mirror x and then rot 90 */ temp = *l ; *l = *t ; *t = temp ; temp = *r ; *r = *b ; *b = temp ; break ; case 5 : /* mirror x and then rot -90 */ temp = *r ; *r = *t ; *t = temp ; temp = *l ; *l = *b ; *b = temp ; break ; case 6 : /* rotate 90 degrees */ temp = *l ; *l = *t ; *t = *r ; *r = *b ; *b = temp ; break ; case 7 : /* rotate - 90 degrees */ temp = *t ; *t = *l ; *l = *b ; *b = *r ; *r = temp ; break ; } /* end switch */ } /* end function translate */ /* given current cell bounding box and new orient - orient to change to */ /* set the cell centering flags - cell will always be left justified */ VOID Ytrans_init( cur_l,cur_b,cur_r,cur_t, new_orient ) INT cur_l, cur_b, cur_r, cur_t, new_orient ; { INT height ; INT length ; height = cur_t - cur_b ; length = cur_r - cur_l ; if( (height % 2 != 0 && (new_orient == 4 || new_orient == 6))|| (length % 2 != 0 && (new_orient == 2 || new_orient == 3))){ Ytrans_xflagG = TRUE ; } else { Ytrans_xflagG = FALSE ; } if( (height % 2 != 0 && (new_orient == 1 || new_orient == 3))|| (length % 2 != 0 && (new_orient == 4 || new_orient == 7))){ Ytrans_yflagG = TRUE ; } else { Ytrans_yflagG = FALSE ; } } /* end Yinv_orient */ /* return back to zero orientation */ static INT invOrientTableS[8] = { 0, 1, 2, 3, 4, 5, 7, 6 } ; INT Ytrans_inv_orient( orient ) INT orient ; { return( invOrientTableS[orient] ) ; } /* end Yinv_orient */ /* this translate performs translation but also centers the tile */ /* so that the truncatated side is always to the left */ VOID YtranslateC(l,b,r,t,orient) INT *l, *b, *r, *t, orient ; { Ytranslate( l, b, r, t, orient ) ; if( Ytrans_xflagG ){ (*l)++ ; (*r)++ ; } if( Ytrans_yflagG ){ (*b)++ ; (*t)++ ; } } /* end YtranslateC */ /* this translate performs translation but also centers the tile */ /* so that the truncatated side is always to the left */ VOID YtranslateT(l,b,r,t, orient) INT *l, *b, *r, *t, orient ; { INT height ; INT length ; height = *t - *b ; length = *r - *l ; Ytranslate( l, b, r, t, orient ) ; if( (height % 2 != 0 && (orient == 4 || orient == 6))|| (length % 2 != 0 && (orient == 2 || orient == 3))){ (*l)++ ; (*r)++ ; } if( (height % 2 != 0 && (orient == 1 || orient == 3))|| (length % 2 != 0 && (orient == 4 || orient == 7))){ (*b)++ ; (*t)++ ; } } /* end YtranslateT */ /* ----------------------------------------------------------------- Ytrans_pos - takes a cell orientation, cell pin position, and cell center and returns global postion. This routine is for test - normally a macro defined in relpos.h is used for speed. Conditional compile switch is in relpos.h. ----------------------------------------------------------------- */ VOID Ytrans_rel_pos( orient_R, globalX_R, globalY_R, relativeX_R, relativeY_R, cellX_R, cellY_R ) INT orient_R, *globalX_R, *globalY_R, relativeX_R, relativeY_R, cellX_R, cellY_R ; { switch(orient_R){ case 0: *globalX_R = cellX_R + relativeX_R ; *globalY_R = cellY_R + relativeY_R ; break ; case 1: *globalX_R = cellX_R + relativeX_R ; *globalY_R = cellY_R - relativeY_R ; break ; case 2: *globalX_R = cellX_R - relativeX_R ; *globalY_R = cellY_R + relativeY_R ; break ; case 3: *globalX_R = cellX_R - relativeX_R ; *globalY_R = cellY_R - relativeY_R ; break ; case 4: *globalX_R = cellX_R - relativeY_R ; *globalY_R = cellY_R - relativeX_R ; break ; case 5: *globalX_R = cellX_R + relativeY_R ; *globalY_R = cellY_R + relativeX_R ; break ; case 6: *globalX_R = cellX_R - relativeY_R ; *globalY_R = cellY_R + relativeX_R ; break ; case 7: *globalX_R = cellX_R + relativeY_R ; *globalY_R = cellY_R - relativeX_R ; break ; } } /* end Ytrans_rel_pos */ /* ----------------------------------------------------------------- Ytrans_post - same as Ytrans_rel_pos except it does cell centering in addition. ----------------------------------------------------------------- */ VOID Ytrans_rel_post( orient_R, globalX_R, globalY_R, relativeX_R, relativeY_R, cellX_R, cellY_R ) INT orient_R, *globalX_R, *globalY_R, relativeX_R, relativeY_R, cellX_R, cellY_R ; { Ytrans_rel_pos( orient_R, globalX_R, globalY_R, relativeX_R, relativeY_R, cellX_R, cellY_R ) ; if( Ytrans_xflagG ){ (*globalX_R)++ ; } if( Ytrans_yflagG ){ (*globalY_R)++ ; } } /* end Ytrans_rel_post */ /* ***************** STATIC VARIABLE DEFINITIONS ******************* */ static INT num_ptS ; /* number of points for boundary */ static INT *pt_xS = NIL(INT *); /* x point array */ static INT *pt_yS = NIL(INT *); /* y point array */ static INT countS ; /* count during output */ static INT pt_allocS ; /* point allocation */ #define EXPECTEDPTS 2 VOID Ytrans_boun_init() { /* allocate the space for reoordering the points of the macro */ num_ptS = 0 ; /* allocate memory if needed */ if(!(pt_xS)){ pt_allocS = EXPECTEDPTS ; pt_xS = YVECTOR_MALLOC( 1, pt_allocS, INT ) ; pt_yS = YVECTOR_MALLOC( 1, pt_allocS, INT ) ; } } /* end Ytrans_boun_init() */ VOID Ytrans_boun_add( x, y ) INT x, y ; { /* increase the space if necessary */ if( ++num_ptS >= pt_allocS ){ pt_allocS += EXPECTEDPTS ; pt_xS = YVECTOR_REALLOC( pt_xS, 1, pt_allocS, INT ) ; pt_yS = YVECTOR_REALLOC( pt_yS, 1, pt_allocS, INT ) ; } pt_xS[num_ptS] = x ; pt_yS[num_ptS] = y ; } /* end Ytrans_boun_add() */ VOID Ytrans_boun( orient, new_xc, new_yc, use_new_orient ) INT new_xc, new_yc, orient ; BOOL use_new_orient ; { INT pt ; /* counter */ INT xc, yc ; /* cell center */ INT x, y ; /* cell relative coordinate */ INT l, b, r, t ; /* bounding box of boundary */ l = INT_MAX ; r = INT_MIN ; b = INT_MAX ; t = INT_MIN ; for( pt = 1; pt <= num_ptS; pt++ ){ l = MIN( l, pt_xS[pt] ) ; r = MAX( r, pt_xS[pt] ) ; b = MIN( b, pt_yS[pt] ) ; t = MAX( t, pt_yS[pt] ) ; } /* end for( pt = 1... */ xc = (l+r)/2 ; yc = (b+t)/2 ; if(!(use_new_orient)){ /* use what we calculated as center instead */ new_xc = xc ; new_yc = yc ; } Ytrans_init( l, b, r, t, orient ) ; for( pt = 1; pt <= num_ptS; pt++ ){ x = pt_xS[pt] -= xc ; y = pt_yS[pt] -= yc ; REL_POST( orient, pt_xS[pt], pt_yS[pt], /* result */ x, y, /* cell relative */ new_xc, new_yc ) ; /* cell center */ } /* end for( pt = 1... */ countS = 0 ; } /* end Ytrans_boun() */ BOOL Ytrans_boun_pt( x_ret, y_ret ) INT *x_ret, *y_ret ; { INT this_pt ; /* used in calculating direction */ INT nextpos, nextneg ; /* next position CW and CCW */ INT x, y ; /* the lowest left pt coordinate */ INT pt ; /* counter */ static INT ptL ; /* current point in array */ static INT limitL ; /* current direction limit */ if( ++countS == 1 ){ /* now we need to reorder the vertices */ /* all the points have been rotated into their proper view and */ /* stored in the vertices array. Now find lowest of the left pts. */ x = INT_MAX ; y = INT_MAX ; for( pt = 1; pt <= num_ptS; pt++ ){ if( pt_xS[pt] <= x ){ if( pt_yS[pt] <= y ){ x = pt_xS[pt] ; y = pt_yS[pt] ; ptL = pt ; } } } /* end for( pt = 1; pt <= numptS... */ /* find the adjacent points in forward and backwards directions */ if( ptL == num_ptS ){ nextpos = 1 ; } else { nextpos = ptL + 1 ; } if( ptL == 1 ){ nextneg = num_ptS ; } else { nextneg = ptL - 1 ; } /* set limitL which tells us direction */ if( pt_xS[nextpos] == x && pt_yS[nextpos] > y ){ /* clockwise is positive */ limitL = ptL + num_ptS; } else if( pt_xS[nextneg] == x && pt_yS[nextneg] > y ){ /* clockwise is negative */ limitL = ptL - num_ptS ; } else { M( ERRMSG, "Ytrans_next_pt", "couldn't find clockwise direction for boundary\n" ) ; return( FALSE ) ; } *x_ret = x ; *y_ret = y ; return( TRUE ) ; } else if( countS <= num_ptS ){ if( limitL >= num_ptS ){ /* clockwise is positive */ if( ++ptL < limitL ) { if( ptL > num_ptS ){ this_pt = ptL - num_ptS ; } else { this_pt = ptL ; } *x_ret = pt_xS[this_pt] ; *y_ret = pt_yS[this_pt] ; return( TRUE ) ; } } else { /* clockwise is negative */ if( --ptL > limitL ){ if( ptL < 1 ){ this_pt = num_ptS + ptL ; } else { this_pt = ptL ; } *x_ret = pt_xS[this_pt] ; *y_ret = pt_yS[this_pt] ; return( TRUE ) ; } } } /* end if( countS <= numptS ... */ return( FALSE ) ; /* no more points to deal with */ } /* end Ytrans_boun_pt() */ VOID Ytrans_boun_free() { /* free allocate memory */ if(pt_xS){ YVECTOR_FREE( pt_xS, 1 ) ; YVECTOR_FREE( pt_yS, 1 ) ; pt_xS = NIL(INT *) ; } } /* end Ytrans_boun_free() */ /* ***************************************************************** */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/wgraphics.c000066400000000000000000000255251305746555600216160ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: wgraphics.c DESCRIPTION:graphic drawing routines which only write files. This is a derivative of draw.c except that it does not need to link with the X11 library. If you are just writing binary files for later use, please use this set of routines. Make sure to use instead of ******************************************************** CONTENTS: TWinitWGraphics(desiredColors,numC,dataDir) char **desiredColors, *datDir ; INT numC ; TWcloseWGraphics() TWstartWFrame() TWflushWFrame() TWsetWFrame( number ) INT number ; drawWPin( ref_num, x1,y1,x2,y2,color,label) drawWLine( ref_num,x1,y1,x2,y2,color,label) drawWRect( ref_num, x1,y1,x2,y2,color,label) INT ref_num ; INT x1,y1,x2,y2, color; char *label; DATE: Mar 21, 1989 - began as derivative of draw.c REVISIONS: Thu Jan 24 20:20:32 PST 1991 - added missing return. Mon May 6 20:35:28 EDT 1991 - no longer support pin file. Mon Aug 12 15:57:17 CDT 1991 - fixed problem with routine names. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) wgraphics.c version 3.8 8/12/91" ; #endif #include #include #define TWDRAWCODE #include #include #include #include #include #include #include #define NODIRECTORY 1 #define NOINIT 2 /********** STATIC DEFINITIONS FOR WRITE FUNCTIONS *************/ static char *dirNameS ; /* pathname including DATA directory */ static BOOL initS = FALSE ; /* tells whether initialization performed */ static INT frameCountS ; /* current number of display frames */ static BOOL frameOpenS ; /* tells whether frame files are open */ static FILE *cellFileS = NULL ; /* cellfile pointer */ static FILE *netFileS = NULL ; /* net file pointer */ static FILE *symbFileS = NULL ; /* symbfile pointer */ static INT numCellS = 0 ; /* cell counter */ static INT numNetS = 0 ; /* net counter */ static INT numCharS = 0 ; /* symbol table counter */ BOOL TWinitWGraphics( numC, desiredColors) INT numC ; char **desiredColors ; { char *Yfixpath() ; char *Ygetenv() ; if(!(dirNameS = Ygetenv( "DATADIR" ))){ /* find fullpathname of data directory */ dirNameS = Ystrclone( Yfixpath( "./DATA", FALSE )) ; } /* first look for data directory */ if( !(YdirectoryExists(dirNameS)) ){ sprintf( YmsgG,"Can't find data directory:%s\n", dirNameS ); M(ERRMSG,"TWinitGraphics",YmsgG ) ; YexitPgm( NODIRECTORY ) ; } /* set count to zero */ frameCountS = 0 ; frameOpenS = FALSE ; /* initialization has been done sucessfully */ initS = TRUE ; return( initS ) ; } /* end function TWinitWGraphics */ TWcloseWGraphics() { if(!(initS )){ fprintf(stderr,"ERROR[closeGraphics]:initialization was not" ) ; fprintf(stderr,"performed\n before calling closeGraphics\n" ) ; YexitPgm( NOINIT ) ; } /* check to see if other files are open */ if( frameOpenS ){ TWflushWFrame() ; } } /* end TWcloseGraphics */ TWstartWFrame() { char filename[LRECL] ; char dummy[5] ; UNSIGNED_INT nitems ; if(!(initS )){ fprintf(stderr,"ERROR[startNewFrame]:initialization was not" ) ; fprintf(stderr,"performed\n before calling startNewFrame\n" ) ; YexitPgm( NOINIT ) ; } if( frameOpenS ){ TWflushWFrame() ; } /* signal that frame is now open */ frameOpenS = TRUE ; /* now open next frame files */ /* increment frame count */ frameCountS++ ; /* first cell file */ sprintf( filename, "%s/cell.bin.%d", dirNameS, frameCountS ) ; cellFileS = TWOPEN( filename, "w", ABORT ) ; numCellS = 0 ; /* reset cell counter */ /* next net file */ sprintf( filename, "%s/net.bin.%d", dirNameS, frameCountS ) ; netFileS = TWOPEN( filename, "w", ABORT ) ; numNetS = 0 ; /* reset net counter */ /* next symb file */ sprintf( filename, "%s/symb.bin.%d", dirNameS, frameCountS ) ; symbFileS = TWOPEN( filename, "w", ABORT ) ; /* write a dummy character at start file makes test for label */ /* index easier since symbtable[0] is meaningless now. */ /* All indexes into symbol table which are valid must be positive */ dummy[0] = EOS ; nitems = (UNSIGNED_INT) 1 ; fwrite( dummy, sizeof(char), nitems, symbFileS ) ; numCharS = 1 ; /* reset symbol table counter */ } /* end startWFrame */ /* write size of data at end of files and close them if frames are open */ TWflushWFrame() { char dummy[5] ; UNSIGNED_INT nitems ; INT numw ; INT excess ; /* check to see if other files are open */ if( frameOpenS ){ nitems = (UNSIGNED_INT) 1 ; /* terminate the file with number of records in each file */ numw = fwrite( &numCellS,sizeof(UNSIGNED_INT),nitems,cellFileS ) ; ASSERT( numw == 1, "startNewFrame", "Number written zero" ) ; numw = fwrite( &numNetS, sizeof(UNSIGNED_INT),nitems,netFileS ) ; ASSERT( numw == 1, "startNewFrame", "Number written zero" ) ; /* need to put on integer boundary */ if( excess = numCharS % 4 ){ /* pad the remainder with dummy */ nitems = (UNSIGNED_INT) (4 - excess ) ; numw = fwrite( dummy, sizeof(char), nitems, symbFileS ) ; ASSERT( numw == nitems,"startNewFrame","Number written zero"); } nitems = (UNSIGNED_INT) 1 ; numw = fwrite( &numCharS,sizeof(UNSIGNED_INT),nitems,symbFileS ) ; ASSERT( numw == 1, "startNewFrame", "Number written zero" ) ; /* files are open close them */ ASSERT( cellFileS, "startNewFrame", "cell file should be open" ) ; TWCLOSE( cellFileS ) ; ASSERT( netFileS, "startNewFrame", "net file should be open" ) ; TWCLOSE( netFileS ) ; ASSERT( symbFileS, "startNewFrame", "symb file should be open" ) ; TWCLOSE( symbFileS ) ; /* signal that frame has been closed */ frameOpenS = FALSE ; } } /* TWflushWFrame */ TWsetWFrame( number ) INT number ; { char fileName[LRECL] ; if( number <= 0 ){ /* search for the first valid file */ /* find max number of frames of data */ for( frameCountS=1;;frameCountS++ ){ sprintf( fileName,"%s/cell.bin.%d",dirNameS,frameCountS ) ; if(! (YfileExists(fileName) )){ /* last file successfully read is one less */ frameCountS-- ; break ; } } } else { frameCountS = number ; } } /* end TWsetWFrame */ /* ********* GENERIC WRITE ROUTINES ************** */ /* draw a rectangle whose diagonals are (x1,y1) and (x2,y2) */ /* if the specified color is default or invalid, use default color */ TWdrawWPin( ref_num, x1,y1,x2,y2,color,label) INT ref_num ; /* reference number */ INT x1,y1,x2,y2, color; char *label; { TWdrawWRect( ref_num, x1,y1,x2,y2,color,label) ; } /* end drawWPin */ /* draw a one pixel tall line segment from x1,y1 to x2,y2 */ TWdrawWLine( ref_num,x1,y1,x2,y2,color,label) INT ref_num ; /* reference number */ INT x1,y1,x2,y2,color ; char *label; { DATABOX record ; UNSIGNED_INT nitems ; INT numw ; /* number written */ /* fill up data record file destination net file */ record.ref = (UNSIGNED_INT) ref_num ; record.x1 = x1 ; record.x2 = x2 ; record.y1 = y1 ; record.y2 = y2 ; /* now take care of color */ record.color = color ; /* now store string in symbol table if given */ if( label ){ /* write string to symbol table file */ nitems = (UNSIGNED_INT) ( strlen( label ) + 1 ) ; numw = fwrite( label, sizeof(char), nitems, symbFileS ) ; ASSERT( numw == nitems, "drawLine", "Couldnt write to string table" ); /* now store in net file offset in table */ record.label = numCharS ; /* now update offset to include this string */ numCharS += (INT) nitems ; } else { record.label = 0 ; } /* now write record */ nitems = (UNSIGNED_INT) 1 ; numw = fwrite( &record, sizeof(DATABOX),nitems,netFileS ) ; ASSERT( numw == 1, "drawLine", "Record not written..." ) ; numNetS++ ; } /* end drawWLine */ /* draw a rectangle whose diagonals are (x1,y1) and (x2,y2) */ /* if the specified color is default or invalid, use default color */ TWdrawWRect( ref_num, x1,y1,x2,y2,color,label) INT ref_num ; /* reference number */ INT x1,y1,x2,y2, color; char *label; { DATABOX record ; UNSIGNED_INT nitems ; INT numw ; /* number of records written */ /* fill up data record file destination net file */ record.ref = (UNSIGNED_INT) ref_num ; record.x1 = x1 ; record.x2 = x2 ; record.y1 = y1 ; record.y2 = y2 ; record.color = color ; /* now store string in symbol table if given */ if( label ){ /* write string to symbol table file */ nitems = (UNSIGNED_INT) ( strlen( label ) + 1 ) ; numw = fwrite( label, sizeof(char), nitems, symbFileS ) ; ASSERT( numw == nitems, "drawWRect", "Couldn't write to string table" ); /* now store in net file offset in table */ record.label = numCharS ; /* now update offset to include this string */ numCharS += (INT) nitems ; } else { record.label = 0 ; } /* now write record */ nitems = (UNSIGNED_INT) 1 ; numw = fwrite( &record, sizeof(DATABOX),nitems,cellFileS ) ; numCellS++ ; ASSERT( numw == 1, "drawWRect", "Record not written..." ) ; } /* end drawWRect */ /* ************************************************************** */ graywolf-0.1.4+20170307gite1bf319/src/Ylib/ydebug.c000066400000000000000000000163141305746555600211020ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: ydebug.c DESCRIPTION:This file turns on and off debug testing. Used by assert and D() routines to determine whether to perform debug testing. At any time, debug can be turned on or off if the debug has been compiled into the code. This gives uses maximum flexibility for debug can be loaded into code using -DDEBUG if asserts and D() statements are used. They remain dormant in code except for Ydebug() call until debugFlagS is turned on. For production code, -DDEBUG should not be used. Each routine is stored in a red-black tree during the execution. CONTENTS: Ydebug() YsetDebug( flag ) DATE: Apr 9, 1989 REVISIONS: Apr 10, 1990 - rewrote debug routines so that each individual debug routine has its own name and can be turned off and on without recompiling. At the end of a execution, it updates the dbg file. Also moved name to ydebug because of a dbx bug. Apr 28, 1990 - added YdebugAssert so that assertions are not added to the tree. Fri Jan 18 18:38:36 PST 1991 - fixed to run on AIX. Fri Feb 22 23:40:32 EST 1991 - changed default to suit Richard. Wed Apr 17 23:33:17 EDT 1991 - renamed treeS to debug_treeS so that debugging would be easier. Stupid dbx. Mon Aug 12 15:54:00 CDT 1991 - update for new Yrbtree_init. Sun Nov 3 13:13:12 EST 1991 - fixed gcc complaints. Tue Feb 4 15:31:28 EST 1992 - added return_code variable to Ydebug so you can switch it in the debugger if necessary. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) ydebug.c (Yale) version 3.15 2/7/92" ; #endif #include #include #include #include #include #define DBGFILE "dbg" typedef struct { char *routine ; BOOL debugOn ; } ROUTINE, *ROUTINEPTR ; static BOOL debugFlagS = FALSE ; static BOOL firstTimeS = FALSE ; /* first time we ran program */ static YTREEPTR debug_treeS ; /* ********* STATIC DEFINITIONS ************ */ static INT compare_routine( P2(ROUTINEPTR key1, ROUTINEPTR key2 ) ) ; static ROUTINEPTR make_data_debug( P2(char *string, BOOL debugOn ) ) ; BOOL Ydebug( routine ) char *routine ; { ROUTINEPTR data ; /* the matched data record */ ROUTINE routine_key ; /* used to test key */ BOOL return_code ; /* return code so we can set in debugger */ if( debugFlagS ){ return_code = FALSE ; if( routine ){ routine_key.routine = routine ; if( data = (ROUTINEPTR) Yrbtree_search( debug_treeS, (char *) &(routine_key) ) ){ if( data->debugOn ){ return_code = TRUE ; } } else { /* add it to the tree */ if( firstTimeS ){ /* the default is for it to be off */ data = make_data_debug( routine, FALSE ) ; Yrbtree_insert( debug_treeS, (char *) data ) ; } else { /* when adding new routines to an existing file */ /* the default is for it to be off */ data = make_data_debug( routine, FALSE ) ; Yrbtree_insert( debug_treeS, (char *) data ) ; } } } else { fprintf( stderr, "No debug routine name specified here\n" ) ; } } else { return_code = FALSE ; } return( return_code ) ; } /* end Ydebug */ /* ASSERTIONS are always on */ BOOL YdebugAssert() { return( debugFlagS ) ; } /* end YdebugAssert */ YdebugWrite() { ROUTINEPTR data ; /* the data in the tree */ FILE *fp ; /* write to the debug file */ if( debugFlagS ){ if( YfileExists( DBGFILE ) ){ /* move to .bak to save a copy of the file */ sprintf( YmsgG, "/bin/cp %s %s.bak", DBGFILE,DBGFILE ) ; system( YmsgG ) ; } /* now write a debug file */ fp = TWOPEN( DBGFILE, "w", ABORT ) ; for( data = (ROUTINEPTR) Yrbtree_enumerate(debug_treeS,TRUE);data; data = (ROUTINEPTR) Yrbtree_enumerate(debug_treeS,FALSE)){ fprintf( fp, "%s %d\n", data->routine, data->debugOn ) ; } TWCLOSE( fp ) ; } } YsetDebug( flag ) BOOL flag ; { char buffer[LRECL], *bufferptr ; char **tokens ; /* for parsing menu file */ INT numtokens ; /* number of tokens on the line */ INT line ; /* count lines in input file */ FILE *fp ; /* open file pointer */ ROUTINEPTR data ; /* new data to be stored */ if( flag ){ /* initialize tree of routine name */ YRBTREE_INIT( debug_treeS, compare_routine ); line = 0 ; if( fp = TWOPEN( DBGFILE, "r", NOABORT ) ){ while( bufferptr=fgets(buffer,LRECL,fp )){ /* parse file */ line ++ ; /* increment line number */ tokens = Ystrparser( bufferptr, " \t\n", &numtokens ); if( numtokens == 2 ){ data = make_data_debug( tokens[0], atoi(tokens[1]) ) ; Yrbtree_insert( debug_treeS, (char *) data ) ; } else { sprintf( YmsgG, "Syntax error on line:%d\n", line ) ; M(ERRMSG, "YsetDebug", YmsgG ) ; } } TWCLOSE( fp ) ; } else { firstTimeS = TRUE ; } } debugFlagS = flag ; } /* end YsetDebug */ static INT compare_routine( key1, key2 ) ROUTINEPTR key1, key2 ; { return( strcmp( key1->routine, key2->routine ) ) ; } /* end compare */ static ROUTINEPTR make_data_debug( string, debugOn ) char *string ; BOOL debugOn ; { ROUTINEPTR data ; data = YMALLOC( 1, ROUTINE ) ; data->routine = Ystrclone( string ) ; data->debugOn = debugOn ; return( data ) ; } /* end make_data_debug */ YfixDebug( ptr, type ) char *ptr ; INT type ; { switch( type ){ case 0: /* integer */ printf( "%d\n", (INT) ptr ) ; break ; case 1: /* string */ printf( "%s\n", ptr ) ; break ; case 2: /* hexidecimal */ printf( "%0x\n", (INT) ptr ) ; break ; } } graywolf-0.1.4+20170307gite1bf319/src/Ylib/yreadpar.c000066400000000000000000000617701305746555600214400ustar00rootroot00000000000000/* * Copyright (C) 1990-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: yreadpar.c DESCRIPTION: Read a TimberWolf parameter file. CONTENTS: DATE: Oct 24, 1990 REVISION: Nov 23, 1990 - Fixed for tab spaces in USER file. Dec 21, 1990 - Changed buffer to static so it won't disappear upon return. Sat Jan 26 16:33:03 PST 1991 - added genrows to list of programs. Wed Jan 30 18:35:01 EST 1991 - fixed problem with numtokens access violation on empty lines. Fri Feb 22 23:41:39 EST 1991 - added wildcard boolean to Yreadpar_next and renamed for Tomus. Wed Apr 17 23:32:00 EDT 1991 - Added design rule information into the .par file. Wed Jun 5 16:35:41 CDT 1991 - added overhang and aspect limit to design rules. Also fixed Yreadpar_next problems. Mon Aug 12 16:02:33 CDT 1991 - modified for new Yrbtree_init routine. Sat Apr 18 11:29:50 EDT 1992 - added compactor program entry - CMPT. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) yreadpar.c (Yale) version 1.6 10/1/91" ; #endif #include #include #include #include #include #include #define COMMENT '#' #define WILDCARD '*' #define END(v) (v-1 + sizeof(v)/sizeof(v[0]) ) /* for table lookup */ #define CHARACTERISTIC (DOUBLE) 1000.0 ; #define DEFAULT_LAYERS 3 #define DEFAULT_VIAS 2 /* the rule type definitions */ #define CAPACITANCE_T 'c' #define RESISTANCE_T 'r' #define DIRECTION_T 'd' #define LAYER_T 'l' #define WIDTH_T 'w' #define VIA_T 'v' #define SPACING_T 's' #define OVERHANG_T 'o' #define ASPECTLIM_T 'a' #define ERROR_CHECK(type) \ if(!(layerArrayS )){ \ M(ERRMSG,"Yreadpar_errorcheck","No rules found in parameter file\n");\ return( (type) 0 ) ; \ } typedef struct { char *rule ; union { BOOL bvalue ; INT ivalue ; DOUBLE fvalue ; char *svalue ; } value ; } RULEBOX, *RULEPTR ; static YTREEPTR rule_treeS ; static INT numlayS = 0 ; static INT numviaS = 0 ; static INT alloc_layS = DEFAULT_LAYERS ; static INT alloc_viaS = DEFAULT_VIAS ; static char **layerArrayS = NIL(char **) ; static char **viaArrayS = NIL(char **) ; /* reserved programs binary search */ /* ----------------------------------------------------------------- The following is table of the reserved words - Table must be in alphabetical order for binary search to work properly. ----------------------------------------------------------------- */ static struct ptable_rec { /* reserved program table */ char *program ; /* program name */ INT program_id ; /* program id */ char *suffix ; /* program suffix */ } pgmtableS[] = { "CMPT", CMPT, "cpar", "GENR", GENR, "genpar", "MICK", MICK, "gpar", "MINC", MINC, "mtpar", "PART", PART, "ppar", "SGGR", SGGR, "sgpar", "TWAR", TWAR, "apar", "TWMC", TWMC, "mpar", "TWSC", TWSC, "spar", "USER", USER, "par" } ; typedef struct { char *parameter ; /* the parameter keyword */ char **tokens ; /* the values of the parameter */ INT numtokens ; /* number of tokens */ INT program ; /* name of program */ } PARAM, *PARAMPTR ; static FILE *fpS = NIL(FILE *) ; static char copy_bufferS[LRECL] ; static char bufferS[LRECL] ; static INT filter_idS = 0 ; static INT prog_idS = 0 ; static INT lineS = 0 ; static char filterNameS[5] ; static BOOL verboseS = TRUE ; static INT prog2id( program ) char *program ; { INT c ; struct ptable_rec *low = pgmtableS, /* ptr to beginning */ *mid , *high = END(pgmtableS) ; /* ptr to end */ /* binary search to look thru table to find pattern match */ while( low <= high){ mid = low + (high-low) / 2 ; if( (c = strcmp(mid->program, program) ) == STRINGEQ){ return( mid->program_id ) ; /* return token number */ } else if( c < 0 ){ low = mid + 1 ; } else { high = mid - 1 ; } } /* at this point we haven't found a match so we have an error */ return( UNKN ) ; } /* end prog2id function */ static char *id2prog( id ) INT id ; { if( id > 0 && id <= MAXID ){ return( pgmtableS[id-1].program ) ; } else { return( NIL(char *) ) ; } } /* end id2prog */ static char *id2suffix( id ) INT id ; { if( id > 0 && id <= MAXID ){ return( pgmtableS[id-1].suffix ) ; } else { return( NIL(char *) ) ; } } /* end id2prog */ /* compare routine for design rule processing */ static INT compare_rule( key1, key2 ) RULEPTR key1, key2 ; { return( (INT)strcmp( key1->rule, key2->rule ) ) ; } /* end compare */ static BOOL check_layer( layer ) char *layer ; { INT i ; /* counter */ verboseS = FALSE ; if( Yreadpar_layer2id( layer ) ){ verboseS = TRUE ; return( FALSE ) ; } else { for( i = 1; i <= numviaS; i++ ){ if( strcmp( Yreadpar_viaId2name( i ), layer ) == STRINGEQ ){ verboseS = TRUE ; return( FALSE ) ; } } } sprintf( YmsgG, "Layer or via:%s has not been defined. Rule ignored.\n", layer) ; M( ERRMSG, "check_layer", YmsgG ) ; verboseS = TRUE ; return( TRUE ) ; } /* end check_layer */ static char *make_data( rule, value, type ) char *rule ; char *value ; char type ; { RULEPTR data ; RULEBOX data_buffer ; DOUBLE fvalue ; INT data_value ; char key[LRECL] ; /* make the key */ sprintf( key, "%s:%c", rule, type ) ; data_buffer.rule = key ; /* see if key already exists */ if( Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){ sprintf( YmsgG, "Rule on line:%d already exists. Ignored.\n", lineS ) ; M( ERRMSG, "Yreadpar_init", YmsgG ) ; return( NIL(char *) ) ; } data = YMALLOC( 1, RULEBOX ) ; data->rule = Ystrclone( key ) ; switch( type ){ case CAPACITANCE_T: case RESISTANCE_T: data->value.fvalue = atof( value ) ; break ; case DIRECTION_T: /* use the HnotV convention */ if( strcmp( value, "vertical" ) == STRINGEQ ){ data->value.bvalue = FALSE ; } else if( strcmp( value, "horizontal" ) == STRINGEQ ){ data->value.bvalue = TRUE ; } else { M( ERRMSG, "Yreadpar_init", "Unknown layer direction\n" ) ; } break ; case LAYER_T: data->value.ivalue = (INT) value ; break ; case WIDTH_T: /* now calculate value */ fvalue = atof( value ) ; /* This code converts the float to an integer fvalue *= CHARACTERISTIC ; data_value = ROUND( fvalue ) ; data->value.ivalue = data_value ; */ data->value.fvalue = fvalue ; break ; case ASPECTLIM_T: data->value.fvalue = atof( value ) ; break ; } /* end switch on type */ return( (char *) data ) ; } /* end make_data */ static char *make_data2( object1, object2, value, type ) char *object1 ; char *object2 ; char *value ; char type ; { RULEPTR data ; RULEBOX data_buffer ; DOUBLE fvalue ; INT data_value ; char key[LRECL] ; /* make the key order the key alphabetically */ if( strcmp( object1, object2 ) <= STRINGEQ ){ sprintf( key, "%s/%s:%c", object1, object2, type ) ; } else { sprintf( key, "%s/%s:%c", object2, object1, type ) ; } data_buffer.rule = key ; /* see if key already exists */ if( Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){ sprintf( YmsgG, "Rule on line:%d already exists. Ignored.\n", lineS ) ; M( ERRMSG, "Yreadpar_init", YmsgG ) ; return( NIL(char *) ) ; } data = YMALLOC( 1, RULEBOX ) ; data->rule = Ystrclone( key ) ; switch( type ){ case VIA_T: data->value.svalue = Ystrclone( value ) ; break ; case SPACING_T: /* now calculate value */ fvalue = atof( value ) ; /* This code converts the float to an integer fvalue *= CHARACTERISTIC ; data_value = ROUND( fvalue ) ; data->value.ivalue = data_value ; */ data->value.fvalue = fvalue ; break ; } return( (char *) data ) ; } /* end make_data_spacing */ VOID Yreadpar_init( design_name, parfile, filter, abortFlag ) char *design_name ; INT parfile ; INT filter ; BOOL abortFlag ; { char *suffix ; /* parameter file suffix */ char *pname ; /* program name of filter */ char filename[LRECL] ; /* the file name */ char *bufferptr ; char **tokens ; INT i ; /* counter */ INT numtokens ; /* number of tokens on a line */ BOOL rule_section ; /* true if rule section exists */ char *data ; /* rule data to be stored */ static BOOL rules_unreadL=TRUE; /* false after the rules have been read */ if( suffix = id2suffix( parfile ) ){ prog_idS = parfile ; sprintf( filename, "%s.%s", design_name, suffix ) ; if( pname = id2prog( filter )){ filter_idS = filter ; strcpy( filterNameS, pname ) ; } else { M( ERRMSG, "Yreadpar_init", "Unknown filter program\n" ) ; } } else { M( ERRMSG, "Yreadpar_init", "Unknown parameter file\n" ) ; return ; } /* end switch on program */ /* now that we have the file name open the par file */ if(fpS){ M( ERRMSG, "Yreadpar_init", "Only one par file may be read at the same time\n" ) ; return ; } fpS = TWOPEN( filename, "r", abortFlag ) ; if(!(fpS) ){ return ; } lineS = 0 ; rule_section = FALSE ; /* TRY to read the RULES SECTION of the parameter file */ while( bufferptr = fgets( bufferS, LRECL, fpS ) ){ lineS++ ; /* remove leading blanks */ bufferptr = Yremove_lblanks( bufferptr ) ; if( *bufferptr == '#' ){ /* skip over comments */ continue ; } tokens = Ystrparser( bufferptr, " \t\n", &numtokens ) ; if( numtokens == 0 ){ continue ; } if( strcmp( tokens[0], "RULES" ) == STRINGEQ ){ rule_section = TRUE ; /* initialize tree of rules */ rule_treeS = Yrbtree_init( compare_rule ) ; /* initialize the number of layers */ layerArrayS = YVECTOR_CALLOC( 1,alloc_layS,char *) ; viaArrayS = YVECTOR_CALLOC( 1,alloc_viaS,char *) ; continue ; } else if( strcmp( tokens[0], "ENDRULES" ) == STRINGEQ ){ rules_unreadL = FALSE ; break ; } if( rule_section && rules_unreadL ){ if( strcmp( tokens[0], "width" ) == STRINGEQ && numtokens == 3 ){ if( check_layer( tokens[1] ) ){ continue ; } data = make_data( tokens[1], tokens[2], WIDTH_T ) ; if( data ){ Yrbtree_insert( rule_treeS, data ) ; } } else if( strcmp( tokens[0], "spacing" ) == STRINGEQ && numtokens == 4 ){ if( check_layer( tokens[1] ) ){ continue ; } if( check_layer( tokens[2] ) ){ continue ; } data = make_data2( tokens[1], tokens[2], tokens[3], SPACING_T ) ; if( data ){ Yrbtree_insert( rule_treeS, data ) ; } } else if( strcmp( tokens[0], "via" ) == STRINGEQ && (numtokens == 4 || numtokens == 5) ){ if( ++numviaS >= alloc_viaS ){ /* need to expand the number of vias allocated */ alloc_viaS = numviaS + 3 ; viaArrayS = YVECTOR_REALLOC( viaArrayS,1,alloc_viaS,char * ) ; for( i = numviaS; i <= alloc_viaS; i++ ){ viaArrayS[i] = NIL(char *) ; } } /* at this point safe to use vianame */ /* we need two mechanisms : viaid to vianame - use array */ /* and vianame to viaid - use balanced tree */ viaArrayS[numviaS] = Ystrclone( tokens[1] ) ; data = make_data2( tokens[2], tokens[3], tokens[1], VIA_T ) ; if( data ){ Yrbtree_insert( rule_treeS, data ) ; } if( numtokens == 5 ){ data = make_data( tokens[1], tokens[4], ASPECTLIM_T ) ; } else { /* set the default to 1.0 for aspect ratio limit */ data = make_data( tokens[1], "1.0", ASPECTLIM_T ) ; } if( data ) Yrbtree_insert( rule_treeS, data ) ; } else if( strncmp( tokens[0], "layer",5 ) == STRINGEQ && numtokens == 5 ){ if( ++numlayS >= alloc_layS ){ /* need to expand the number of layers allocated */ alloc_layS = numlayS + 3 ; layerArrayS = YVECTOR_REALLOC(layerArrayS,1,alloc_layS,char*); for( i = numlayS; i <= alloc_layS; i++ ){ layerArrayS[i] = NIL(char *) ; } } /* at this point safe to use layer */ /* we need two mechanisms : layerid to layername - use array */ /* and layername to layerid - use balanced tree */ layerArrayS[numlayS] = Ystrclone( tokens[1] ) ; data = make_data( tokens[1], (char *) numlayS, LAYER_T ) ; if( data ) Yrbtree_insert( rule_treeS, data ) ; /* store the values of res, cap, and routing preference */ data = make_data( tokens[1], tokens[2], RESISTANCE_T ) ; if( data ) Yrbtree_insert( rule_treeS, data ) ; data = make_data( tokens[1], tokens[3], CAPACITANCE_T ) ; if( data ) Yrbtree_insert( rule_treeS, data ) ; data = make_data( tokens[1], tokens[4], DIRECTION_T ) ; if( data ) Yrbtree_insert( rule_treeS, data ) ; } else if( strncmp( tokens[0], "overhang",8 ) == STRINGEQ && numtokens == 4 ){ data = make_data2( tokens[1], tokens[2], tokens[3], OVERHANG_T ) ; if( data ) Yrbtree_insert( rule_treeS, data ) ; } else { sprintf( YmsgG, "Unknown rule at line:%d in filename:%s\n", lineS, filename ) ; M( ERRMSG, "Yreadpar_init", YmsgG ) ; } }/* end processing of rule section */ } /* end while */ if(!(rule_section)){ rewind(fpS) ; lineS = 0 ; } } /* end Yreadpar_init */ char **Yreadpar_next( lineptr, line, numtokens, onNotOff, wildcard ) char **lineptr ; INT *line ; INT *numtokens ; BOOL *onNotOff ; BOOL *wildcard ; { PARAMPTR data ; char *bufferptr ; char **tokens ; BOOL rule_section ; if( filter_idS == UNKN || !(fpS) ){ /* don't read an unknown format */ return( NIL(char **) ) ; } /* assume that every option is on */ *onNotOff = TRUE ; rule_section = FALSE ; while( bufferptr = fgets( bufferS, LRECL, fpS )){ /* parse file */ lineS++ ; *line = lineS ; /* remove leading blanks */ bufferptr = Yremove_lblanks( bufferptr ) ; /* skip comments */ if( *bufferptr == COMMENT ){ continue ; } if( strncmp( bufferptr, "RULES", 5 ) == STRINGEQ ){ rule_section = TRUE ; /* skip over rules section */ continue ; } else if( strncmp( bufferptr, "ENDRULES", 8 ) == STRINGEQ ){ rule_section = FALSE ; /* skip over rules section */ continue ; } else if( rule_section ){ continue ; } *wildcard = FALSE ; strcpy( copy_bufferS, bufferptr ) ; *lineptr = copy_bufferS ; if( prog_idS == USER ){ bufferptr = Yremove_lblanks( bufferptr ) ; if( *bufferptr != WILDCARD ){ tokens = Ystrparser( bufferptr, "*\n", numtokens ) ; if( *numtokens == 2 ){ /* look for match for this program */ if( strcmp( tokens[0], filterNameS ) != STRINGEQ ){ /* go on to the next line */ if( prog_idS == USER ){ continue ; } } bufferptr = tokens[1] ; } else if( *numtokens == 0 ){ continue ; } else { sprintf( YmsgG, "Trouble parsing line:%d :\n\t%s\n", lineS, copy_bufferS ) ; M( ERRMSG, "Yreadpar_next", YmsgG ) ; continue ; } } else { /* WILDCARD skip over it */ *wildcard = TRUE ; bufferptr++ ; } } tokens = Ystrparser( bufferptr, " :\t\n", numtokens ) ; if( *numtokens > 1 ){ if( strcmp( tokens[*numtokens-1], "off" ) == STRINGEQ ){ /* we have turned this value off */ *onNotOff = FALSE ; } } return( tokens ) ; } TWCLOSE( fpS ) ; fpS = NIL( FILE * ) ; return( NIL(char **) ) ; } /* end Yreadpar_next */ static INT compare_parameter( key1, key2 ) PARAMPTR key1, key2 ; { return( (INT)strcmp( key1->parameter, key2->parameter ) ) ; } /* end compare */ YPARPTR Yreadpar_file() { PARAMPTR data ; YPARPTR store ; /* a tree with all the parameters */ char *lineptr ; char **tokens ; INT numtokens ; INT line ; INT i ; /* counter */ BOOL onNotOff ; BOOL wildcard ; store = (YPARPTR) NULL ; if( prog_idS == UNKN || !(fpS) ){ /* don't read an unknown format */ return( store ) ; } /* initialize a tree which store the data found in the *par file*/ YRBTREE_INIT( store, compare_parameter ); /* assume that every option is on */ while( tokens = Yreadpar_next( &lineptr, &line, &numtokens, &onNotOff, &wildcard )){ if( numtokens == 0 ){ continue ; } if( numtokens >= 2 ){ /* copy tokens for storing in a tree */ data = YMALLOC( 1, PARAM ) ; data->parameter = Ystrclone( tokens[0] ) ; data->program = filter_idS ; data->tokens = YMALLOC( numtokens-1, char * ) ; for( i = 1; i < numtokens ; i++ ){ data->tokens[i-1] = Ystrclone( tokens[i] ) ; } data->numtokens = numtokens - 1 ; /* save rest of line */ /* now write the tokens */ Yrbtree_insert( store, data ) ; } else { sprintf( YmsgG, "Trouble parsing line:%d :\n\t%s\n", line, lineptr ) ; M( ERRMSG, "Yreadpar_file", YmsgG ) ; continue ; } } /* end while loop */ TWCLOSE( fpS ) ; fpS = NIL( FILE * ) ; return( store ) ; } /* end Yreadpar_file */ char **Yreadpar_lookup( par_object, param, program, numtokens ) YPARPTR par_object ; /* parameter tree */ char *param ; /* parameter */ INT program ; /* program id */ INT *numtokens ; /* returns the number of tokens for parameter */ { PARAMPTR data ; /* store this in the tree */ PARAM key ; *numtokens = 0 ; key.parameter = param ; data = (PARAMPTR) Yrbtree_interval(par_object,&key,&key,TRUE) ; while( data ){ if( data->program == program ){ *numtokens = data->numtokens ; return( data->tokens ) ; } data = (PARAMPTR) Yrbtree_interval(par_object,&key,&key,FALSE) ; } /* if we get to this point we didn't find a match */ return( NIL(char **) ) ; } /* end Yreadpar_lookup */ DOUBLE Yreadpar_spacing( object1, object2 ) char *object1, *object2 ; { char key[LRECL] ; RULEPTR data ; RULEBOX data_buffer ; ERROR_CHECK(DOUBLE) ; /* first build the key */ sprintf( key, "%s/%s:%c", object1, object2, SPACING_T ) ; data_buffer.rule = key ; if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){ return( data->value.fvalue ) ; } else if( verboseS ){ sprintf( YmsgG, "Spacing for %s to %s not defined in the given design rules.\n", object1, object2 ); M( ERRMSG, "Yreadpar_spacing", YmsgG ) ; M( ERRMSG, NULL, "\tDefaulting to zero.\n\n" ) ; return( 0 ) ; } } /* end Yreadpar_spacing */ DOUBLE Yreadpar_width( object ) char *object ; { char key[LRECL] ; RULEPTR data ; RULEBOX data_buffer ; ERROR_CHECK(DOUBLE) ; /* first build the key */ sprintf( key, "%s:%c", object, WIDTH_T ) ; data_buffer.rule = key ; if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){ return( data->value.fvalue ) ; } else { sprintf( YmsgG, "Width for %s not defined in the given design rules.\n", object ); M( ERRMSG, "Yreadpar_width", YmsgG ) ; M( ERRMSG, NULL, "\tDefaulting to zero.\n\n" ) ; return( 0 ) ; } } /* end Yreadpar_spacing */ DOUBLE Yreadpar_pitch( object ) char *object ; { DOUBLE spacing ; DOUBLE width ; /* pitch for a given layer is spacing plus width */ ERROR_CHECK(DOUBLE) ; spacing = Yreadpar_spacing( object, object ) ; width = Yreadpar_width( object ) ; return( spacing + width ) ; } /* end Yreadpar_pitch */ DOUBLE Yreadpar_layer_res( object ) char *object ; { char key[LRECL] ; RULEPTR data ; RULEBOX data_buffer ; ERROR_CHECK(DOUBLE) ; /* first build the key */ sprintf( key, "%s:%c", object, RESISTANCE_T ) ; data_buffer.rule = key ; if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){ return( data->value.fvalue ) ; } else if( verboseS ){ sprintf( YmsgG, "Resistance for layer %s not defined in the given design rules.\n", object ); M( ERRMSG, "Yreadpar_layer_res", YmsgG ) ; M( ERRMSG, NULL, "\tDefaulting to zero.\n\n" ) ; return( 0 ) ; } } /* end Yreadpar_layer_res */ DOUBLE Yreadpar_layer_cap( object ) char *object ; { char key[LRECL] ; RULEPTR data ; RULEBOX data_buffer ; ERROR_CHECK(DOUBLE) ; /* first build the key */ sprintf( key, "%s:%c", object, CAPACITANCE_T ) ; data_buffer.rule = key ; if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){ return( data->value.fvalue ) ; } else if( verboseS ){ sprintf( YmsgG, "Capacitance for layer %s defined in the given design rules.\n", object ); M( ERRMSG, "Yreadpar_layer_cap", YmsgG ) ; M( ERRMSG, NULL, "\tDefaulting to zero.\n\n" ) ; return( (DOUBLE) 0.0 ) ; } } /* end Yreadpar_layer_cap */ BOOL Yreadpar_layer_HnotV( object ) char *object ; { char key[LRECL] ; char *keyptr ; RULEPTR data ; RULEBOX data_buffer ; ERROR_CHECK(BOOL) ; /* first build the key */ sprintf( key, "%s:%c", object, DIRECTION_T ) ; data_buffer.rule = key ; if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){ return( data->value.bvalue ) ; } else if( verboseS ){ sprintf( YmsgG, "Routing direction for layer %s defined in the given design rules.\n", object ); M( ERRMSG, "Yreadpar_layer_HnotV", YmsgG ) ; M( ERRMSG, NULL, "\tDefaulting to horizontal.\n\n" ) ; return( TRUE ) ; } } /* end Yreadpar_layer_HnotV */ INT Yreadpar_layer2id( object ) char *object ; { char key[LRECL] ; RULEPTR data ; RULEBOX data_buffer ; ERROR_CHECK(INT) ; /* first build the key */ sprintf( key, "%s:%c", object, LAYER_T ) ; data_buffer.rule = key ; if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){ return( data->value.ivalue ) ; } else if( verboseS ){ sprintf( YmsgG, "Routing layer %s not defined in the given design rules.\n", object ); M( ERRMSG, "Yreadpar_layer2id", YmsgG ) ; M( ERRMSG, NULL, "\tDefaulting to horizontal.\n\n" ) ; return( TRUE ) ; } } /* end Yreadpar_layer2id */ char *Yreadpar_id2layer( layerid ) INT layerid ; { ERROR_CHECK(char*) ; if( layerid > 0 && layerid <= numlayS ){ return( layerArrayS[layerid] ) ; } else { sprintf( YmsgG, "Layer id:%d is out of bounds. Numlayers = %d\n", layerid, numlayS ) ; M( ERRMSG, "Yreadpar_id2layer", YmsgG ) ; M( ERRMSG, NULL, "\tDefaulting to layer 1.\n\n" ) ; return( layerArrayS[1] ) ; } } /* end Yreadpar_id2layer */ INT Yreadpar_numlayers() { return( numlayS ) ; } /* end Yreadpar_numlayers */ char *Yreadpar_vianame( object1, object2 ) char *object1, *object2 ; { char key[LRECL] ; RULEPTR data ; RULEBOX data_buffer ; ERROR_CHECK(char*) ; /* first build the key */ data_buffer.rule = key ; /* make the key order the key alphabetically */ if( strcmp( object1, object2 ) <= STRINGEQ ){ sprintf( key, "%s/%s:%c", object1, object2, VIA_T ) ; } else { sprintf( key, "%s/%s:%c", object2, object1, VIA_T ) ; } if( data = (RULEPTR) Yrbtree_search( rule_treeS, (char *) &(data_buffer) ) ){ return( data->value.svalue ) ; } else if( verboseS ){ sprintf( YmsgG, "Could not find a via between layers %s and %s.\n", object1, object2 ); M( ERRMSG, "Yreadpar_vianame", YmsgG ) ; return( NIL(char *) ) ; } } /* end Yreadpar_vianame */ char *Yreadpar_viaId2name( viaid ) INT viaid ; { ERROR_CHECK(char*) ; if( viaid > 0 && viaid <= numviaS ){ return( viaArrayS[viaid] ) ; } else { sprintf( YmsgG, "Via id:%d is out of bounds. Numvias = %d\n", viaid, numviaS ) ; M( ERRMSG, "Yreadpar_viaId2name", YmsgG ) ; M( ERRMSG, NULL, "\tDefaulting to via id 1.\n\n" ) ; return( viaArrayS[1] ) ; } } /* end Yreadpar_viaId2name */ graywolf-0.1.4+20170307gite1bf319/src/date/000077500000000000000000000000001305746555600174705ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/src/date/CMakeLists.txt000066400000000000000000000000441305746555600222260ustar00rootroot00000000000000 add_executable(getdate getdate.c) graywolf-0.1.4+20170307gite1bf319/src/date/date.c000066400000000000000000000041061305746555600205520ustar00rootroot00000000000000/* * Copyright (C) 1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: date.c DESCRIPTION:Compile date stamp routine. This simple function stores the compile date of the program. DATE: Jan 29, 1988 REVISIONS: May 4, 1990 - now use static so we can look at compile date in object code. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) date.c version 1.2 5/12/90" ; #endif #include static char compileDate[] = DATE ; char *getCompileDate() { return( &(compileDate[27]) ) ; } /* end getCompileDate */ graywolf-0.1.4+20170307gite1bf319/src/date/getdate.c000066400000000000000000000047231305746555600212570ustar00rootroot00000000000000/* * Copyright (C) 1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #include #define LRECL 256 #define EOS '\0' #ifndef lint static char SccsId[] = "@(#) getdate.c version 1.2 5/12/90" ; #endif /* this small program creates a file called date.h */ /* which contains a define statement with the current time */ main( argc , argv ) int argc ; char *argv ; { FILE *fp ; char *date , buffer[LRECL] ; int len ; system("date > date.h") ; if( !(fp = fopen("date.h","r" ))){ printf("Could not reopen date.h"); exit(0) ; } rewind(fp) ; /* read line from system call */ date = fgets(buffer,LRECL,fp) ; fclose(fp) ; if( !(fp = fopen("date.h","w" ))){ printf("Could not open date.h"); exit(0) ; } if( date ){ /* get rid of newline character */ len = strlen( date ) ; date[len-1] = EOS ; fprintf(fp,"#define DATE \"@\(#\) Yale compilation date:%s\"\n",date); fclose(fp) ; exit(0) ; } /* errors - give unknown date */ fprintf(fp,"#define DATE \"@\(#\) Yale compilation date:unknown\"\n") ; fclose(fp) ; } /* end main */ graywolf-0.1.4+20170307gite1bf319/src/genrows/000077500000000000000000000000001305746555600202375ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/src/genrows/CMakeLists.txt000066400000000000000000000006031305746555600227760ustar00rootroot00000000000000 add_executable(genrows draw.c genrows.c main.c merge.c readpar.c ${CMAKE_SOURCE_DIR}/src/date/date.c) target_link_libraries(genrows ${CMAKE_BINARY_DIR}/src/Ylib/libycadgraywolf.so) target_link_libraries(genrows X11) target_link_libraries(genrows m) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include .) install(TARGETS genrows DESTINATION lib/graywolf/bin) graywolf-0.1.4+20170307gite1bf319/src/genrows/date.h000066400000000000000000000001071305746555600213230ustar00rootroot00000000000000#define DATE "@(#) Yale compilation date:Mon May 25 20:57:18 EDT 1992" graywolf-0.1.4+20170307gite1bf319/src/genrows/dialog.h000066400000000000000000000025471305746555600216570ustar00rootroot00000000000000static TWDIALOGBOX dialogS[40] = { 1,5,8," ACCEPT ",2,6,0, 1,25,8," CANCEL ",2,3,0, 2,15,9,"Tile Edit",0,3,0, 3,5,6,"Tile :",0,4,0, 4,5,6,"Left :",0,4,0, 5,5,6,"Bottom:",0,4,0, 6,5,6,"Right :",0,4,0, 7,5,6,"Top :",0,4,0, 9,5,10,"Legal Tile",3,4,9, 9,25,3,"YES",2,6,1, 9,31,2,"NO",2,3,1, 10,5,21,"Row Height :",0,4,0, 10,25,8," ",1,4,0, 11,5,21,"Max. No. of Rows :",0,4,0, 11,25,8," ",1,4,0, 12,5,21,"Number of Rows :",0,4,0, 12,25,8," ",1,4,2, 13,5,19,"Force No. of Rows :",3,4,17, 13,25,3,"YES",2,6,0, 13,31,2,"NO",2,3,0, 14,5,21,"Min. length of row:",0,4,0, 14,25,8," ",1,4,0, 15,5,21,"Start of row :",0,4,0, 15,25,8," ",1,4,0, 16,5,21,"End of row :",0,4,0, 16,25,8," ",1,4,0, 17,5,21,"Channel separation:",0,4,0, 17,25,8," ",1,4,0, 18,5,21,"Default Class :",0,4,0, 18,25,8," ",1,4,0, 19,5,19,"Mirror rows :",3,4,32, 19,25,3,"YES",2,6,3, 19,31,2,"NO",2,3,3, 21,1,35,"To change case fields put pointer",0,4,0, 22,1,35,"in window and click. To change",0,4,0, 23,1,35,"input fields put pointer in window",0,4,0, 24,1,35,"and back up over current contents",0,4,0, 25,1,35,"using the delete key. After modifying",0,4,0, 26,1,35,"the field, hit the return key.",0,4,0, 0,0,0,0,0,0,0 } ; graywolf-0.1.4+20170307gite1bf319/src/genrows/dialog2.h000066400000000000000000000013711305746555600217330ustar00rootroot00000000000000static TWDIALOGBOX row_dialogS[19] = { 1,5,8," ACCEPT ",2,6,0, 1,25,8," CANCEL ",2,3,0, 2,15,8,"Row Edit",0,3,0, 4,5,6,"Left :",0,4,0, 5,5,6,"Bottom :",0,4,0, 6,5,6,"Right :",0,4,0, 7,5,6,"Top :",0,4,0, 8,5,21,"Class :",0,4,0, 8,25,8," ",1,4,0, 9,5,19,"Mirror rows :",3,4,11, 9,25,3,"YES",2,6,1, 9,31,2,"NO",2,3,1, 11,1,35,"To change case fields put pointer",0,4,0, 12,1,35,"in window and click. To change",0,4,0, 13,1,35,"input fields put pointer in window",0,4,0, 14,1,35,"and back up over current contents",0,4,0, 15,1,35,"using the delete key. After modifying",0,4,0, 16,1,35,"the field, hit the return key.",0,4,0, 0,0,0,0,0,0,0 } ; graywolf-0.1.4+20170307gite1bf319/src/genrows/dialog3.h000066400000000000000000000036401305746555600217350ustar00rootroot00000000000000static TWDIALOGBOX macro_dialogS[29] = { 1,5,8," ACCEPT ",2,6,0, 1,25,8," CANCEL ",2,3,0, 2,15,9,"Macro Edit",0,3,0, 4,5,11,"Coordinates",0,4,0, 5,5,11,"-----------",0,2,0, 6,5,9,"X :",0,4,0, 6,25,8," ",1,4,0, 7,5,9,"Y :",0,4,0, 7,25,8," ",1,4,0, 8,5,9,"Delta X :",0,4,0, 8,25,8," ",1,4,0, 9,5,9,"Delta Y :",0,4,0, 9,25,8," ",1,4,0, 10,5,7,"Orient:",3,4,14, #ifndef TI 10,25,1,"0",2,4,1, 10,26,1,"1",2,4,1, 10,27,1,"2",2,4,1, 10,28,1,"3",2,4,1, 10,29,1,"4",2,4,1, 10,30,1,"5",2,4,1, 10,31,1,"6",2,4,1, 10,32,1,"7",2,4,1, #else /* the TI case */ 10,25,1,"1",2,4,1, 10,26,1,"2",2,4,1, 10,27,1,"3",2,4,1, 10,28,1,"4",2,4,1, 10,29,1,"5",2,4,1, 10,30,1,"6",2,4,1, 10,31,1,"7",2,4,1, 10,32,1,"8",2,4,1, #endif /* TI */ 13,1,35,"To change case fields put pointer",0,4,0, 14,1,35,"in window and click. To change",0,4,0, 15,1,35,"input fields put pointer in window",0,4,0, 16,1,35,"and back up over current contents",0,4,0, 17,1,35,"using the delete key. After modifying",0,4,0, 18,1,35,"the field, hit the return key.",0,4,0, 0,0,0,0,0,0,0 } ; #ifdef TI /* timberwolf to ice view translations */ INT tw2ice(orient) INT orient; { switch (orient){ case 0: return(1); case 1: return(7); case 2: return(5); case 3: return(3); case 4: return(8); case 5: return(6); case 6: return(2); case 7: return(4); } } INT ice2tw(orient) INT orient; { switch (orient){ case 1: return(0); case 2: return(6); case 3: return(3); case 4: return(7); case 5: return(2); case 6: return(5); case 7: return(1); case 8: return(4); } } /* end ice2tw */ #endif /* TI */ graywolf-0.1.4+20170307gite1bf319/src/genrows/draw.c000066400000000000000000001750161305746555600213520ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: draw.c DESCRIPTION:This file draw the data structures to the screen CONTENTS: initgraphics() DATE: Aug 9, 1989 REVISIONS: Feb 7, 1990 - took total row length out of procedure calls. Feb 28, 1990 - added tile dialog box. Sep 25, 1990 - added modify core area. Oct 14, 1990 - updated for new graphics. Oct 21, 1990 - fixed dialog boxes. Dec 7, 1990 - rewrote and reorganized graphics functions. Added merge functions, align function, set parameter menus. Also modified edit tile dialog box. Dec 15, 1990 - added divide tile and reset tiles. Dec 28, 1990 - added edit and align functions for macros. Also added divide tiles L/R. Mon Jan 7 18:21:05 CST 1991 - now announce presence of restart file. Also check for errors during read_vertices. Fri Jan 25 17:50:54 PST 1991 - added mirror row feature. Sat Jan 26 16:24:18 PST 1991 - made feeds a double and moved force rows to a call in main.c Sat Feb 23 00:32:10 EST 1991 - disallow macro moves during partitioning. Tue Mar 12 16:52:19 CST 1991 - added numrows function. Thu Apr 18 00:57:25 EDT 1991 - now genrows can rotate macros. Sun Apr 21 21:48:10 EDT 1991 - fixed problem with macro orientation and now follow control menu convention. Sat Sep 21 15:37:36 EDT 1991 - added memory capability. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) draw.c (Yale) version 3.22 5/14/92" ; #endif #include #include #include #include #ifndef NOGRAPHICS #define MENUP "genrows_menu" #include #include #include #include #include #include #define FCOLOR TWYELLOW static BOOL auto_drawS=TRUE ;/* whether to draw immediately after exp.*/ static BOOL drawLabelS=FALSE ; /* whether to draw labels */ static BOOL drawTileS=TRUE ; /* whether to draw tiles */ static BOOL drawMacroS=TRUE ; /* whether to draw macros */ static BOOL drawRowS=TRUE ; /* whether to draw stdcell rows */ static BOOL drawOrientS=FALSE ; /* whether to draw macro orientation label */ static BOOL selectMacroS = 0 ; /* current chosen macro */ static TILE_BOX *selected_tileS = NULL ;/* current chosen tile */ static ROW_BOX *selected_rowS = NULL ;/* current chosen row */ /* #define DEVELOPMENU */ /* During development use TWread_menus in place of menuS */ /* to create menu record, ie. TWread_menus(MENUP) */ #ifdef DEVELOPMENU #define MENU TWread_menus(MENUP) #else #define MENU menuS #endif /* #define DEVELOPDIALOG */ #ifndef DEVELOPDIALOG #include #include #include #else static TWDIALOGPTR dialogS ; static TWDIALOGPTR row_dialogS ; static TWDIALOGPTR macro_dialogS ; #endif #include static draw_tile(); static draw_macro(); static draw_fs(); static last_chance(); static no_move_message(); static save_for_do(); static update_macro(); static graphics_dump(); static INT pick_macro(); static TILE_BOX *pick_tile(); static ROW_BOX *pick_row(); static BOOL edit_tiles(); static edit_macro(); static update_vertices(); static rotate_vertices(); static find_nearest_corner(); static highlight_corner(); static outm(); initgraphics( argc, argv, windowId ) INT argc, windowId ; char *argv[] ; { char *host ; char *Ygetenv() ; extern INT draw_the_data() ; if( !(graphicsG) ){ return ; } /* we need to find host for display */ if(!(TWcheckServer() )){ M(MSG,NULL, "Aborting graphics...\n\n" ) ; graphicsG = FALSE ; return ; } if( windowId ){ /* init windows as a parasite */ if( !( TWinitParasite(argc,argv,TWnumcolors(), TWstdcolors(),FALSE,MENU, draw_the_data, windowId ))){ M(ERRMSG,"initgraphics","Aborting graphics."); graphicsG = FALSE ; return ; } } else { /* init window as a master */ if(!(TWinitGraphics(argc,argv,TWnumcolors(),TWstdcolors(), FALSE,MENU, draw_the_data ))){ M(ERRMSG,"initgraphics","Aborting graphics."); graphicsG = FALSE ; return ; } } TWsetMode(0) ; TWsetwindow( 0, 0, 10, 10 ) ; TWdrawMenus() ; TWflushFrame() ; } /* end initgraphics */ /* how to draw the data */ INT draw_the_data() { INT i ; /* counter */ INT l, b, r, t ; /* core dimensions */ INT color ; /* current color */ INT macro ; /* current macro */ char label[LRECL] ; /* make a label buffer */ char *labelptr ; /* pointer to current label */ TILE_BOX *tileptr ; /* current tile */ ROW_BOX *rowptr ; /* current row being output */ ROW_BOX *segment ; /* current segment being output */ ROW_BOX *get_rowptr(); /* get data structure */ if( !(graphicsG) ){ return ; } /* initialize screen */ TWstartFrame() ; /**** draw the MC calculated core *******/ get_core( &l, &b, &r, &t, FALSE ) ; TWdrawCell( 0, l, b, r, t, TWWHITE, NULL ) ; /**** draw the tiles *******/ if( drawTileS ){ /* draw all but last tile */ for( tileptr=tile_listG;tileptr->next;tileptr=tileptr->next ){ draw_tile( tileptr ) ; } } /**** draw the rows *******/ if( drawRowS ){ for( rowptr=get_rowptr();rowptr;rowptr=rowptr->next_row ){ if( rowptr->class ){ sprintf( label, "SEGMENT:%d CLASS:%d", rowptr->seg, rowptr->class); } else { sprintf( label, "SEGMENT:%d CLASS:1", rowptr->seg ) ; } if( rowptr->mirror ){ strcat( label, " MIRROR" ) ; } if( drawLabelS ){ labelptr = label ; } else { labelptr = NULL ; } if( feeds_per_segG > 0 ){ if( rowptr->next_segment ){ /* means we have more that one segment to row */ for( segment=rowptr;segment;segment=segment->next_segment){ if( segment->class ){ sprintf( label, "SEGMENT:%d CLASS:%d", segment->seg, segment->class); } else { sprintf( label, "SEGMENT:%d CLASS:1", segment->seg ) ; } if( rowptr->mirror ){ strcat( label, " MIRROR" ) ; } if( drawLabelS ){ labelptr = label ; } else { labelptr = NULL ; } r = segment->urx - feeds_per_segG ; if( r > segment->llx ){ /* make sure we have two valid segments */ TWdrawCell( segment->seg, segment->llx, segment->lly, r, segment->ury, TWBLUE, labelptr ) ; TWdrawCell( segment->seg, r, segment->lly, segment->urx, segment->ury, TWYELLOW, NULL ) ; } else { TWdrawCell( segment->seg, segment->llx, segment->lly, segment->urx, segment->ury, TWBLUE, labelptr ) ; } if( segment == selected_rowS ){ TWdrawCell( segment->seg, segment->llx, segment->lly, segment->urx, segment->ury, TWVIOLET, labelptr ) ; } } /* end for loop */ } else { r = rowptr->urx - feeds_per_segG ; if( r > rowptr->llx ){ /* make sure we have two valid segments */ TWdrawCell( rowptr->seg, rowptr->llx, rowptr->lly, r, rowptr->ury, TWBLUE, labelptr ) ; TWdrawCell( rowptr->seg, r, rowptr->lly, rowptr->urx, rowptr->ury, TWYELLOW, NULL ) ; } else { TWdrawCell( rowptr->seg, rowptr->llx, rowptr->lly, rowptr->urx, rowptr->ury, TWBLUE, labelptr ) ; } if( rowptr == selected_rowS ){ TWdrawCell( rowptr->seg, rowptr->llx, rowptr->lly, rowptr->urx, rowptr->ury, TWVIOLET, labelptr ) ; } } } else { if( rowptr->next_segment ){ /* means we have more that one segment to row */ for( segment=rowptr;segment;segment=segment->next_segment){ if( segment->class ){ sprintf( label, "SEGMENT:%d CLASS:%d", segment->seg, segment->class); } else { sprintf( label, "SEGMENT:%d CLASS:1", segment->seg ) ; } if( rowptr->mirror ){ strcat( label, " MIRROR" ) ; } TWdrawCell( segment->seg, segment->llx, segment->lly, segment->urx, segment->ury, TWBLUE, labelptr ) ; if( segment == selected_rowS ){ TWdrawCell( segment->seg, segment->llx, segment->lly, segment->urx, segment->ury, TWVIOLET, labelptr ) ; } } /* end for loop */ } else { TWdrawCell( rowptr->seg, rowptr->llx, rowptr->lly, rowptr->urx, rowptr->ury, TWBLUE, labelptr ) ; if( rowptr == selected_rowS ){ TWdrawCell( rowptr->seg, rowptr->llx, rowptr->lly, rowptr->urx, rowptr->ury, TWVIOLET, labelptr ) ; } } } } /* end for loop */ } /* end drawRowS */ if( drawMacroS ){ for( macro = 1; macro <= num_macrosG; macro++ ){ draw_macro( macro, TWORANGE ) ; } } if( selectMacroS ){ draw_macro( selectMacroS, TWVIOLET ) ; } /* FLUSH OUTPUT BUFFER */ TWflushFrame() ; } /* end draw_the_data */ /* ***************************************************************** */ static draw_tile( tileptr ) TILE_BOX *tileptr ; /* current tile */ { INT color ; /* current color */ char label[LRECL] ; /* make a label buffer */ char *labelptr ; /* pointer to current label */ if( drawLabelS ){ sprintf( label, "TILE:%d", tileptr->name ) ; labelptr = label ; } else { labelptr = NULL ; } /* determine color base on legality */ if( tileptr == selected_tileS ){ color = TWVIOLET ; } else if( tileptr->illegal ){ color = TWRED ; } else { color = TWGREEN ; } TWdrawCell( tileptr->name, tileptr->llx , tileptr->lly , tileptr->urx , tileptr->ury, color, labelptr ) ; } /* end draw_tile */ static draw_macro( macro, color ) INT macro ; INT color ; { INT i ; char *labelptr ; /* name of cell */ char label[LRECL] ; /* buffer for name */ VERTEXPTR *vptr ; /* current vertex array */ VERTEXPTR pt_ptr ; /* current point */ MACROPTR mptr ; /* current macro */ mptr = macroArrayG[macro] ; vptr = mptr->vertices ; TWarb_init() ; for( i = 0 ; i < mptr->num_vertices ; i++ ) { pt_ptr = vptr[i] ; TWarb_addpt( pt_ptr->x, pt_ptr->y ) ; D( "genrows/macropts", sprintf( label, "%d", i ) ; TWdrawString( pt_ptr->x, pt_ptr->y, TWRED, label ) ; ) ; } if( drawLabelS ){ sprintf( label, "C:%d", macro ) ; labelptr = label ; } else { labelptr = NULL ; } TWdrawArb( macro, color, labelptr ) ; if( drawOrientS ){ draw_fs( mptr ) ; } } /* end draw_macro */ static draw_fs( mptr ) MACROPTR mptr ; /* current macro */ { INT i ; /* counter */ INT x[10], y[10] ; /* only 10 points to an F */ INT l, b, r, t ; /* bounding box points */ VERTEXPTR pt_ptr ; /* current point */ VERTEXPTR *vptr ; /* current vertex array */ INT xout, yout ; /* rotated points */ INT wid ; /* with of the F */ INT pt ; /* point counter */ INT xc, yc ; /* center of cell */ l = INT_MAX ; b = INT_MAX ; r = INT_MIN ; t = INT_MIN ; vptr = mptr->vertices ; xc = mptr->xcenter ; yc = mptr->ycenter ; for( i = 0 ; i < mptr->num_vertices ; i++ ) { pt_ptr = vptr[i] ; if( mptr->orient <= 3 ){ l = MIN( l, pt_ptr->x - xc ) ; b = MIN( b, pt_ptr->y - yc ) ; r = MAX( r, pt_ptr->x - xc ) ; t = MAX( t, pt_ptr->y - yc ) ; } else { /* opposite aspect ratio */ l = MIN( l, pt_ptr->y - yc ) ; b = MIN( b, pt_ptr->x - xc ) ; r = MAX( r, pt_ptr->y - yc ) ; t = MAX( t, pt_ptr->x - xc ) ; } } wid = (INT) (0.25 * (DOUBLE)( t - b ) ) ; /* now set the points */ x[0] = l ; y[0] = b ; x[1] = l ; y[1] = t ; x[2] = r ; y[2] = t ; x[3] = r ; y[3] = t - wid ; x[4] = l + wid ; y[4] = y[3] ; x[5] = x[4] ; y[5] = y[4] - wid ; x[6] = l + 2*wid ; y[6] = y[5] ; x[7] = x[6] ; y[7] = y[6] - wid ; x[8] = x[5] ; y[8] = y[7] ; x[9] = x[4] ; y[9] = b ; TWarb_init() ; for( pt = 0; pt <= 9; pt++ ){ /* rel position is a macro which calculates */ /* absolute pin loc - defined in relpos.h */ REL_POS( mptr->orient, xout, yout, /* result */ x[pt], y[pt], /* cell relative */ xc, yc ) ; /* cell center */ TWarb_addpt( xout, yout ) ; } TWdrawArb( 0, FCOLOR, NULL ) ; } /* end draw_fs */ /* set the size of the graphics window */ setGraphicWindow() { INT l, b, r, t ; INT expand ; get_core( &l, &b, &r, &t, TRUE ) ; expand = (int) (0.10 * (DOUBLE) (r - l) ) ; expand = MAX( expand, (int) (0.10 * (DOUBLE) (t - b) ) ) ; l -= expand ; r += expand ; b -= expand ; t += expand ; TWsetwindow( l, b, r, t ) ; } /* end draw_changraph */ /* ***************************************************************** USER INTERFACE */ /* heart of the graphic system processes user input */ void process_graphics() { INT x1, y1, x2, y2 ; /* coordinates for fixing cells and neighhds */ INT x, y ; /* coordinates from pointer */ INT i ; /* temp variable */ INT rows ; /* number of stdcell rows */ INT net ; /* net for minimum spanning tree */ INT selection ; /* the users pick */ INT temp ; /* temporary variable for atoi calc */ INT minlength ; /* minimum length of a tile */ DOUBLE tempf ; /* user reply transformed to float */ /* static INT pick_macro(); */ /* get macro from user */ INT pick_macro(); /* get macro from user */ char *reply ; /* user reply to a querry */ char filename[LRECL];/* file name */ BOOL ok ; /* loop until this value is true */ BOOL save_memory ; /* save the memory state */ FILE *fp ; /* restore file */ TILE_BOX *tile ; /* traverse list of tiles */ /* static TILE_BOX *pick_tile() ; */ /* used to pick a tile */ TILE_BOX *pick_tile() ; /* used to pick a tile */ TILE_BOX *cur_tile ; /* currently lit up tile */ /* static ROW_BOX *pick_row() ; */ /* used to pick a row */ ROW_BOX *pick_row() ; /* used to pick a row */ sprintf( filename, "%s.gsav", cktNameG ) ; if( YfileExists( filename) ){ sprintf( YmsgG, "Note: restore state file exists:%s\n\n", cktNameG ) ; M( MSG, NULL, YmsgG ) ; } /* data might have changed so show user current config */ /* any function other that the draw controls need to worry about */ /* this concurrency problem - show user current config */ setGraphicWindow() ; draw_the_data() ; /* use TWcheckExposure to flush exposure events since we just */ /* drew the data */ TWcheckExposure() ; if(!(wait_for_userG)){ if (last_chanceG) { wait_for_userG = TRUE ; last_chance() ; } return; } TWmessage( "Genrows is waiting for your response..." ) ; selection = CANCEL ; while( selection != CONTINUE_PGM ){ /* loop until exit */ selection = TWcheckMouse() ; switch( selection ){ case CANCEL: /* do nothing */ break ; case AUTO_REDRAW_ON: auto_drawS = TRUE ; break ; case AUTO_REDRAW_OFF: auto_drawS = FALSE ; break ; case CLOSE_GRAPHICS: if( invalidG ){ TWmessage( "ERROR:you may not quit graphics since errors exist"); selection = CANCEL ; break ; } else { TWcloseGraphics() ; /* update all costs and reload cells */ return ; } case COLORS: TWtoggleColors() ; break ; case CONTINUE_PGM: if( invalidG ){ TWmessage( "ERROR:you may not continue since errors exist" ) ; selection = CANCEL ; } break ; case DUMP_GRAPHICS: graphics_dump() ; break ; case FULLVIEW: TWfullView() ; break ; case REDRAW: draw_the_data() ; /* use TWcheckExposure to flush exposure events since */ /* we just drew the data */ TWcheckExposure() ; break ; case TELL_POINT: TWmessage( "Pick a point" ) ; TWgetPt( &x, &y ) ; sprintf( YmsgG,"The point is (%d,%d)",x,y ) ; TWmessage( YmsgG ) ; break ; case TRANSLATE: TWtranslate() ; break ; case ZOOM: TWzoom() ; break ; case ALIGN_MACRO_IN_X: if( noMacroMoveG ){ no_move_message() ; break ; } if(!(selectMacroS = pick_macro( "Select the reference macro by clicking any mouse button in cell center"))){ break ; } draw_macro( selectMacroS, TWVIOLET ) ; TWmessage( "Now pick the reference corner|center for alignment" ) ; TWgetPt2( &x, &y ) ; find_nearest_corner( selectMacroS, x, y, &x1, &y1 ) ; highlight_corner( selectMacroS, x1, y1 ) ; if(!(selectMacroS = pick_macro( "Select the macro to be aligned by clicking any mouse button in cell center"))){ break ; } draw_macro( selectMacroS, TWVIOLET ) ; TWmessage( "Now pick the corner|center you wish to align" ) ; TWgetPt2( &x, &y ) ; find_nearest_corner( selectMacroS, x, y, &x2, &y2 ) ; highlight_corner( selectMacroS, x2, y2 ) ; if( x1 == x2 ){ /* no work to be done */ draw_the_data() ; TWcheckExposure() ; break ; } save_for_do( UNDO ) ; /* calculate the new center of the macro */ x = macroArrayG[selectMacroS]->xcenter + x1 - x2 ; y = macroArrayG[selectMacroS]->ycenter ; update_vertices( selectMacroS, x, y ) ; update_macro() ; break ; case ALIGN_MACRO_IN_Y: if( noMacroMoveG ){ no_move_message() ; break ; } if(!(selectMacroS = pick_macro( "Select the reference macro by clicking any mouse button in cell center"))){ break ; } draw_macro( selectMacroS, TWVIOLET ) ; TWmessage( "Now pick the reference corner|center for alignment" ) ; TWgetPt2( &x, &y ) ; find_nearest_corner( selectMacroS, x, y, &x1, &y1 ) ; highlight_corner( selectMacroS, x1, y1 ) ; if(!(selectMacroS = pick_macro( "Select the macro to be aligned by clicking any mouse button in cell center"))){ break ; } draw_macro( selectMacroS, TWVIOLET ) ; TWmessage( "Now pick the corner|center you wish to align" ) ; TWgetPt2( &x, &y ) ; find_nearest_corner( selectMacroS, x, y, &x2, &y2 ) ; highlight_corner( selectMacroS, x2, y2 ) ; if( y1 == y2 ){ /* no work to be done */ draw_the_data() ; TWcheckExposure() ; break ; } save_for_do( UNDO ) ; /* calculate the new center of the macro */ x = macroArrayG[selectMacroS]->xcenter ; y = macroArrayG[selectMacroS]->ycenter + y1 - y2 ; update_vertices( selectMacroS, x, y ) ; update_macro() ; break ; case ALIGN_ROWS: save_for_do( UNDO ) ; selected_tileS = pick_tile( "Pick reference tile whose row separation is desired") ; if( selected_tileS == 0 ){ break ; } temp = selected_tileS->channel_separation ; draw_tile( selected_tileS ) ; /* show user which tile selected */ selected_tileS = pick_tile( "Pick destination tile whose rows need to be aligned") ; if( selected_tileS == 0 ){ draw_the_data() ; TWcheckExposure() ; break ; } draw_tile( selected_tileS ) ; /* show user which tile selected */ selected_tileS->channel_separation = temp ; selected_tileS = NULL ; remakerows() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case EDIT_ROW: if( shortRowG ){ TWmessage( "You cannot edit row in KEEP SHORT ROW mode") ; break ; } selected_rowS = pick_row() ; if(!(selected_rowS)){ break ; } save_for_do( UNDO ) ; draw_the_data() ; /* show user which row is selected */ edit_row( selected_rowS ) ; selected_rowS = NULL ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case EDIT_MACRO: if( noMacroMoveG ){ no_move_message() ; break ; } if(!(selectMacroS = pick_macro(NULL) )){ break ; } draw_macro( selectMacroS, TWVIOLET ) ; TWmessage( "Now pick the reference corner|center" ) ; TWgetPt2( &x, &y ) ; find_nearest_corner( selectMacroS, x, y, &x1, &y1 ) ; highlight_corner( selectMacroS, x1, y1 ) ; save_for_do( UNDO ) ; edit_macro( selectMacroS, x1, y1 ) ; update_macro() ; break ; case EDIT_TILE: selected_tileS = pick_tile(NULL) ; if( selected_tileS == 0 ){ break ; } save_for_do( UNDO ) ; draw_tile( selected_tileS ) ; /* show user which tile selected */ if(!(edit_tiles( selected_tileS))){ /* nothing changed so don't do any work */ cur_tile = selected_tileS ; selected_tileS = NULL ;/* turn off tile */ draw_tile( cur_tile ) ; break ; } selected_tileS = NULL ; remakerows() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case KEEP_SHORT_ROW: shortRowG = TRUE ; TWmessage( "Genrows will keep short row" ) ; remakerows() ; draw_the_data() ; TWcheckExposure() ; break ; case DISCARD_SHORT_ROW: TWmessage( "Genrows will discard short row and round up if possible" ) ; shortRowG = FALSE ; remakerows() ; draw_the_data() ; TWcheckExposure() ; break ; case MODIFY_CORE_AREA: if( noMacroMoveG ){ no_move_message() ; break ; } TWmessage( "Pick or enter bottom left corner of core area:" ) ; TWgetPt2( &x, &y ) ; TWmessage( "Pick or enter upper right corner of core area:" ) ; TWgetPt2( &x1, &y1 ) ; if( x1 <= x ){ TWmessage("ERROR:x coordinates invalid - ignored" ) ; break ; } if( y1 <= y ){ TWmessage("ERROR:y coordinates invalid - ignored" ) ; break ; } save_for_do( UNDO ) ; set_core( x, x1, y, y1 ) ; /* now we need to redo all the work we have done before */ start_tileG = NULL; recalculate(TRUE) ; /* free data */ remakerows() ; draw_the_data() ; get_core( &x, &y, &x1, &y1, FALSE ) ; sprintf( YmsgG, "Core is now llx:(%d,%d) urx:(%d,%d)", x, y, x1, y1 ) ; TWmessage( YmsgG ) ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case MOVE_MACRO: if( noMacroMoveG ){ no_move_message() ; break ; } if(!(selectMacroS = pick_macro(NULL) )){ break ; } save_for_do( UNDO ) ; TWmessage( "Pick or enter a reference point relative to cell center:" ) ; if( TWgetPt2( &x, &y ) ){ /* we know from keyboard */ TWmessage( "Enter new position x, y:" ) ; TWgetPt( &x1, &y1 ) ; update_vertices( selectMacroS, x1 - x, y1 - y ) ; } else { /* from mouse */ TWmessage( "Pick new position with mouse" ) ; /* get old position of cell */ get_global_pos( selectMacroS, &x1, &y1, &x2, &y2 ) ; TWmoveRect( &x1, &y1, &x2, &y2, x, y ) ; /* calculate new position for cell */ update_vertices( selectMacroS, (x1+x2)/2,(y1+y2)/2 ); } update_macro() ; break ; case NUMROWS: if( noMacroMoveG ){ no_move_message() ; break ; } if( num_macrosG != 0 ){ TWmessage( "Number of rows may not be set since macros exist") ; break ; } save_for_do( UNDO ) ; do { if( reply = TWgetString("Enter the number of rows: ")){ num_rowsG = atoi(reply) ; if( num_rowsG <= 0 ){ TWmessage( "Number of row may not be <= 0" ) ; (void) sleep( (unsigned) 2) ; } } } while( num_rowsG <= 0 ) ; save_memory = memoryG ; memoryG = FALSE ; calculate_numrows() ; setGraphicWindow() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; memoryG = save_memory ; break ; case REDO: sprintf( filename, "%s.redo", cktNameG ) ; fp = TWOPEN( filename, "r", NOABORT ) ; if(!fp){ outm(ERRMSG,"save_state", "could not redo command" ) ; break ; } if(!(read_vertices(fp,FALSE))){ break ; } start_tileG = NULL; recalculate(FALSE) ; /* don't free data */ if( restore_state(fp) ){ remakerows() ; draw_the_data() ; TWcheckExposure() ; } TWCLOSE( fp ) ; break ; case RESTORE_STATE: do { reply = TWgetString("Enter restore file name: ") ; } while(!(reply)) ; sprintf( filename, "%s.gsav", reply ) ; fp = TWOPEN( filename, "r", NOABORT ) ; if(!fp){ sprintf( YmsgG, "ERROR:could not open file:%s", filename ) ; outm(ERRMSG,"save_state", YmsgG ) ; break ; } if(!(read_vertices(fp,FALSE))){ break ; } start_tileG = NULL; recalculate(FALSE) ; /* don't free data */ if( restore_state(fp) ){ remakerows() ; setGraphicWindow() ; draw_the_data() ; TWcheckExposure() ; } TWCLOSE( fp ) ; break ; case SAVE_STATE: do { reply = TWgetString("Enter file name for save file: ") ; } while(!(reply)) ; sprintf( filename, "%s.gsav", reply ) ; fp = TWOPEN( filename, "w", NOABORT ) ; if(!fp){ sprintf( YmsgG, "ERROR:could not open file:%s", filename ) ; outm(ERRMSG,"save_state", YmsgG ) ; break ; } save_state(fp) ; TWCLOSE( fp ) ; sprintf( YmsgG, "Genrows saved state:%s", reply ) ; TWmessage( YmsgG ) ; break ; case UNDO: sprintf( filename, "%s.undo", cktNameG ) ; fp = TWOPEN( filename, "r", NOABORT ) ; if(!fp){ outm(ERRMSG,"save_state", "could not undo command" ) ; break ; } if(!(read_vertices(fp,FALSE))){ break ; } start_tileG = NULL; recalculate(FALSE) ; /* don't free data */ if( restore_state(fp) ){ remakerows() ; draw_the_data() ; TWcheckExposure() ; } TWCLOSE( fp ) ; break ; case DIVIDE_TILE_LEFT_RIGHT: selected_tileS = pick_tile(NULL) ; if( selected_tileS == 0 ){ break ; } save_for_do( UNDO ) ; draw_tile( selected_tileS ) ; /* show user which tile selected */ TWmessage( "Now pick the division point for the tile"); do { ok = FALSE ; TWgetPt2( &x, &y ) ; if( x<=selected_tileS->llx || x>=selected_tileS->urx ){ TWmessage("Division line outside tile - pick again" ) ; } else { ok = TRUE ; } } while(!(ok)) ; divide_tilelr( selected_tileS , x ) ; renumber_tiles() ; remakerows() ; selected_tileS = NULL; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case DIVIDE_TILE_UP_DOWN: selected_tileS = pick_tile(NULL) ; if( selected_tileS == 0 ){ break ; } save_for_do( UNDO ) ; draw_tile( selected_tileS ) ; /* show user which tile selected */ TWmessage( "Now pick the division point for the tile"); do { ok = FALSE ; TWgetPt2( &x, &y ) ; if( y<=selected_tileS->lly || y>=selected_tileS->ury ){ TWmessage("Division line outside tile pick again" ) ; } else { ok = TRUE ; } } while(!(ok)) ; divide_tile( selected_tileS , y ) ; renumber_tiles() ; remakerows() ; selected_tileS = NULL; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case LIMIT_MERGES: limitMergeG = TRUE ; TWmessage( "Merges will be limited to immediate neighbors"); break ; case UNLIMIT_MERGES: limitMergeG = FALSE ; TWmessage( "Maximum possible merges from a tile will be performed" ); break ; case MERGE_DOWNWARD: selected_tileS = pick_tile(NULL) ; if( selected_tileS == 0 ){ break ; } save_for_do( UNDO ) ; draw_tile( selected_tileS ) ; /* show user which tile selected */ TWflushFrame() ; (void) sleep( (unsigned) 2) ; merge_downward( selected_tileS ) ; renumber_tiles() ; selected_tileS = NULL ; remakerows() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case MERGE_LEFT: selected_tileS = pick_tile(NULL) ; if( selected_tileS == 0 ){ break ; } save_for_do( UNDO ) ; draw_tile( selected_tileS ) ; /* show user which tile selected */ TWflushFrame() ; (void) sleep( (unsigned) 2) ; merge_left( selected_tileS ) ; renumber_tiles() ; selected_tileS = NULL ; remakerows() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case MERGE_RIGHT: selected_tileS = pick_tile(NULL) ; if( selected_tileS == 0 ){ break ; } save_for_do( UNDO ) ; draw_tile( selected_tileS ) ; /* show user which tile selected */ TWflushFrame() ; (void) sleep( (unsigned) 2) ; merge_right( selected_tileS ) ; renumber_tiles() ; selected_tileS = NULL ; remakerows() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case MERGE_UPWARD: selected_tileS = pick_tile(NULL) ; if( selected_tileS == 0 ){ break ; } save_for_do( UNDO ) ; draw_tile( selected_tileS ) ; /* show user which tile selected */ TWflushFrame() ; (void) sleep( (unsigned) 2) ; merge_upward( selected_tileS ) ; renumber_tiles() ; selected_tileS = NULL ; remakerows() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case RESET_TILES: save_for_do( UNDO ) ; save_memory = memoryG ; memoryG = FALSE ; /* redo all the work we have done before */ recalculate(TRUE) ; /* free data */ remakerows() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; memoryG = save_memory ; break ; case DRAW_LABELS: drawLabelS = TRUE ; TWforceRedraw() ; break ; case IGNORE_LABELS: drawLabelS = FALSE ; TWforceRedraw() ; break ; case DRAW_ORIENT: drawOrientS = TRUE ; TWforceRedraw() ; break ; case IGNORE_ORIENT: drawOrientS = FALSE ; TWforceRedraw() ; break ; case DRAW_MACROS: drawMacroS = TRUE ; TWforceRedraw() ; break ; case IGNORE_MACROS: drawMacroS = FALSE ; TWforceRedraw() ; break ; case DRAW_ROWS: drawRowS = TRUE ; TWforceRedraw() ; break ; case IGNORE_ROWS: drawRowS = FALSE ; TWforceRedraw() ; break ; case DRAW_TILES: drawTileS = TRUE ; TWforceRedraw() ; break ; case IGNORE_TILES: drawTileS = FALSE ; TWforceRedraw() ; break ; case FEED_PERCENTAGE: save_for_do( UNDO ) ; ok = FALSE ; while(!(ok)){ if( reply = TWgetString( "Enter feed ratio in percentage [0-100]: " )){ tempf = atof( reply ) ; if( tempf >= 0.0 ){ ok = TRUE ; } } } set_feed_length( tempf ) ; remakerows() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case MIN_ROW_LENGTH: save_for_do( UNDO ) ; ok = FALSE ; while(!(ok)){ if( reply = TWgetString( "Enter minimum valid row length: " )){ temp = atoi( reply ) ; if( temp >= 0 ){ ok = TRUE ; set_minimum_length( temp ) ; } else { outm( ERRMSG, "reset_min_row_length", "Invalid minimum row length. Must be >= 0" ) ; } } } remakerows() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case ROW_SEPARATION: save_for_do( UNDO ) ; ok = FALSE ; while(!(ok)){ if( reply = TWgetString( "Enter row separation [1.0 nominal]:" )){ tempf = atof( reply ) ; if( tempf > 0.0 ){ ok = TRUE ; set_row_separation( tempf, 0.0 ) ; } else { outm( ERRMSG, "reset_row_separation", "Invalid row separation. Must be > 0.0" ) ; } } } remakerows() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case SET_SPACING: save_for_do( UNDO ) ; ok = FALSE ; while(!(ok)){ if( reply = TWgetString( "Enter spacing between row and tile edge: " )){ temp = atoi( reply ) ; if( temp >= 0 ){ ok = TRUE ; spacingG = temp ; set_spacing() ; } else { outm( ERRMSG, "set_spacing", "Invalid space. Must be >= 0" ) ; } } } remakerows() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; break ; case MEMORY_ON: memoryG = TRUE ; TWmessage("Genrows will try to remember the last state" ) ; break ; case MEMORY_OFF: memoryG = FALSE ; TWmessage("Genrow's memory has been turned off" ) ; break ; } /*********************** end graphics SWITCH *****************/ if( auto_drawS && TWcheckExposure() ){ draw_the_data() ; } } if( shortRowG ){ TWmessage( "Now forcing removal of short row") ; shortRowG = FALSE ; remakerows() ; draw_the_data() ; if (last_chanceG) (VOID)last_chance() ; } } /* end process_graphics */ static last_chance() { INT i ; /* counter */ (void) sleep( (unsigned) 1 ) ; TWmessage( "If you wish to modify the rows, you have 10 secs. to click on top menu") ; for( i = 1; i <= 10; i++ ){ (void) sleep( (unsigned) 1 ) ; if( TWinterupt() ){ TWmessage( "Please reconfigure the rows" ) ; (void) sleep( (unsigned) 1 ) ; process_graphics() ; break ; } } } /* end last_chance */ static no_move_message() { TWmessage("Macro moves/core changes not allowed in partitioning"); } static save_for_do( save ) INT save ; { char filename[LRECL] ; FILE *fp ; if( save == UNDO ){ sprintf( filename, "%s.undo", cktNameG ) ; } else if( save == REDO ){ sprintf( filename, "%s.redo", cktNameG ) ; } fp = TWOPEN( filename, "w", ABORT ) ; save_state(fp) ; TWCLOSE( fp ) ; } /* end undo */ static update_macro() { char filename[LRECL] ; FILE *fp ; /* this is the easiest way to redo entire algorithm from scratch */ sprintf( filename, "%s.tmp", cktNameG ) ; fp = TWOPEN( filename, "w", ABORT ) ; save_state(fp) ; TWCLOSE( fp ) ; fp = TWOPEN( filename, "r", ABORT ) ; if(!(read_vertices(fp,FALSE))){ return ; } start_tileG = NULL; selectMacroS = 0 ; recalculate(FALSE) ; /* don't free data */ remakerows() ; draw_the_data() ; TWcheckExposure() ; save_for_do( REDO ) ; } /* update_macro */ /* dumps the data to a file for future study */ static graphics_dump() { /* now change mode to dump to file */ TWsetMode(1) ; TWsetFrame(0) ; /* dump the data to a file now instead of screen */ draw_the_data() ; /* restore the state to previous condition and set draw to screen */ TWsetMode(0) ; } /* find the macro in question */ static INT pick_macro( twmsg ) char *twmsg ; { INT i ; INT match_count ; /* keep track of all cells that match */ INT x, y ; /* coordinates picked by user */ INT cell ; /* selected cell */ INT l, r, b, t ; /* cell sides */ if( twmsg ){ TWmessage( twmsg ) ; } else { TWmessage("Pick cell by clicking any mouse button at center of cell"); } TWgetPt( &x, &y ) ; /* look thru all cells O(numcells) algorithm */ match_count = 0 ; for( i = 1 ; i <= num_macrosG; i++ ){ get_global_pos( i, &l, &b, &r, &t ) ; /* see if cell boundary contains this point */ if( x >= l && x <= r ){ if( y >= b && y <= t ){ selectMacroS = i ; match_count++ ; } } } /* end loop */ if( match_count == 0 ){ TWmessage( "No cell selected" ) ; if( selectMacroS ){ /* user didn't like any options */ selectMacroS = 0 ; /* draw the data with highlight off draw_the_data() ; TWcheckExposure() ; */ } return( 0 ) ; } else if( match_count == 1 ){ /* draw the data with highlight on */ draw_macro( selectMacroS, TWVIOLET ) ; TWcheckExposure() ; sprintf( YmsgG, "Selected macro:%d", selectMacroS ) ; TWmessage( YmsgG ) ; return( selectMacroS ) ; } else { /* more than one match */ TWmessage( "More than one match. Choose correct cell" ) ; (void) sleep( (unsigned) 2 ) ; while( TRUE ){ for( i = 1 ; i <= num_macrosG; i++ ){ get_global_pos( i, &l, &b, &r, &t ) ; /* see if cell boundary contains this point */ if( x >= l && x <= r ){ if( y >= b && y <= t ){ selectMacroS = i ; draw_the_data() ; TWcheckExposure() ; /* give directions */ sprintf( YmsgG, "Selected cell:%d", selectMacroS ) ; TWmessage( YmsgG ) ; (void) sleep( (unsigned) 2 ) ; sprintf( YmsgG,"%s","If correct, enter . Otherwise ") ; strcat( YmsgG, "enter n for next cell: ") ; /* look for empty string - means we are satisfied */ if(!(TWgetString(YmsgG))){ return( selectMacroS ) ; } } } } /* end loop */ } } } /* end pick_macro */ static TILE_BOX *pick_tile( pmsg ) char *pmsg ; { INT x, y ; /* the user's pick points */ TILE_BOX *tile ; /* the current tile */ if( pmsg ){ TWmessage( pmsg ) ; } else { TWmessage( "Select tile to edit by using mouse") ; } TWgetPt( &x, &y ) ; for( tile=tile_listG;tile;tile=tile->next ){ if( tile->llx <= x && x <= tile->urx && tile->lly <= y && y <= tile->ury ){ /* we found a tile return */ return(tile) ; } } /* if we get here we didn't find a tile */ TWmessage( "No tile selected") ; return( NULL ) ; } /* end pick_tile */ static ROW_BOX *pick_row() { INT x, y ; /* the user's pick points */ ROW_BOX *rowptr ; /* current row being output */ ROW_BOX *segment ; /* current segment being output */ ROW_BOX *get_rowptr(); /* get data structure */ TWmessage( "Select row to edit by using mouse") ; TWgetPt( &x, &y ) ; for( rowptr=get_rowptr();rowptr;rowptr=rowptr->next_row ){ if( rowptr->next_segment ){ /* means we have more that one segment to row */ for( segment=rowptr;segment;segment=segment->next_segment){ if( segment->llx <= x && x <= segment->urx && segment->lly <= y && y <= segment->ury ){ /* we found a tile return */ return(segment) ; } } /* end for loop */ } else { if( rowptr->llx <= x && x <= rowptr->urx && rowptr->lly <= y && y <= rowptr->ury ){ /* we found a tile return */ return(rowptr) ; } } } /* end for loop */ /* if we get here we didn't find a row */ TWmessage( "No row selected") ; return( NULL ) ; } /* end pick row */ #define TILEF 3 #define LEFTF 4 #define BOTF LEFTF+1 #define RITEF LEFTF+2 #define TOPF LEFTF+3 #define LEGALF 8 #define LEGALCASE LEGALF+1 #define ILLEGALCASE LEGALF+2 #define ROWF 12 #define MAXROWF 14 #define NUMROWF 16 #define MINF 21 #define STARTF 23 #define MAXF 25 #define SEPF 27 #define CLASSF 29 #define FORCEF 17 #define FORCECASE FORCEF+1 #define NOFORCECASE FORCEF+2 #define MIRRORF 30 #define MIRRORCASE MIRRORF+1 #define NOMIRRORCASE MIRRORF+2 #define FWIDTH 15 /* field width */ static INT get_row_height( answer ) TWDRETURNPTR answer ; /* return from user */ { INT height ; height = atoi( answer[ROWF].string ) ; if( height <= 0 ){ outm( ERRMSG, "edit_tile", "Invalid row height. Must be greater than zero" ) ; return( 1 ) ; ; } return( height ) ; } /* end get_row_height */ static INT get_row_sep( answer ) TWDRETURNPTR answer ; /* return from user */ { INT sep ; sep = atoi( answer[SEPF].string ) ; if( sep <= 0 ){ outm( ERRMSG, "edit_tile", "Invalid row separation. Must be greater than zero" ) ; return(1) ; } if( sep > selected_tileS->ury - selected_tileS->lly ){ outm( ERRMSG, "edit_tile", "Invalid row separation. Must be less than tile y dimension" ) ; return(1) ; } return( sep ) ; } /* end get_row_sep */ static INT get_maxrows( answer ) TWDRETURNPTR answer ; /* return from user */ { INT maxrows ; /* means the user change the field */ maxrows = atoi( answer[MAXROWF].string ) ; if( maxrows < 0 ){ outm( ERRMSG, "edit_tile", "Invalid number of rows. Must be non-negative" ) ; return( 0 ) ; } return( maxrows ) ; } /* end get_maxrows */ static INT update_tile_data( answer, field ) TWDRETURNPTR answer ; /* return from user */ INT field ; { INT sep ; INT rows ; INT maxrows ; INT height ; INT row_height ; switch( field ){ case FORCECASE: break ; case NOFORCECASE: sprintf( answer[STARTF].string, "%d", selected_tileS->llx + spacingG ) ; sprintf( answer[MAXF].string, "%d", selected_tileS->urx - spacingG ) ; answer[STARTF].bool = TRUE ; answer[MAXF].bool = TRUE ; break ; case ROWF: row_height = get_row_height( answer ) ; sep = get_row_sep( answer ) ; height = selected_tileS->ury - selected_tileS->lly ; maxrows = ( height ) / (row_height + sep ) ; sprintf( answer[MAXROWF].string, "%d", maxrows ) ; rows = atoi( answer[NUMROWF].string ) ; if( rows < 0 ){ outm( ERRMSG, "edit_tile", "Invalid number of rows. Must be non-negative" ) ; return ; } if( rows > maxrows ){ sprintf( answer[NUMROWF].string, "%d", maxrows ) ; } break ; case MAXROWF: /* means the user change the field */ maxrows = get_maxrows( answer ) ; row_height = get_row_height( answer ) ; /* now calculate the channel separation for this tile */ height = selected_tileS->ury - selected_tileS->lly ; sep = (height - maxrows * row_height) / (maxrows) ; if( sep <= 0 ){ /* calculate the maximum amount of rows if sep = 1 */ sep = 1 ; maxrows = ( height ) / (row_height + sep ) ; outm( WARNMSG, "edit_tile", "Exceeded maximum number of rows. Set to maximum." ) ; } sprintf( answer[NUMROWF].string, "%d", maxrows ) ; sprintf( answer[SEPF].string, "%d", sep ) ; break ; case NUMROWF: maxrows = get_maxrows( answer ) ; /* means the user changed the field */ rows = atoi( answer[NUMROWF].string ) ; if( rows < 0 ){ outm( ERRMSG, "edit_tile", "Invalid number of rows. Must be non-negative" ) ; return ; } if( rows > maxrows ){ outm( WARNMSG, "edit_tile", "Exceeded maximum number of rows. Set to maximum." ) ; sprintf( answer[NUMROWF].string, "%d", maxrows ) ; } break ; case MINF: break ; case SEPF: sep = get_row_sep( answer ) ; row_height = get_row_height( answer ) ; height = selected_tileS->ury - selected_tileS->lly ; rows = ( height ) / (row_height + sep ) ; sprintf( answer[MAXROWF].string, "%d", rows ) ; if( rows > selected_tileS->numrows ){ sprintf( answer[NUMROWF].string, "%d", rows ) ; } break ; } /* end switch */ } static BOOL edit_tiles( tile ) TILE_BOX *tile ; { INT temp ; /* temporary answer from user */ INT sep ; /* channel separation */ INT rows ; /* number of rows */ INT height ; /* tile height */ INT max_rows ; /* maximum number of rows */ char tileName[FWIDTH]; /* a scratch buffer for tile name */ char left[FWIDTH]; /* a scratch buffer for left tile side */ char right[FWIDTH]; /* a scratch buffer for right tile side */ char class[FWIDTH]; /* a scratch buffer for the class */ char top[FWIDTH]; /* a scratch buffer for top tile side */ char bottom[FWIDTH]; /* a scratch buffer for bottom tile side */ char numrows[FWIDTH]; /* a scratch buffer for number of rows */ char maxrows[FWIDTH]; /* a scratch buffer for number of rows */ char rowHeight[FWIDTH];/* a scratch buffer for row height */ char minlength[FWIDTH];/* a scratch buffer for minimum length of row */ char maxlength[FWIDTH];/* a scratch buffer for maximum length of row */ char separation[FWIDTH];/* a scratch buffer for row separation */ char startrow[FWIDTH]; /* a scratch buffer for row separation */ BOOL old_force ; /* keep track of change */ TWDRETURNPTR answer ; /* return from user */ TWmessage( "Edit Tile" ) ; #ifdef DEVELOPDIALOG dialogS = TWread_dialog( "genrows.dialog" ) ; if( !(dialogS) ){ return ; /* avoid crashes */ } #endif /* now initialize the fields to user data */ sprintf( tileName, "Tile : %d", tile->name ) ; dialogS[TILEF].string = tileName ; dialogS[TILEF].len = strlen( tileName ) ; sprintf( left, "Left : %d", tile->llx ) ; dialogS[LEFTF].string = left ; dialogS[LEFTF].len = strlen( left ) ; sprintf( bottom,"Bottom: %d", tile->lly ) ; dialogS[BOTF].string = bottom ; dialogS[BOTF].len = strlen( bottom ) ; sprintf( right, "Right : %d", tile->urx ) ; dialogS[RITEF].string = right ; dialogS[RITEF].len = strlen( right ) ; sprintf( top, "Top : %d", tile->ury ) ; dialogS[TOPF].string = top ; dialogS[TOPF].len = strlen( top ) ; /* set legality of tile */ if( tile->illegal ){ dialogS[LEGALF].group = ILLEGALCASE ; } else { dialogS[LEGALF].group = LEGALCASE ; } /* Now set the row height fields */ sprintf( rowHeight, "%d", tile->actual_row_height ) ; dialogS[ROWF].string = rowHeight ; /* Now set the number of rows */ height = tile->ury - tile->lly ; sep = tile->channel_separation ; max_rows = ( height ) / (tile->actual_row_height + sep ) ; if( tile->numrows > max_rows ){ max_rows = tile->numrows ; } sprintf( maxrows, "%d", max_rows ) ; dialogS[MAXROWF].string = maxrows ; sprintf( numrows, "%d", tile->numrows ) ; dialogS[NUMROWF].string = numrows ; /* Now set the min length of row */ sprintf( minlength, "%d", tile->min_length ) ; dialogS[MINF].string = minlength ; /* Now set the start of the row */ sprintf( startrow, "%d", tile->llx + tile->row_start ) ; dialogS[STARTF].string = startrow ; /* Now set the max length of row */ sprintf( maxlength, "%d", tile->llx + tile->row_start + tile->max_length ) ; dialogS[MAXF].string = maxlength ; /* Now set the chan separation of row */ sprintf( separation, "%d", tile->channel_separation ) ; dialogS[SEPF].string = separation ; sprintf( class, "%d", tile->class ) ; dialogS[CLASSF].string = class ; if( tile->force ){ dialogS[FORCEF].group = FORCECASE ; } else { dialogS[FORCEF].group = NOFORCECASE ; } old_force = tile->force ; /* set mirror option of tile */ if( tile->mirror ){ dialogS[MIRRORF].group = MIRRORCASE ; } else { dialogS[MIRRORF].group = NOMIRRORCASE ; } /* initialization complete */ if( answer = TWdialog( dialogS, "genrows", update_tile_data ) ){ /* must be the number of the case field */ if( answer[LEGALCASE].bool ){ /* the tile is legal */ tile->illegal = FALSE ; } else if( answer[ILLEGALCASE].bool ){ tile->illegal = TRUE ; } if( answer[MIRRORCASE].bool ){ tile->mirror = TRUE ; } else if( answer[NOMIRRORCASE].bool ){ tile->mirror = FALSE ; } if( answer[FORCECASE].bool ){ tile->force = TRUE ; } else if( answer[NOFORCECASE].bool ){ tile->force = FALSE ; if( old_force != tile->force ){ /* only do this on a change */ tile->row_start = spacingG ; tile->max_length = tile->urx - tile->llx - 2 * spacingG ; } } if( answer[ROWF].bool ){ /* means the user change the field */ temp = get_row_height( answer ) ; if( temp <= 0 ){ return ; } tile->actual_row_height = temp ; } if( answer[MAXROWF].bool ){ /* means the user change the field */ rows = atoi( answer[MAXROWF].string ) ; if( rows < 0 ){ outm( ERRMSG, "edit_tile", "Invalid number of rows. Must be non-negative" ) ; return ; } /* now calculate the channel separation for this tile */ height = tile->ury - tile->lly ; sep = (height - rows * tile->actual_row_height) / (rows) ; if( sep <= 0 ){ /* calculate the maximum amount of rows if sep = 1 */ sep = 1 ; rows = ( height ) / (tile->actual_row_height + sep ) ; outm( WARNMSG, "edit_tile", "Exceeded maximum number of rows. Set to maximum." ) ; } tile->numrows = rows ; tile->channel_separation = sep ; } if( answer[NUMROWF].bool ){ /* means the user change the field */ rows = atoi( answer[NUMROWF].string ) ; if( rows < 0 ){ outm( ERRMSG, "edit_tile", "Invalid number of rows. Must be non-negative" ) ; return ; } /* now calculate the channel separation for this tile */ height = tile->ury - tile->lly ; sep = tile->channel_separation ; max_rows = ( height ) / (tile->actual_row_height + sep ) ; if( rows <= max_rows ){ tile->numrows = rows ; } else { outm( WARNMSG, "edit_tile", "Exceeded maximum number of rows. Set to maximum." ) ; tile->numrows = max_rows ; } } if( answer[MINF].bool ){ /* means the user change the field */ temp = atoi( answer[MINF].string ) ; if( temp <= 0 ){ outm( ERRMSG, "edit_tile", "Invalid minimum length. Must be greater than zero" ) ; return ; } tile->min_length = temp ; } if( answer[MAXF].bool ){ /* means the user change the field */ temp = atoi( answer[MAXF].string ) ; if( temp < tile->llx ){ outm( ERRMSG, "edit_tile", "Invalid end of row. Must be greater than tile left" ); return ; } if( temp > tile->urx ){ outm( ERRMSG, "edit_tile", "Invalid end of row. Must be less than tile right" ) ; return ; } tile->max_length = temp - tile->llx - tile->row_start ; } if( answer[STARTF].bool ){ /* means the user change the field */ temp = atoi( answer[STARTF].string ) ; if( temp < tile->llx ){ outm( ERRMSG, "edit_tile", "Invalid start of row. Must be greater than tile left") ; return ; } if( temp > tile->urx ){ outm( ERRMSG, "edit_tile", "Invalid start of row. Row must start before end of tile" ) ; return ; } tile->row_start = temp - tile->llx ; /* now modify the width of the tile accordingly */ if( tile->llx + tile->row_start + tile->max_length > tile->urx - 2*spacingG ){ tile->max_length = tile->urx - tile->llx - tile->row_start - 2*spacingG ; outm( MSG, "edit_tile", "Note:resetting maximum length of row." ) ; } } if( answer[SEPF].bool ){ /* means the user change the field */ tile->channel_separation = get_row_sep( answer ) ; } if( answer[CLASSF].bool ){ /* means the user change the field */ temp = atoi( answer[CLASSF].string ) ; if( temp <= 0 ){ outm( ERRMSG, "edit_tile", "ERROR:Invalid class. Must be greater than zero" ) ; return ; } tile->class = temp ; } return( TRUE ) ; } else { return( FALSE ) ; } } /* end edit_tiles */ edit_row( rowptr ) ROW_BOX *rowptr ; { #define LEFT_F 3 #define BOT_F LEFT_F+1 #define RITE_F LEFT_F+2 #define TOP_F LEFT_F+3 #define CLASS_F 8 #define MIRROR_F 9 #define MIRRORCASE_F MIRROR_F+1 #define NOMIRRORCASE_F MIRROR_F+2 char left[FWIDTH]; /* a scratch buffer for left tile side */ char right[FWIDTH]; /* a scratch buffer for right tile side */ char top[FWIDTH]; /* a scratch buffer for top tile side */ char bottom[FWIDTH]; /* a scratch buffer for bottom tile side */ char class[FWIDTH]; /* a scratch buffer for the class */ INT temp ; /* calculate the class */ TWDRETURNPTR answer ; /* return from user */ TWmessage( "Edit Row" ) ; #ifdef DEVELOPDIALOG row_dialogS = TWread_dialog( "row.dialog" ) ; if( !(row_dialogS) ){ return ; /* avoid crashes */ } #endif /* now initialize the fields to user data */ sprintf( left, "Left : %d", rowptr->llx ) ; row_dialogS[LEFT_F].string = left ; row_dialogS[LEFT_F].len = strlen(left) ; sprintf( bottom,"Bottom: %d", rowptr->lly ) ; row_dialogS[BOT_F].string = bottom ; row_dialogS[BOT_F].len = strlen(bottom) ; sprintf( right, "Right : %d", rowptr->urx ) ; row_dialogS[RITE_F].string = right ; row_dialogS[RITE_F].len = strlen(right) ; sprintf( top, "Top : %d", rowptr->ury ) ; row_dialogS[TOP_F].string = top ; row_dialogS[TOP_F].len = strlen(top) ; /* Now set the class field */ if( rowptr->class ){ sprintf( class, "%d", rowptr->class ) ; } else { sprintf( class, "1" ) ; } row_dialogS[CLASS_F].string = class ; /* set mirror option of tile */ if( rowptr->mirror ){ row_dialogS[MIRROR_F].group = MIRRORCASE_F ; } else { row_dialogS[MIRROR_F].group = NOMIRRORCASE_F ; } /* Now call the dialog box */ if( answer = TWdialog( row_dialogS, "row", NULL ) ){ if( answer[CLASS_F].bool ){ /* means the user change the field */ temp = atoi( answer[CLASS_F].string ) ; if( temp <= 0 ){ TWmessage( "ERROR:Invalid class. Must be greater than zero" ) ; return ; } rowptr->class = temp ; } if( answer[MIRRORCASE_F].bool ){ rowptr->mirror = TRUE ; } else if( answer[NOMIRRORCASE_F].bool ){ rowptr->mirror = FALSE ; } } } /* end edit_row */ /* the MACRO DIALOG definitions */ #define XPOSF 6 #define YPOSF 8 #define DELTAXF 10 #define DELTAYF 12 #define ORIENTF 13 #define ORIENTBASE 14 static INT update_macro_data( answer, field ) TWDRETURNPTR answer ; /* return from user */ INT field ; { INT pos ; INT deltax, deltay ; INT orient ; deltax = 0 ; deltay = 0 ; switch( field ){ case DELTAXF: deltax = atoi( answer[DELTAXF].string ) ; break ; case DELTAYF: deltay = atoi( answer[DELTAYF].string ) ; break ; case ORIENTBASE: case ORIENTBASE+1: case ORIENTBASE+2: case ORIENTBASE+3: case ORIENTBASE+4: case ORIENTBASE+5: case ORIENTBASE+6: case ORIENTBASE+7: #ifdef TI orient = ice2tw(field-ORIENTBASE+1) ; #else orient = field - ORIENTBASE ; #endif /* order is important here */ rotate_vertices( macroArrayG[selectMacroS], orient ) ; macroArrayG[selectMacroS]->orient = orient ; TWforceRedraw() ; break ; } /* end switch */ if( deltax == 0 && deltay == 0 ){ return ; /* no work to do */ } /* else update the cooridates positions */ if( deltax != 0 ){ pos = atoi( answer[XPOSF].string ) ; pos += deltax ; sprintf( answer[XPOSF].string, "%d", pos ) ; answer[XPOSF].bool = TRUE ; sprintf( answer[DELTAXF].string, "0" ) ; } if( deltay != 0 ){ pos = atoi( answer[YPOSF].string ) ; pos += deltay ; sprintf( answer[YPOSF].string, "%d", pos ) ; answer[YPOSF].bool = TRUE ; sprintf( answer[DELTAYF].string, "0" ) ; } } /* end update_macro_data */ static edit_macro( macro, xoff, yoff ) { TWDRETURNPTR answer ; /* return from user */ MACROPTR mptr ; /* current macro information */ char xpos[FWIDTH]; /* a scratch buffer for xpos */ char ypos[FWIDTH]; /* a scratch buffer for ypos */ char deltax[FWIDTH]; /* a scratch buffer for deltax */ char deltay[FWIDTH]; /* a scratch buffer for deltay */ INT x, y ; /* new coordinates */ INT pos ; /* user's input */ INT old_orient ; /* put orientation back if necessary */ #ifdef DEVELOPDIALOG macro_dialogS = TWread_dialog( "macro.dialog" ) ; if( !(macro_dialogS) ){ return ; /* avoid crashes */ } #endif mptr = macroArrayG[macro] ; /* now initialize the fields to user data */ sprintf( xpos, "%d", xoff ) ; macro_dialogS[XPOSF].string = xpos ; sprintf( ypos, "%d", yoff ) ; macro_dialogS[YPOSF].string = ypos ; sprintf( deltax,"0" ) ; macro_dialogS[DELTAXF].string = deltax ; sprintf( deltay,"0" ) ; macro_dialogS[DELTAYF].string = deltay ; /* set orientation */ #ifdef TI macro_dialogS[ORIENTF].group = tw2ice(mptr->orient) + ORIENTBASE - 1 ; #else macro_dialogS[ORIENTF].group = mptr->orient + ORIENTBASE ; #endif /* TI */ old_orient = macroArrayG[selectMacroS]->orient ; if( answer = TWdialog( macro_dialogS, "macro", update_macro_data )){ if( answer[XPOSF].bool ){ /* means the user change the field */ pos = atoi( answer[XPOSF].string ) ; /* calculate the new center of the macro */ x = mptr->xcenter + pos - xoff ; } else { x = mptr->xcenter ; } if( answer[YPOSF].bool ){ /* means the user change the field */ pos = atoi( answer[YPOSF].string ) ; /* calculate the new center of the macro */ y = mptr->ycenter + pos - yoff ; } else { y = mptr->ycenter ; } update_vertices( selectMacroS, x, y ) ; } else if( macroArrayG[selectMacroS]->orient != old_orient ){ /* order is important here */ rotate_vertices( macroArrayG[selectMacroS], old_orient ) ; macroArrayG[selectMacroS]->orient = old_orient ; TWforceRedraw() ; } } /* end edit_macro */ get_global_pos( macro, l, b, r, t ) INT macro ; INT *l, *r, *b, *t ; { MACROPTR mptr ; mptr = macroArrayG[macro] ; *l = mptr->left + mptr->xcenter ; *r = mptr->right + mptr->xcenter ; *b = mptr->bottom + mptr->ycenter ; *t = mptr->top + mptr->ycenter ; } /* end get_global_pos */ static update_vertices( macro, newxcenter, newycenter ) INT macro, newxcenter, newycenter ; { INT j ; INT deltaX ; INT deltaY ; MACROPTR mptr ; VERTEXPTR vptr ; mptr = macroArrayG[macro] ; deltaX = newxcenter - mptr->xcenter ; deltaY = newycenter - mptr->ycenter ; for( j = 0; j < mptr->num_vertices; j++ ){ vptr = mptr->vertices[j] ; vptr->x += deltaX ; vptr->y += deltaY ; } mptr->xcenter = newxcenter ; mptr->ycenter = newycenter ; } /* end update_vertices */ static rotate_vertices( mptr, orient ) MACROPTR mptr ; INT orient ; { INT j, p ; INT x, y ; INT l, b ; INT this_pt ; INT inverse ; INT old_orient ; INT lowestp ; INT limit ; INT nextpos, nextneg ; INT *temp_x ; INT *temp_y ; INT numpts ; VERTEXPTR vptr ; old_orient = mptr->orient ; numpts = mptr->num_vertices ; /* allocate the space for reoordering the points of the macro */ temp_x = (INT *) Ysafe_malloc( numpts * sizeof(INT) ) ; temp_y = (INT *) Ysafe_malloc( numpts * sizeof(INT) ) ; /* first subtract off the center */ for( j = 0; j < mptr->num_vertices; j++ ){ vptr = mptr->vertices[j] ; vptr->x -= mptr->xcenter ; vptr->y -= mptr->ycenter ; } if( old_orient ){ /* we need to perform the inverse first */ /* if we have any orientation other than zero */ inverse = Ytrans_inv_orient( old_orient ) ; for( j = 0; j < numpts; j++ ){ vptr = mptr->vertices[j] ; REL_POST( inverse, x, y, /* result */ vptr->x, vptr->y, /* cell relative */ 0, 0 ) ; /* cell center */ vptr->x = x ; vptr->y = y ; } } for( j = 0; j < numpts; j++ ){ vptr = mptr->vertices[j] ; REL_POST( orient, temp_x[j], temp_y[j], /* result */ vptr->x, vptr->y, /* cell relative */ mptr->xcenter, mptr->ycenter ) ; /* cell center */ } /* now we need to reorder the vertices */ /* all the points have been rotated into their proper view and */ /* stored in the vertices array. Now find lowest of the left pts. */ l = INT_MAX ; b = INT_MAX ; for( j = 0; j < numpts; j++ ){ if( temp_x[j] <= l ){ if( temp_y[j] <= b ){ l = temp_x[j] ; b = temp_y[j] ; lowestp = j ; } } } /* now determine CW direction */ nextpos = (lowestp + 1 ) % numpts; ; if( lowestp == 0 ){ nextneg = numpts - 1 ; } else { nextneg = lowestp - 1 ; } j = 0 ; if( temp_x[nextpos] == l && temp_y[nextpos] > b ){ /* clockwise is positive */ limit = lowestp + numpts; for( p = lowestp; p < limit; p++ ) { this_pt = p % numpts ; vptr = mptr->vertices[j++] ; vptr->x = temp_x[this_pt] ; vptr->y = temp_y[this_pt] ; } } else if( temp_x[nextneg] == l && temp_y[nextneg] > b ){ /* clockwise is negative */ limit = lowestp - numpts ; for( p = lowestp; p > limit; p-- ) { if( p < 0 ){ this_pt = numpts + p ; } else { this_pt = p ; } vptr = mptr->vertices[j++] ; vptr->x = temp_x[this_pt] ; vptr->y = temp_y[this_pt] ; } } else { M( ERRMSG, "rotate_vertices", "couldn't find clockwise direction for boundary\n" ) ; } Ysafe_free( temp_x ) ; Ysafe_free( temp_y ) ; } /* end rotate_vertices */ static find_nearest_corner( macro, x, y, x_ret, y_ret ) INT macro, x, y, *x_ret, *y_ret ; { INT j ; INT dist ; INT cdist ; INT closest_pt ; MACROPTR mptr ; VERTEXPTR vptr ; mptr = macroArrayG[macro] ; dist = INT_MAX ; for( j = 0; j < mptr->num_vertices; j++ ){ vptr = mptr->vertices[j] ; cdist = ABS(vptr->x - x) + ABS(vptr->y - y) ; if( cdist < dist ){ closest_pt = j ; dist = cdist ; } } /* now check the center point */ cdist = ABS(mptr->xcenter-x) + ABS(mptr->ycenter-y) ; if( cdist < dist ){ /* the center is the closest point */ *x_ret = mptr->xcenter ; *y_ret = mptr->ycenter ; } else { /* one of the corner points */ vptr = mptr->vertices[closest_pt] ; *x_ret = vptr->x ; *y_ret = vptr->y ; } } /* end find_nearest_corner */ static highlight_corner( macro, x, y ) INT macro, x, y ; { INT l, b, r, t ; /* the core */ INT xpand ; /* blow up corner by this amount */ get_core( &l, &b, &r, &t, TRUE ) ; xpand = MIN( r - l, t - b ) ; xpand = (INT) (0.025 * (DOUBLE) xpand ) ; xpand = MAX( xpand, 1 ) ; /* don't let it go to zero */ TWdrawCell( 0, x-xpand,y-xpand,x+xpand,y+xpand,TWBLACK, NULL ) ; TWflushFrame() ; /* (void) sleep( (unsigned) 2 ) ; */ } /* end highlight_corner */ static outm( errtype, routine, string ) INT errtype ; char *routine ; char *string ; { char buffer[LRECL] ; switch( errtype ){ case ERRMSG: if( routine ){ sprintf( buffer, "ERROR[%s]:", routine ) ; } else { sprintf( buffer, "ERROR:" ) ; } break ; case WARNMSG: if( routine ){ sprintf( buffer, "WARNING[%s]:", routine ) ; } else { sprintf( buffer, "WARNING:" ) ; } break ; default : buffer[0] = EOS ; } strcat( buffer, string ) ; TWmessage( buffer ) ; sprintf( buffer, "%s\n", string ) ; M( errtype, routine, buffer ) ; } /* end outm */ #else /* NOGRAPHICS */ /* dummy routines to resolve globals */ #endif graywolf-0.1.4+20170307gite1bf319/src/genrows/genrows.c000066400000000000000000001675171305746555600221100ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: genrows.c DESCRIPTION:This file contains the main algorithm for generating the standard cell rows. CONTENTS: DATE: Aug 9, 1989 REVISIONS: Sep 18, 1989 - added row gridding to algorithm. Dec 18, 1989 - handle special case of total row length less than minimum tile size. Feb 8, 1990 - took total_row_length out of call by making it a static. May 4, 1990 - added error checking for genrows. Sep 25, 1990 - now create a .gen file when user changes macro positions. Fixed a pointer problem in vertex list. Oct 21, 1990 - added snap core feature. Dec 7, 1990 - added set parameter options and added force function. Also fixed rounding of rows. Dec 15, 1990 - fixed problem with stdcell only UNDO and install divide tile. Dec 28, 1990 - added divide_tilelr. Mon Jan 7 18:24:05 CST 1991 - removed two versions of core. Check for compatible restart file. Turned off info about placed row length. Sun Jan 20 21:22:37 PST 1991 - ported to AIX. Fri Jan 25 17:50:54 PST 1991 - added mirror row feature. Sat Jan 26 16:29:59 PST 1991 - added check_user_data and force_tiles. Also updated shortRow at top of core. Sat Feb 23 00:33:08 EST 1991 - now make discard short row the default. Thu Mar 7 03:10:48 EST 1991 - now allow user to set number of rows in the standard cell case. Thu Mar 7 03:36:00 EST 1991 - added comments to the .blk file. Wed Apr 17 22:35:57 EDT 1991 - now genrows can rotate macros. Deleted snap_core. Sun Apr 21 21:49:14 EDT 1991 - fixed problem with dividing tiles vertically. Sat Sep 21 15:38:45 EDT 1991 - added memory function. Tue Sep 24 00:47:00 EDT 1991 - output core into .gen file. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) genrows.c (Yale) version 3.24 5/14/92" ; #endif #include #include #include #include #include #include #include #include #define NOTOUCH 0 #define OVERLAP1 1 #define OVERLAP2 2 #define OVERLAP3 3 #define TOUCH 4 static ROW_BOX *set_of_rowsS , *last_rowptrS ; static VERTEX_BOX *vertex_listS , *last_vertexS ; static INT number_of_rows_addedS ; static INT number_of_segs_addedS ; /* core boundaries, as read in from the data */ static INT cx1S , cy1S , cx2S , cy2S ;/* current values */ static INT actual_row_heightS ; /* row height in microns */ static INT channel_separationS ; /* channel separation in microns */ static INT min_lengthS ; /* minimum valid row length */ static INT total_row_lengthS ; /* total row length of standard cells and feeds */ static INT total_row_segmentS ; /* number of row segments */ static INT stdcell_lengthS ; /* total row length of standard cells */ static INT feed_lengthS = 0 ; /* length of feeds */ static YTREEPTR tile_memoryG ; static reset_tile_parameters(); static INT compare_tiles(); #if SIZEOF_VOID_P == 64 #define INTSCANSTR "%ld" #else #define INTSCANSTR "%d" #endif init_data_structures() { /*static INT compare_tiles() ;*/ set_of_rowsS = NULL ; last_rowptrS = NULL ; tile_listG = NULL ; shortRowG = FALSE ; macroArrayG = NULL ; start_tileG = NULL ; /* current chosen tile */ vertex_listS = NULL ; limitMergeG = FALSE; spacingG = 1 ; memoryG = TRUE ; tile_memoryG = Yrbtree_init( compare_tiles ) ; } /* end init_data_structures */ set_feed_length( percent ) DOUBLE percent ; { feed_lengthS = (INT) ( percent / 100.0 * (DOUBLE) stdcell_lengthS ) ; } /* end set_feed_length */ process_tiles() { TILE_BOX *tptr ; INT llx , lly , urx , ury ; INT counter = 0 ; last_tileG = NULL ; tile_listG = NULL ; while( find_tile(&llx , &lly , &urx , &ury ) ) { if(!(tile_listG)) { tile_listG = (TILE_BOX *) Ysafe_malloc( sizeof(TILE_BOX) ) ; tptr = last_tileG = tile_listG ; tile_listG->prev = NULL ; } else { tptr = last_tileG->next = (TILE_BOX *) Ysafe_malloc( sizeof(TILE_BOX) ) ; tptr->prev = last_tileG ; last_tileG = tptr ; } tptr->name = ++counter ; tptr->llx = llx ; tptr->lly = lly ; tptr->urx = urx ; tptr->ury = ury ; tptr->merged = MERGED_NONE ; tptr->actual_row_height = actual_row_heightS ; tptr->channel_separation = channel_separationS ; tptr->min_length = min_lengthS ; tptr->numrows = 0 ; tptr->illegal = FALSE ; tptr->class = 1 ; tptr->mirror = FALSE ; tptr->force = FALSE ; tptr->add_no_more_than = 0 ; tptr->allocated = TRUE ; tptr->next = NULL ; } /* ADD EXTRA TILE ACROSS TOP OF THE CORE OF THE CHIP */ /* (in case there isn't enough row space within the core) */ tptr = last_tileG->next = (TILE_BOX *) Ysafe_malloc( sizeof(TILE_BOX) ) ; tptr->prev = last_tileG ; last_tileG = tptr ; tptr->llx = cx1S ; tptr->lly = cy2S ; tptr->urx = cx2S ; tptr->ury = cy2S + (cy2S - cy1S) / 2 ; /* Just some upper bound; I would expect that we would never have to extend the core upward by more than 1/2 */ tptr->merged = MERGED_NONE ; tptr->actual_row_height = actual_row_heightS ; tptr->channel_separation = channel_separationS ; tptr->min_length = min_lengthS ; tptr->numrows = 0 ; tptr->illegal = FALSE ; tptr->force = FALSE ; tptr->class = 1 ; tptr->mirror = FALSE ; tptr->add_no_more_than = 0 ; tptr->allocated = TRUE ; tptr->next = NULL ; /* now set row start and max length fields */ set_spacing() ; } /* end process_tiles */ check_tiles() { TILE_BOX *tile1 , *tile2 ; /* CHECK FOR ILLEGAL TILE CONFIGURATIONS */ for( tile1 = tile_listG ; tile1 ; tile1 = tile1->next ) { for( tile2 = tile1->next ; tile2 ; tile2 = tile2->next ) { if( !(tile1->lly >= tile2->ury || tile2->lly >= tile1->ury)){ if( tile1->actual_row_height!=tile2->actual_row_height || tile1->channel_separation != tile2->channel_separation){ printf("\nERROR:\n") ; printf("Tiles which overlap in the y-direction must have\n"); printf("the same row height and the same channel separation\n\n"); } } } } } /* end check_tiles */ print_blk_file() { /* output the rows; check for multiple row segments - if there are any, create the appropriate exceptions */ FILE *fpb ; /* block file */ FILE *fpg ; /* gen file */ ROW_BOX *rowptr , *segment , *save_segment ; MACROPTR mptr ; /* the current macro */ INT llx , urx , last_llx , last_urx , next_llx ; INT r ; INT i ; /* counter */ INT pt ; /* counter */ char filename[LRECL] ; VERTEXPTR *vptr ; /* current vertex array */ VERTEXPTR pt_ptr ; /* current point */ TILE_BOX *tileptr ; /* current tile */ if( no_outputG ){ return ; } sprintf( filename, "%s.blk", cktNameG ) ; fpb = TWOPEN( filename, "w", ABORT ) ; fprintf(fpb,"rows %d\n", number_of_rows_addedS ) ; grid_rows() ; i = 1; for( rowptr = set_of_rowsS ; rowptr ; rowptr = rowptr->next_row ){ /* Flip alternate rows, if requested */ if (i == flip_alternateG) rowptr->mirror = !(rowptr->mirror); if (++i == 3) i = 1; fprintf(fpb,"row ") ; segment = rowptr->next_segment ; if( segment == NULL ) { if( feeds_per_segG ){ r = rowptr->urx - feeds_per_segG ; if( r > rowptr->llx ){ /* only output up to the feed to make space */ fprintf(fpb,"%d %d %d %d", rowptr->llx, rowptr->lly, r, rowptr->ury); /* go on to the next row */ if( rowptr->class != 1 ){ fprintf(fpb,"\n class %d", rowptr->class ) ; } if( rowptr->mirror ){ fprintf(fpb,"\n mirror" ) ; } fprintf(fpb,"\n" ) ; continue ; } } /* no feeds to worry about */ fprintf(fpb,"%d %d %d %d", rowptr->llx, rowptr->lly, rowptr->urx, rowptr->ury); if( rowptr->class != 1 ){ fprintf(fpb," class %d", rowptr->class ) ; } if( rowptr->mirror ){ fprintf(fpb," mirror" ) ; } fprintf(fpb,"\n" ) ; } else { /* find x-extent of row segments */ llx = rowptr->llx ; urx = rowptr->urx ; last_urx = urx ; /* used below */ for( segment=rowptr->next_segment;segment;segment=segment->next_segment){ if( segment->llx < llx ) { llx = segment->llx ; last_urx = segment->urx ; /* used below */ last_llx = segment->llx ; /* used below */ } if( segment->urx > urx ) { urx = segment->urx ; } } /* end for loop */ r = rowptr->urx - feeds_per_segG ; if( feeds_per_segG && r > last_llx ){ fprintf(fpb,"%d %d %d %d ", llx, rowptr->lly, r, rowptr->ury ) ; } else { fprintf(fpb,"%d %d %d %d ", llx, rowptr->lly, urx, rowptr->ury ) ; } /* now print out the exceptions */ last_llx = llx ; next_llx = INT_MAX ; save_segment = NULL ; while( TRUE ) { if( rowptr->llx > last_llx ) { next_llx = rowptr->llx ; save_segment = rowptr ; } segment = rowptr->next_segment ; while( segment ) { if( segment->llx > last_llx && segment->llx < next_llx ) { next_llx = segment->llx ; save_segment = segment ; } segment = segment->next_segment ; } if( save_segment ) { r = next_llx - feeds_per_segG ; if( feeds_per_segG && r > last_urx ){ fprintf(fpb," except %d %d", last_urx , r ) ; } else if( next_llx > last_urx ){ fprintf(fpb," except %d %d", last_urx , next_llx ) ; } last_llx = next_llx ; next_llx = INT_MAX ; last_urx = save_segment->urx ; save_segment = NULL ; } else { break ; } } if( rowptr->class != 1 ){ fprintf(fpb," class %d\n", rowptr->class ) ; } if( rowptr->mirror ){ fprintf(fpb," mirror" ) ; } fprintf(fpb,"\n" ) ; } } /* end for loop */ /* now output the tiles in C comment format */ fprintf(fpb,"\n/* \n" ) ; fprintf(fpb," The Tile and Macro Information:\n" ) ; /* now count the number of tiles */ i = 0 ; for( tileptr=tile_listG;tileptr;tileptr=tileptr->next ){ if( tileptr->numrows > 0 ){ i++ ; } } fprintf(fpb," numtiles %d\n", i ) ; /* now give the positions of the tiles */ for( tileptr=tile_listG;tileptr;tileptr=tileptr->next ){ if( tileptr->numrows > 0 ){ fprintf(fpb," %d %d %d %d\n", tileptr->llx, tileptr->lly, tileptr->urx, tileptr->ury ) ; } } fprintf(fpb,"\n" ) ; fprintf(fpb," nummacros %d", num_macrosG ) ; /* if macros exist write them in the .gen file */ sprintf( filename, "%s.gen", cktNameG ) ; fpg = TWOPEN( filename, "w", ABORT ) ; fprintf( fpg, "core %d %d %d %d\n", cx1S, cy1S, cx2S, cy2S ) ; for( i = 1; i <= num_macrosG; i++ ){ mptr = macroArrayG[i] ; fprintf( fpg, "%d %d %d\n", mptr->xcenter, mptr->ycenter, mptr->orient ) ; /* also write macro positions to block file */ fprintf(fpb,"\n macro orient %d ", mptr->orient ) ; vptr = mptr->vertices ; for( pt = 0 ; pt < mptr->num_vertices ; pt++ ) { pt_ptr = vptr[pt] ; fprintf(fpb,"%d %d ", pt_ptr->x, pt_ptr->y ) ; } } fprintf(fpb,"\n\n*/\n" ) ; /* close comment */ TWCLOSE( fpg ) ; TWCLOSE( fpb ) ; return ; } /* end print_blk_file */ print_tiles() { INT i ; TILE_BOX *tileptr ; i = 0 ; for( tileptr=tile_listG;tileptr;tileptr=tileptr->next ){ i++ ; printf("TILE:%4d\t(%4d %4d) (%4d %4d)\n", i , tileptr->llx , tileptr->lly , tileptr->urx , tileptr->ury ) ; } printf("\n"); return ; } /* end print_tiles */ print_vertices() { /* for debug only */ VERTEX_BOX *vertex ; printf("VERTICES, where START=1, END=2, NOTHING=3, "); printf("MAYBE_START=12, MAYBE_END=13\n"); for( vertex = vertex_listS ;vertex; vertex = vertex->next ){ printf("x:%d y:%d class:%d macro:%d\n", vertex->x , vertex->y , vertex->class , vertex->macro ) ; } /* end for loop */ return ; } /* end print_vertices */ BOOL find_tile( llx , lly , urx , ury ) INT *llx , *lly , *urx , *ury ; { VERTEX_BOX *vertex , *lvertex , *rvertex , *tvertex ; INT lowest , left_edge , right_edge , top_edge ; BOOL found ; /* find the leftmost of the lowest START vertices */ /* this is where I start to write slow, but effective algs */ TOP: lowest = INT_MAX ; left_edge = INT_MAX ; lvertex = NULL ; for(vertex = vertex_listS ;vertex ; vertex = vertex->next ){ if( vertex->class == START ) { if( vertex->y < lowest ) { lowest = vertex->y ; lvertex = vertex ; left_edge = vertex->x ; } else if( vertex->y == lowest ) { if( vertex->x < left_edge ) { left_edge = vertex->x ; lvertex = vertex ; } } } } /* end for loop */ if( lvertex == NULL ) { return(FALSE); /* no more tiles exist */ } /* find the END vertex whose y is lowest */ /* and whose x is the nearest to the right of left_edge */ right_edge = INT_MAX ; rvertex = NULL ; for( vertex = vertex_listS;vertex;vertex = vertex->next ){ if( vertex->class == END ) { if( vertex->y == lowest ) { if( vertex->x >= left_edge ) { if( vertex->x < right_edge ) { right_edge = vertex->x ; rvertex = vertex ; } } } } } /* end for loop */ if(!(rvertex)) { lvertex->class = NOTHING ; goto TOP ; } /* now find ANY vertex whose x is between left_edge and */ /* right_edge and whose y is greater than lowest */ top_edge = INT_MAX ; tvertex = NULL ; for(vertex = vertex_listS ;vertex ; vertex = vertex->next ){ if( vertex->x >= left_edge && vertex->x <= right_edge ) { if( vertex->y > lowest ) { if( vertex->y < top_edge ) { top_edge = vertex->y ; tvertex = vertex ; } } } } /* end for loop */ if( tvertex == NULL || left_edge == right_edge || lowest == top_edge ) { lvertex->class = NOTHING ; if( rvertex ) { rvertex->class = NOTHING ; } goto TOP ; } /* change classes to NOTHING for the selected vertices */ lvertex->class = NOTHING ; rvertex->class = NOTHING ; /* here is the tile */ *llx = left_edge ; *lly = lowest ; *urx = right_edge ; *ury = top_edge ; /* the generated tile has four vertices; if any of these vertices */ /* is not currently in the list (only the two top ones could be new) */ /* we need to add them */ found = FALSE ; for(vertex = vertex_listS ;vertex ; vertex = vertex->next ){ if( vertex->x == *llx && vertex->y == *ury ) { found = TRUE ; break ; } } /* end for loop */ if( !found ) { last_vertexS = last_vertexS->next = (VERTEX_BOX *) Ysafe_malloc(sizeof(VERTEX_BOX)); last_vertexS->x = *llx ; last_vertexS->y = *ury ; last_vertexS->next = NULL ; last_vertexS->macro = 0 ; last_vertexS->class = START ; } found = FALSE ; for( vertex = vertex_listS ;vertex ; vertex = vertex->next ){ if( vertex->x == *urx && vertex->y == *ury ) { found = TRUE ; break ; } } /* end for loop */ if( !found ) { last_vertexS = last_vertexS->next = (VERTEX_BOX *) Ysafe_malloc(sizeof(VERTEX_BOX)); last_vertexS->x = *urx ; last_vertexS->y = *ury ; last_vertexS->next = NULL ; last_vertexS->macro = 0 ; last_vertexS->class = END ; } return(TRUE) ; } /* end find_tile */ BOOL read_vertices(fp,initial) FILE *fp ; BOOL initial ; { /* format of input file: */ /* stdcell_length [x] */ /* actual_row_height [y] --->DOES NOT include channel sep */ /* channel_separation [y] */ /* min_length [x] */ /* core [x] [y] [x] [y] */ /* macro [n] vertices [x][y] ... [x][y] */ /* etc. */ VERTEX_BOX *check_vertex , *vertex ; MACROPTR mptr ; TILE_BOX *tptr ; char string[LRECL] ; INT vert_count ; INT row_length ; INT x , y , i , next_x , next_y ; INT l, r, b, t ; INT last_direction , num_vertices , next_direction ; INT macro , check_macro ; INT xgrid, ygrid ; /* I will assume that the input data is syntactically correct */ fscanf(fp,"%s", string ) ; /* "total_row_length" */ fscanf(fp, INTSCANSTR, &row_length ) ; if( initial ){ stdcell_lengthS = row_length ; } else { if( stdcell_lengthS != row_length ){ sprintf( YmsgG, "Restart file row_length does not match:input(%d) vs restart(%d)\n", stdcell_lengthS, row_length ) ; M( ERRMSG, "read_vertices", YmsgG ) ; M( ERRMSG, NULL, "\tCircuit or grid has changed. Must abort restore state.\n\n" ) ; return( FALSE ) ; } } macro = 0 ; /* if an old macroArray exists blow it away */ if( macroArrayG ){ for( i = 1; i <= num_macrosG; i++ ){ Ysafe_free( macroArrayG[i] ) ; } Ysafe_free( macroArrayG ) ; } free_structures( TRUE ) ; /* free all points */ fscanf(fp,"%s", string ) ; /* "actual_row_height" */ fscanf(fp, INTSCANSTR, &actual_row_heightS ) ; fscanf(fp,"%s", string ) ; /* "channel_separation" */ fscanf(fp, INTSCANSTR, &channel_separationS ) ; fscanf(fp,"%s", string ) ; /* "min_length" */ fscanf(fp, INTSCANSTR, &min_lengthS ) ; fscanf(fp,"%s", string ) ; /* "core" */ fscanf(fp, INTSCANSTR " " INTSCANSTR, &cx1S , &cy1S ) ; fscanf(fp, INTSCANSTR " " INTSCANSTR, &cx2S , &cy2S ) ; fscanf(fp,"%s", string ) ; /* "grid" */ fscanf(fp, INTSCANSTR " " INTSCANSTR, &xgrid , &ygrid ) ; fscanf(fp,"%s", string ) ; /* "num_macros" */ fscanf(fp, INTSCANSTR, &num_macrosG ) ; if( stdcell_lengthS <= 0 ){ M( ERRMSG, "genrow", "No standard cells were found.\n" ) ; M( MSG, NULL, "Make sure Mincut was executed properly.\n" ) ; M( MSG, NULL, "Must exit.\n" ) ; if( graphicsG ){ G( TWcloseGraphics() ) ; } YexitPgm( PGMFAIL ) ; } if( min_lengthS > stdcell_lengthS ){ M( WARNMSG, "read_vertices", "Total row length is smaller that minimum tile length\n" ) ; M( MSG, NULL, "Minimum tile set to total row length / 2\n" ) ; min_lengthS = stdcell_lengthS / 2 ; } init_vertex_list( cx1S, cy1S, cx2S, cy2S ) ; macroArrayG = (MACROPTR *) Ysafe_malloc( (num_macrosG+1) * sizeof(MACROPTR) ) ; for( i = 1; i <= num_macrosG; i++ ){ macroArrayG[i] = (MACROPTR) Ysafe_malloc( sizeof(MACROBOX) ) ; macroArrayG[i]->tiles = NULL ; } if( num_macrosG == 0 ){ /* no work to do */ return( TRUE ) ; } while( fscanf(fp,"%s", string ) == 1 ) { /* "macro" */ /* now initialize vertices array */ mptr = macroArrayG[++macro] ; fscanf(fp,"%s", string ) ; /* orient */ fscanf(fp, INTSCANSTR, &(mptr->orient) ) ; fscanf(fp, INTSCANSTR, &num_vertices ) ; fscanf(fp,"%s", string ) ; /* "vertices" */ mptr->vertices = (VERTEXPTR *) Ysafe_malloc( num_vertices * sizeof(VERTEXPTR)); mptr->num_vertices = num_vertices ; vert_count = 0 ; l = INT_MAX ; r = INT_MIN ; b = INT_MAX ; t = INT_MIN ; for( i = 0 ; i < num_vertices ; i++ ) { fscanf(fp, INTSCANSTR " " INTSCANSTR, &x , &y ) ; if( initial && (x < cx1S || x > cx2S || y < cy1S || y > cy2S) ) { printf("a macro vertex lies outside the core\n"); printf("this is not allowed\n"); printf("macro:%d x:%d y:%d\n",macro,x,y ) ; printf("core: l:%d r:%d b:%d t:%d\n",cx1S,cx2S,cy1S,cy2S ) ; if( graphicsG ){ G( TWcloseGraphics() ) ; } YexitPgm(PGMFAIL); } /* now save the vertex */ vertex = (VERTEX_BOX *) Ysafe_malloc(sizeof(VERTEX_BOX)); vertex->x = x ; vertex->y = y ; vertex->macro = macro ; vertex->next = NULL ; /* save the bounding box of macro */ l = MIN( l, x ) ; r = MAX( r, x ) ; b = MIN( b, y ) ; t = MAX( t, y ) ; /* now save vertex in macro vertex array */ mptr->vertices[vert_count++] = vertex ; } /* now set the xcenter and ycenter fields */ mptr->xcenter = (l + r) / 2 ; mptr->ycenter = (b + t) / 2 ; /* set the relative bounding box */ mptr->left = l - mptr->xcenter ; mptr->right = r - mptr->xcenter ; mptr->bottom = b - mptr->ycenter ; mptr->top = t - mptr->ycenter ; if( macro == num_macrosG ){ break ; } } /* end while loop */ return( TRUE ) ; } /* end read_vertices */ BOOL restore_state( fp ) FILE *fp ; { INT i ; INT numtiles ; INT cur_numtiles ; INT start ; INT diff ; char string[LRECL] ; TILE_BOX *tptr ; TILE_BOX *newtile ; TILE_BOX *last_tile ; /* feed_lengthS */ fscanf(fp,"%s " INTSCANSTR, string , &feed_lengthS ) ; /* spacing */ fscanf(fp,"%s " INTSCANSTR, string , &spacingG ) ; /* numtiles */ fscanf(fp,"%s " INTSCANSTR, string , &numtiles ) ; cur_numtiles = 0 ; for( tptr=tile_listG;tptr;tptr=tptr->next ){ /* count number of tiles for maintaining memory req. */ cur_numtiles++ ; } if( numtiles > cur_numtiles ){ /* add to the number of tiles */ diff = numtiles - cur_numtiles ; tptr = last_tileG ; for( i =1; i <= diff; i++ ){ newtile = (TILE_BOX *) Ysafe_malloc( sizeof(TILE_BOX) ) ; newtile->allocated = TRUE ; tptr->next = newtile ; newtile->prev = tptr ; tptr = newtile ; } newtile->next = NULL ; last_tileG = newtile ; } else if( numtiles < cur_numtiles ){ /* free up some tiles */ cur_numtiles = 0 ; for( tptr=tile_listG;tptr;tptr=tptr->next ){ if( ++cur_numtiles == numtiles ){ break ; } } last_tileG = tptr ; /* free the tile structure */ for( tptr=tptr->next;tptr; ){ last_tile = tptr ; tptr = tptr->next ; Ysafe_free( last_tile ) ; } last_tileG->next = NULL ; update_tile_memory( FALSE ) ; } /* now read in tiles */ for( tptr=tile_listG;tptr;tptr=tptr->next ){ /* 1 if this is the start tile */ fscanf( fp, INTSCANSTR, &start ) ; if( start ){ start_tileG = tptr ; } /* llx, lly, urx, ury, force, class mirror */ fscanf(fp, INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR, &(tptr->llx), &(tptr->lly), &(tptr->urx), &(tptr->ury), &(tptr->force), &(tptr->class), &(tptr->mirror) ) ; /* numrows, actual_row_height, add_no_more_than, chansep */ fscanf(fp, INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR, &(tptr->numrows), &(tptr->actual_row_height), &(tptr->add_no_more_than), &(tptr->channel_separation) ) ; /* min_length, row_start, max_length, illegal */ fscanf(fp, INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR, &(tptr->min_length), &(tptr->row_start), &(tptr->max_length), &(tptr->illegal) ) ; } /* end tile loop */ return( TRUE ) ; } save_state(fp) FILE *fp ; { INT i ; INT vert ; INT cur_numtiles ; TILE_BOX *tptr ; MACROPTR mptr ; VERTEXPTR pt ; fprintf( fp, "total_row_length %d\n", stdcell_lengthS ) ; fprintf( fp, "actual_row_height %d\n", actual_row_heightS ) ; fprintf( fp, "channel_separation %d\n", channel_separationS ) ; fprintf( fp, "min_length %d\n", min_lengthS ) ; fprintf( fp, "core %d %d %d %d\n", cx1S, cy1S, cx2S, cy2S ) ; fprintf( fp, "grid 0 0\n" ) ; fprintf( fp, "num_macro %d\n", num_macrosG ) ; for( i = 1; i <= num_macrosG; i++ ){ mptr = macroArrayG[i] ; fprintf( fp, "macro orient %d %d vertices ", mptr->orient, mptr->num_vertices ) ; for( vert = 0; vert < mptr->num_vertices; vert++ ){ pt = mptr->vertices[vert] ; fprintf( fp, "%d %d ", pt->x, pt->y ) ; } fprintf( fp, "\n" ) ; } fprintf( fp, "feed_length %d\n", feed_lengthS ) ; fprintf( fp, "spacing %d\n", spacingG ) ; cur_numtiles = 0 ; for( tptr=tile_listG;tptr;tptr=tptr->next ){ /* count number of tiles for error checking */ cur_numtiles++ ; } fprintf( fp, "numtiles %d\n", cur_numtiles ) ; for( tptr=tile_listG;tptr;tptr=tptr->next ){ /* 1 if this is the start tile */ if( tptr == start_tileG ){ fprintf( fp, "1 " ) ; } else { fprintf( fp, "0 " ) ; } /* llx, lly, urx, ury, force, class mirror */ fprintf( fp,"%d %d %d %d %d %d %d ", tptr->llx, tptr->lly, tptr->urx, tptr->ury, tptr->force, tptr->class, tptr->mirror ) ; /* numrows, actual_row_height, add_no_more_than, chansep*/ fprintf(fp,"%d %d %d %d ", tptr->numrows, tptr->actual_row_height, tptr->add_no_more_than, tptr->channel_separation ) ; /* min_length, row_start, max_length, illegal */ fprintf(fp,"%d %d %d %d\n", tptr->min_length, tptr->row_start, tptr->max_length, tptr->illegal ) ; } /* end tile loop */ } /* end save_state */ process_vertices() { VERTEXPTR check_vertex , vertex ; VERTEXPTR pt_ptr ; VERTEXPTR *vptr ; MACROPTR mptr ; char string[LRECL] ; INT vert_count ; INT x , y , i , next_x , next_y ; INT last_direction , num_vertices , next_direction ; INT macro , check_macro ; INT xgrid, ygrid ; for( macro = 1; macro <= num_macrosG; macro++ ){ mptr = macroArrayG[macro] ; vptr = mptr->vertices ; num_vertices = mptr->num_vertices ; last_direction = FROM_RIGHT ; x = vptr[0]->x ; y = vptr[0]->y ; for( i = 1 ; i <= num_vertices ; i++ ) { pt_ptr = vptr[i-1] ; /* link all the vertices */ last_vertexS->next = pt_ptr ; last_vertexS = pt_ptr ; if( i < num_vertices ) { next_x = vptr[i]->x ; next_y = vptr[i]->y ; if( next_x == x ) { if( next_y > y ) { next_direction = TO_TOP ; } else { next_direction = TO_BOTTOM ; } } else { if( next_x > x ) { next_direction = TO_RIGHT ; } else { next_direction = TO_LEFT ; } } } else { next_direction = TO_LEFT ; } if( last_direction == FROM_BOTTOM ) { if( next_direction == TO_RIGHT ) { pt_ptr->class = MAYBE_START ; } else { /* TO_LEFT */ pt_ptr->class = NOTHING ; } } else if( last_direction == FROM_TOP ) { if( next_direction == TO_RIGHT ) { pt_ptr->class = START ; } else { /* TO_LEFT */ pt_ptr->class = START ; } } else if( last_direction == FROM_LEFT ) { if( next_direction == TO_TOP ) { pt_ptr->class = END ; } else { /* TO_BOTTOM */ pt_ptr->class = MAYBE_END ; } } else { /* last_direction == FROM_RIGHT */ if( next_direction == TO_TOP ) { pt_ptr->class = END ; } else { /* TO_BOTTOM */ pt_ptr->class = NOTHING ; } } if( next_direction == TO_TOP ) { last_direction = FROM_BOTTOM ; } else if( next_direction == TO_BOTTOM ) { last_direction = FROM_TOP ; } else if( next_direction == TO_RIGHT ) { last_direction = FROM_LEFT ; } else { /* next_direction == TO_LEFT */ last_direction = FROM_RIGHT ; } x = next_x ; /* set for the next time thru the loop */ y = next_y ; } } /* see if the MAYBE_START vertices should really be START */ /* this transformation happens when macros abut or when a */ /* macro touches the left or right core boundary */ for( check_vertex=vertex_listS;check_vertex;check_vertex=check_vertex->next ){ if( check_vertex->class == MAYBE_START ) { /* perform the check */ check_macro = check_vertex->macro ; for( vertex = vertex_listS ;vertex ; vertex = vertex->next ){ if( vertex->macro != check_macro && vertex->next && vertex->macro == vertex->next->macro && vertex->x == vertex->next->x && vertex->x == check_vertex->x ) { if( vertex->y > vertex->next->y ) { if( check_vertex->y > vertex->next->y && check_vertex->y < vertex->y ) { check_vertex->class = START ; break ; } } else { if( check_vertex->y < vertex->next->y && check_vertex->y > vertex->y ) { check_vertex->class = START ; break ; } } } } /* end for loop */ } /* end if */ } /* end for loop */ for( check_vertex=vertex_listS;check_vertex;check_vertex=check_vertex->next ){ if( check_vertex->class == MAYBE_END ) { /* perform the check */ check_macro = check_vertex->macro ; for( vertex = vertex_listS ;vertex ; vertex = vertex->next ){ if( vertex->macro != check_macro && vertex->next && vertex->macro == vertex->next->macro && vertex->x == vertex->next->x && vertex->x == check_vertex->x ) { if( vertex->y > vertex->next->y ) { if( check_vertex->y > vertex->next->y && check_vertex->y < vertex->y ) { check_vertex->class = END ; break ; } } else { if( check_vertex->y < vertex->next->y && check_vertex->y > vertex->y ) { check_vertex->class = END ; break ; } } } } /* end inner for loop */ } /* end if */ } /* end outer for loop */ return ; } /* end process_vertices */ build_macros() { INT i ; INT j ; MACROPTR mptr ; VERTEXPTR vptr ; MACRO_TILE *tptr ; MACRO_TILE *last_tile ; YBUSTBOXPTR bustptr ; if( num_macrosG <= 0 ){ return ; } /* otherwise we have macro tiles to build */ for( i = 1 ; i <= num_macrosG ; i++ ){ mptr = macroArrayG[i] ; /* first remove old tiles if they exist */ for( tptr = mptr->tiles;tptr; ){ last_tile = tptr ; tptr = tptr->next ; Ysafe_free( last_tile ) ; } mptr->tiles = NULL ; Ybuster_init() ; for( j = 0; j < mptr->num_vertices; j++ ){ vptr = mptr->vertices[j] ; Ybuster_addpt( vptr->x, vptr->y ) ; } while( bustptr = Ybuster() ){ /* l = bustptr[1].x ; */ /* r = bustptr[4].x ; */ /* b = bustptr[1].y ; */ /* t = bustptr[2].y ; */ last_tile = mptr->tiles ; tptr = mptr->tiles = (MACRO_TILE *) Ysafe_malloc( sizeof(MACRO_TILE) ) ; tptr->next = last_tile ; /* now fill in the data */ tptr->l = bustptr[1].x ; tptr->r = bustptr[4].x ; tptr->b = bustptr[1].y ; tptr->t = bustptr[2].y ; } } Ybuster_free() ; check_overlap() ; } /* end build_macros */ makerows() { TILE_BOX *tileptr, *get_starting_tile() ; ROW_BOX *rowptr , *segment ; DOUBLE amount , total ; INT row_length_so_far , count , actually_added , add_no_more_than ; INT num_segments, llx, width ; BOOL top_rows ; row_length_so_far = 0 ; number_of_rows_addedS = 0 ; number_of_segs_addedS = 0 ; /* traverse thru tile list */ if( !(tileptr = start_tileG )){ tileptr = tile_listG ; } total_row_lengthS = stdcell_lengthS + feed_lengthS ; total_row_segmentS = 0 ; for( ; tileptr ; tileptr = tileptr->next ){ add_no_more_than = total_row_lengthS - row_length_so_far ; row_length_so_far += convert_tile_to_rows( tileptr, add_no_more_than ) ; } /* Check if we can get row_length_so_far closer to total_row_length by adding a row across the top of the core */ if( last_tileG->numrows >= 1 ){ top_rows = TRUE ; } else { top_rows = FALSE ; } width = last_tileG->max_length ; llx = last_tileG->llx + last_tileG->row_start ; /* initiallly set width of row to max length of tile */ while( cx2S - cx1S + row_length_so_far <= total_row_lengthS ) { if( last_rowptrS == NULL ) { set_of_rowsS = (ROW_BOX *) Ysafe_malloc( sizeof( ROW_BOX ) ) ; rowptr = last_rowptrS = set_of_rowsS ; } else { rowptr = last_rowptrS->next_row = (ROW_BOX *) Ysafe_malloc( sizeof( ROW_BOX ) ) ; last_rowptrS = rowptr ; } top_rows = TRUE ; rowptr->next_row = NULL ; rowptr->next_segment = NULL ; rowptr->class = last_tileG->class ; rowptr->mirror = last_tileG->mirror ; rowptr->seg = ++number_of_segs_addedS ; rowptr->llx = cx1S ; rowptr->lly = cy2S ; rowptr->urx = cx2S ; rowptr->ury = cy2S + actual_row_heightS + channel_separationS ; cy2S += actual_row_heightS + channel_separationS ; row_length_so_far += cx2S - cx1S ; number_of_rows_addedS++ ; } /* make sure the last row is a full row if short */ if(!(shortRowG)){ if( top_rows ){ last_rowptrS->llx = llx ; last_rowptrS->urx = llx + width ; } } D( "genrows/placed_amount", if( total_row_lengthS - row_length_so_far ){ fprintf( stderr, "Warning:Total row length requested exceeds placed row length by:%d\n", total_row_lengthS - row_length_so_far ) ; } else { fprintf( stderr, "Total row length requested equals placed row length\n") ; } ) ; /* now divide up feedthru length among segments */ /* feed length is only an approximation so don't worry about remainder */ if( total_row_segmentS > 0 ){ feeds_per_segG = feed_lengthS / total_row_segmentS ; } else { feeds_per_segG = 0 ; } return ; } /* end makerows */ BOOL convert_tile_to_rows( tileptr, add_no_more_than ) /* Purpose: given a rectangular tile region, generate a set of rows which covers this region */ /* returns the total length of rows generated for this tile */ TILE_BOX *tileptr ; INT add_no_more_than ; { INT llx , lly ; /* lower left x and y coordinates */ INT urx , ury ; /* upper right x and y coordinates */ INT width ; INT totalw ; INT shortage ; INT actual_row_height ; INT channel_separation ; ROW_BOX *rowptr , *saveptr ; INT horiz_line , mismatch , overlap ; INT row_segments_generated ; INT chan_sep_below_row , row_height ; INT half_chan_sep_above_row ; INT chan_sep_above_row ; INT limit ; INT numrows ; INT proposed_length ; /* form local variables for speed */ actual_row_height = tileptr->actual_row_height ; channel_separation = tileptr->channel_separation ; llx = tileptr->llx ; lly = tileptr->lly ; urx = tileptr->urx ; ury = tileptr->ury ; /* reset add_no_more_than parameter if uses has set it for this tile*/ if( tileptr->add_no_more_than ){ add_no_more_than = MIN( add_no_more_than, tileptr->add_no_more_than ) ; } row_height = actual_row_height + channel_separation ; chan_sep_below_row = channel_separation / 2 ; chan_sep_above_row = channel_separation - channel_separation / 2 ; half_chan_sep_above_row = chan_sep_above_row / 2 ; width = tileptr->max_length ; /* initiallly set width of row to max length of tile */ if( urx - llx < tileptr->min_length || tileptr->illegal || width < tileptr->min_length ) { return(FALSE) ; } row_segments_generated = 0 ; totalw = 0 ; horiz_line = lly ; /* now calculate the new llx base on the given offset from beginning of tile */ llx += tileptr->row_start ; /* the offset from beginning of tile normally 1 */ if( tileptr->force && tileptr->numrows > 0 ){ /* see if we need to modify the start and stop of row to accommodate */ /* exactly n rows */ proposed_length = tileptr->numrows * width ; numrows = tileptr->numrows ; if( proposed_length > add_no_more_than ){ shortage = proposed_length - add_no_more_than ; /* calculate shortage per row */ shortage /= tileptr->numrows ; tileptr->max_length = width -= shortage ; /* break up the shortage evenly between start and stop */ /* shortage /= 2 ; llx += shortage ; tileptr->row_start += shortage ; */ } } else { numrows = 0 ; } /* now reset the number of rows */ tileptr->numrows = 0 ; while( horiz_line + chan_sep_below_row + actual_row_height + half_chan_sep_above_row <= ury ){ if( totalw >= add_no_more_than ){ /* we are done */ break ; } if( tileptr->force && tileptr->numrows > 0 && tileptr->numrows >= numrows){ break ; } /* see if we will get closer if we add another segment */ proposed_length = (row_segments_generated+1) * tileptr->max_length ; if( proposed_length > add_no_more_than ) { /* try setting width to the shortage if we allow a short row */ if( shortRowG || ( !(shortRowG) && number_of_rows_addedS < 1) ){ /* second clause is special case when only very */ /* small number of standard cells */ width = add_no_more_than - totalw ; } else { /* we will round up or down to the closest row */ limit = (INT) ( (DOUBLE) 0.50 * (DOUBLE) width ) ; if( proposed_length - add_no_more_than > limit ){ /* we will be over limit if we add another row */ break ; } } } /* *********************************************************** Propose a new row : proposed row coord's: (llx, horiz_line + chan_sep_below_row), (llx+width,horiz_line + chan_sep_below_row + actual_row_height ) check if proposed row has a partial overlap - in the y direction - with any other row segment. if so, we merge the two and create an exception *************************************************************/ for( rowptr = set_of_rowsS ;rowptr; rowptr = rowptr->next_row ) { if( !(rowptr->lly - chan_sep_below_row >= horiz_line + channel_separation + actual_row_height || rowptr->ury + chan_sep_above_row <= horiz_line) ) { /* try to line up these row segments */ /* try to shift up proposed row by an amount equal to their mismatch in the y direction */ mismatch = rowptr->lly - (horiz_line + chan_sep_below_row) ; if( mismatch < 0 ) { horiz_line += channel_separation + actual_row_height + mismatch ; } else { horiz_line += mismatch ; } if( horiz_line + chan_sep_below_row + half_chan_sep_above_row + actual_row_height > ury ) { /* row won't fit anymore */ return(FALSE) ; } break ; } } /* end for loop */ /* check if we need to add a row segment to an existing row */ overlap = FALSE ; for( rowptr = set_of_rowsS ;rowptr; rowptr = rowptr->next_row ) { if( !(rowptr->lly - chan_sep_below_row >= horiz_line + channel_separation + actual_row_height || rowptr->ury + chan_sep_above_row <= horiz_line) ) { /* the proposed row is thus part of a larger row */ tileptr->numrows++ ; saveptr = rowptr->next_segment ; rowptr->next_segment = (ROW_BOX *) Ysafe_malloc( sizeof( ROW_BOX ) ) ; rowptr->next_segment->next_segment = saveptr ; rowptr = rowptr->next_segment ; rowptr->class = tileptr->class ; rowptr->mirror = tileptr->mirror ; rowptr->seg = ++number_of_segs_addedS ; rowptr->llx = llx ; rowptr->lly = horiz_line + chan_sep_below_row ; rowptr->urx = llx + width ; rowptr->ury = horiz_line + chan_sep_below_row + actual_row_height ; overlap = TRUE ; break ; } } /* end for loop */ if( !overlap ) { /* start a new row */ number_of_rows_addedS++ ; tileptr->numrows++ ; if(!(last_rowptrS)) { set_of_rowsS = (ROW_BOX *) Ysafe_malloc( sizeof( ROW_BOX ) ) ; set_of_rowsS->next_row = NULL ; set_of_rowsS->next_segment = NULL ; set_of_rowsS->class = tileptr->class ; set_of_rowsS->mirror = tileptr->mirror ; set_of_rowsS->seg = ++number_of_segs_addedS ; set_of_rowsS->llx = llx ; set_of_rowsS->lly = horiz_line + chan_sep_below_row ; set_of_rowsS->urx = llx + width ; set_of_rowsS->ury = horiz_line + chan_sep_below_row + actual_row_height ; last_rowptrS = set_of_rowsS ; } else { last_rowptrS->next_row = (ROW_BOX *) Ysafe_malloc( sizeof( ROW_BOX ) ) ; last_rowptrS = last_rowptrS->next_row ; last_rowptrS->next_row = NULL ; last_rowptrS->next_segment = NULL ; last_rowptrS->class = tileptr->class ; last_rowptrS->mirror = tileptr->mirror ; last_rowptrS->seg = ++number_of_segs_addedS ; last_rowptrS->llx = llx ; last_rowptrS->lly = horiz_line + chan_sep_below_row ; last_rowptrS->urx = llx + width ; last_rowptrS->ury = horiz_line + chan_sep_below_row + actual_row_height ; } } row_segments_generated++ ; horiz_line += row_height ; totalw += width ; } total_row_segmentS += row_segments_generated ; return( totalw ) ; } /* end convert_tile_to_rows */ divide_tile( tile , horiz_line ) TILE_BOX *tile ; INT horiz_line ; { TILE_BOX *new_tile ; INT orig_top ; new_tile = (TILE_BOX *) Ysafe_malloc( sizeof(TILE_BOX) ) ; new_tile->next = tile->next ; tile->next = new_tile ; /* now fix the backlinks */ new_tile->prev = tile ; new_tile->next->prev = new_tile ; orig_top = tile->ury ; tile->ury = horiz_line ; /* the orig. tile stops at horiz_line */ new_tile->lly = horiz_line ;/* the new tile begins at horiz_line */ new_tile->ury = orig_top ;/* the new tile top is the old one's top */ new_tile->llx = tile->llx ; new_tile->urx = tile->urx ; new_tile->merged = MERGED_NONE ; new_tile->actual_row_height = tile->actual_row_height ; new_tile->channel_separation = tile->channel_separation ; new_tile->min_length = tile->min_length ; new_tile->max_length = tile->max_length ; new_tile->row_start = tile->row_start ; new_tile->numrows = 0 ; new_tile->illegal = tile->illegal ; new_tile->force = tile->force ; new_tile->add_no_more_than = tile->add_no_more_than ; new_tile->class = tile->class ; new_tile->mirror = tile->mirror ; new_tile->allocated = TRUE ; return ; } /* end divide_tile */ divide_tilelr( tile , vert_line ) TILE_BOX *tile ; INT vert_line ; { TILE_BOX *new_tile ; INT orig_right ; new_tile = (TILE_BOX *) Ysafe_malloc( sizeof(TILE_BOX) ) ; new_tile->next = tile->next ; tile->next = new_tile ; /* now fix the backlinks */ new_tile->prev = tile ; new_tile->next->prev = new_tile ; orig_right = tile->urx ; tile->urx = vert_line ; /* the orig. tile stops at vert_line */ new_tile->llx = vert_line ;/* the new tile begins at vert_line */ new_tile->urx = orig_right ;/* the new tile top is the old one's rite */ new_tile->lly = tile->lly ; new_tile->ury = tile->ury ; new_tile->merged = MERGED_NONE ; new_tile->actual_row_height = tile->actual_row_height ; new_tile->channel_separation = tile->channel_separation ; new_tile->min_length = tile->min_length ; new_tile->row_start = tile->row_start ; new_tile->numrows = 0 ; new_tile->illegal = tile->illegal ; new_tile->force = tile->force ; new_tile->add_no_more_than = tile->add_no_more_than ; new_tile->class = tile->class ; new_tile->mirror = tile->mirror ; new_tile->max_length = new_tile->urx - new_tile->llx - 2 * spacingG ; tile->max_length = tile->urx - tile->llx - 2 * spacingG ; new_tile->allocated = TRUE ; return ; } /* end divide_tilelr */ get_core( left, bottom, right, top, tileFlag ) INT *left, *bottom, *right, *top ; BOOL tileFlag ; /* if true include the tiles in core */ { INT l, r, b, t ; TILE_BOX *tileptr ; /* expanded core is max over given core and tiles */ l = cx1S ; b = cy1S ; r = cx2S ; t = cy2S ; if( tileFlag ){ for( tileptr=tile_listG;tileptr;tileptr=tileptr->next ){ l = MIN( l, tileptr->llx ) ; b = MIN( b, tileptr->lly ) ; r = MAX( r, tileptr->urx ) ; t = MAX( t, tileptr->ury ) ; } } D( "genrows/get_core",printf( "l:%d r:%d b:%d t:%d\n", l,r,b,t )); *left = l ; *right = r ; *bottom = b ; *top = t ; return ; } /* end get_core */ ROW_BOX *get_rowptr() { return( set_of_rowsS ) ; } /* end get_rowptr */ grid_rows() { ROW_BOX *rowptr , *segment ; INT oldX, oldY ; for( rowptr = set_of_rowsS ; rowptr ; rowptr = rowptr->next_row ){ oldX = rowptr->llx ; oldY = rowptr->lly ; YforceGrid( &(rowptr->llx), &(rowptr->lly) ) ; rowptr->urx += rowptr->llx - oldX ; rowptr->ury += rowptr->lly - oldY ; for( segment=rowptr->next_segment;segment;segment=segment->next_segment){ oldX = segment->llx ; oldY = segment->lly ; YforceGrid( &(segment->llx), &(segment->lly) ) ; segment->urx += segment->llx - oldX ; segment->ury += segment->lly - oldY ; } } } /* end grid_rows */ set_minimum_length( length ) INT length ; { TILE_BOX *tileptr ; /* current tile */ min_lengthS = length ; for( tileptr=tile_listG;tileptr;tileptr=tileptr->next ){ tileptr->min_length = min_lengthS ; } } /* end set_minimum_length */ set_row_separation( channel_sep_relative, channel_sep_absolute ) DOUBLE channel_sep_relative; INT channel_sep_absolute; { TILE_BOX *tileptr ; /* current tile */ channel_separationS = (INT) (channel_sep_relative *(DOUBLE) actual_row_heightS) + channel_sep_absolute; for( tileptr=tile_listG;tileptr;tileptr=tileptr->next ){ tileptr->channel_separation = channel_separationS ; } } /* end set_row_separation */ set_spacing() { TILE_BOX *tileptr ; /* current tile */ for( tileptr=tile_listG;tileptr;tileptr=tileptr->next ){ tileptr->row_start = spacingG ; tileptr->max_length = tileptr->urx - tileptr->llx - 2 * spacingG ; if( tileptr->max_length < 0 ){ tileptr->max_length = 0 ; } } } /* end set_spacing */ BOOL force_tiles() { TILE_BOX *tile ; /* current tile */ for( tile=last_tileG; tile; tile = tile->prev ){ if( tile == last_tileG ){ /* don't do anything in this case */ break ; } if( tile->numrows > 0 ){ tile->force = TRUE ; return( TRUE ) ; } } return( FALSE ) ; } /* end force_tiles */ check_user_data() { if( min_lengthS < spacingG ){ M( ERRMSG, "check_user_errors", "minimum row length < tile_to_row_spacing. Reset\n" ) ; set_minimum_length( spacingG + 2 ) ; } } /* end check_user_errors */ remakerows() { ROW_BOX *freerow, *freeseg ; /* used to free data */ ROW_BOX *segptr ; /* traverse segments freeing them */ /* free memory if allocated before calling make rows again */ for( ; set_of_rowsS ; ){ /* keep memory of where row was */ /* first free segments of the row */ for( segptr = set_of_rowsS->next_segment;segptr; ){ freeseg = segptr ; segptr = segptr->next_segment ; Ysafe_free( freeseg ) ; } freerow = set_of_rowsS ; set_of_rowsS = set_of_rowsS->next_row ; Ysafe_free( freerow ) ; } last_rowptrS = NULL ; /* now everything has been freed - ok to make rows */ makerows() ; D( "genrows/numrows", fprintf( stderr, "Number of rows = %d\n", number_of_rows_addedS ) ; ) ; } /* end remakerows */ init_vertex_list( left, bottom, right, top ) INT left, bottom, right, top ; { /* start the vertex list */ last_vertexS = vertex_listS = (VERTEX_BOX *) Ysafe_malloc( sizeof( VERTEX_BOX ) ) ; last_vertexS->x = right ; last_vertexS->y = bottom ; last_vertexS->macro = 0 ; last_vertexS->class = END ; last_vertexS = last_vertexS->next = (VERTEX_BOX *) Ysafe_malloc( sizeof( VERTEX_BOX ) ) ; last_vertexS->x = right ; last_vertexS->y = top ; last_vertexS->macro = 0 ; last_vertexS->class = NOTHING ; last_vertexS = last_vertexS->next = (VERTEX_BOX *) Ysafe_malloc( sizeof( VERTEX_BOX ) ) ; last_vertexS->x = left ; last_vertexS->y = top ; last_vertexS->macro = 0 ; last_vertexS->class = NOTHING ; last_vertexS = last_vertexS->next = (VERTEX_BOX *) Ysafe_malloc( sizeof( VERTEX_BOX ) ) ; last_vertexS->x = left ; last_vertexS->y = bottom ; last_vertexS->macro = 0 ; last_vertexS->class = START ; last_vertexS->next = NULL ; } /* end init_vertex_list */ static VOID free_tile( tile ) TILE_BOX *tile ; { Ysafe_free( tile ) ; } /* end free_tile */ free_structures( allpts ) BOOL allpts ; { TILE_BOX *last_tile ; VERTEXPTR vertex ; /* current point */ VERTEXPTR free_vertex ; /* used to free point */ /* first initialize vertex array */ for( vertex = vertex_listS ;vertex; ){ free_vertex = vertex ; vertex = vertex->next ; if( allpts || free_vertex->macro == 0 ){ /* free only the non macro points */ Ysafe_free( free_vertex ) ; } else { /* reset the link field */ free_vertex->next = NULL ; } } } update_tile_memory( free_flag ) BOOL free_flag ; { TILE_BOX *tile ; /* free the tile structure */ if( free_flag ){ Yrbtree_empty( tile_memoryG, free_tile ) ; } else { Yrbtree_empty( tile_memoryG, NULL ) ; } /* put the new tiles in the tree */ for( tile=tile_listG ;tile;tile = tile->next ){ Yrbtree_insert( tile_memoryG, tile ) ; } } /* end update_tile_memory */ recalculate( freepts ) BOOL freepts ; { BOOL previous_invalid_state ; previous_invalid_state = invalidG ; update_tile_memory( TRUE ) ; if( freepts ){ /* if we are asked to free points this means recalculation */ /* is not from a reread of the points. Therefore keep macros*/ free_structures( FALSE ) ; } find_core() ; init_vertex_list( cx1S, cy1S, cx2S, cy2S ) ; build_macros() ; process_vertices() ; process_tiles() ; merge_tiles() ; check_tiles() ; if( memoryG && !(previous_invalid_state) ){ reset_tile_parameters() ; } } /* end recalculate */ find_core() { INT macro ; INT left, rite, bot, top ; INT i ; INT num_vertices ; MACROPTR mptr ; VERTEXPTR *vptr ; VERTEXPTR pt_ptr ; for( macro = 1; macro <= num_macrosG; macro++ ){ mptr = macroArrayG[macro] ; vptr = mptr->vertices ; num_vertices = mptr->num_vertices ; for( i = 0 ; i < num_vertices ; i++ ) { pt_ptr = vptr[i] ; /* find the limits over all vertices */ cx1S = MIN( cx1S, pt_ptr->x ) ; cx2S = MAX( cx2S, pt_ptr->x ) ; cy1S = MIN( cy1S, pt_ptr->y ) ; cy2S = MAX( cy2S, pt_ptr->y ) ; } } } /* end find_core */ BOOL snap_core( l, r, b, t ) INT *l, *r, *b, *t ; { INT width ; /* new width of core */ INT height ; /* new width of core */ INT numtiles ; /* number of tiles with rows */ INT total_sep ; /* total row separation */ TILE_BOX *tileptr ; /* current tile */ if( num_macrosG > 0 ){ return( FALSE ) ; } /* need to determine the current values of channel_separation */ /* take the average of the tiles */ total_sep = 0 ; numtiles = 0 ; for( tileptr=tile_listG;tileptr;tileptr=tileptr->next ){ if( tileptr->numrows > 0 ){ total_sep += tileptr->channel_separation ; numtiles++ ; } } /* set channel_separation to average channel separation */ channel_separationS = total_sep / numtiles ; height = number_of_rows_addedS * actual_row_heightS + number_of_rows_addedS * channel_separationS ; /* take into account the start and end of the row thru spacingG */ width = (total_row_lengthS+2*number_of_rows_addedS+ 2*spacingG*number_of_rows_addedS) / number_of_rows_addedS ; if( total_row_lengthS % number_of_rows_addedS ){ width++ ; } *l = cx1S ; *r = cx1S + width ; *b = cy1S ; *t = cy1S + height ; return( TRUE ) ; } /* end snap_core */ set_core( left, right, bottom, top ) INT left, right, bottom, top ; { cx1S = left ; cx2S = right ; cy1S = bottom ; cy2S = top ; } /* end set_core */ check_overlap() { INT macro ; INT match ; MACRO_TILE *tilea ; MACRO_TILE *tileb ; INT projectX() ; INT projectY() ; invalidG = FALSE ; for( macro = 1; macro <= num_macrosG; macro++ ){ tilea = macroArrayG[macro]->tiles ; if(!(tilea)){ continue ; } for( match = macro+1; match <= num_macrosG; match++ ){ tileb = macroArrayG[match]->tiles ; if(!(tileb)){ continue ; } /* now check for overlap */ if( projectY( tilea->b, tilea->t, tileb->b, tileb->t) ){ if( projectX( tilea->l,tilea->r,tileb->l,tileb->r )){ sprintf( YmsgG, "Macro %d overlaps macro %d.\n", macro, match ) ; M(ERRMSG, "check_overlap", YmsgG ) ; invalidG = TRUE ; } } } } if( invalidG ){ M(ERRMSG, NULL, "Results are invalid. Turn on draw macros to locate overlap\n\n"); } } /********* end check of tiles ***********/ static INT xspaceS = 0 ; static INT yspaceS = 0 ; /* function returns whether one cell projects onto another */ INT projectX( tile1_left, tile1_right, tile2_left, tile2_right ) INT tile1_left, tile1_right, tile2_left, tile2_right ; { /* ----------------------------------------------------- First check case 2nd tile larger than first complete overlap */ if( tile2_left <= tile1_left && tile1_right <= tile2_right ){ return( OVERLAP1 ) ; /* ----------------------------------------------------- Check if an edge of tile two is encompassed by tile 1 Second check left edge of tile2 : tile1_left <= tile2_left < tile1_right + xspaceG */ } else if( tile1_left<=tile2_left&&tile2_leftnext_row ){ count++ ; } return( count ) ; } /* end count_rows */ #endif /* NEEDED */ calculate_numrows() { INT l, r, b, t ; /* dimensions of new core */ if( num_macrosG <= 0 ){ /* first count rows and set bounds */ number_of_rows_addedS = num_rowsG ; snap_core( &l, &r, &b, &t ) ; set_core( l, r, b, t ) ; start_tileG = NULL ; /* now we need to redo all the work we have done before */ recalculate(TRUE) ; /* free data */ remakerows() ; } else { /* binary search to find correct row separation */ #ifdef LATER while( low <= high ){ mid = low + (high-low) / 2 ; switch (c = SIGN(strcmp(mid->rw_name, yytext))) { case -1: low = mid + 1; break; case 0: return(mid->rw_yylex); break; case 1: high = mid - 1; break; } /* switch ... */ } #endif } } /* calculate_numrows */ static INT compare_tiles( tile1, tile2 ) TILE_BOX *tile1, *tile2 ; { /* sort by x then y */ if( tile1->llx < tile2->llx ){ return( -1 ) ; } else if( tile1->llx > tile2->lly ){ return( 1 ) ; } else { if( tile1->lly < tile2->lly ){ return( -1 ) ; } else { return( 1 ) ; } } } /* end compare_tiles */ static reset_tile_parameters() { TILE_BOX lo ; /* low sentinel */ TILE_BOX hi ; /* hi sentinel */ TILE_BOX *ntile ; /* the new tile */ TILE_BOX *otile ; /* the old tile */ TILE_BOX *match_tile ; /* the old tile with the most area in common*/ INT overlapx ; /* type of x overlap */ INT overlapy ; /* type of y overlap */ FLOAT area ; /* area of overlap between new and old tiles */ FLOAT deltay ; /* area of overlap in y direction */ FLOAT largest_area ; /* old tile with largest amount of overlap */ for( ntile=tile_listG;ntile;ntile = ntile->next ){ lo.llx = INT_MIN ; lo.lly = INT_MIN ; hi.llx = ntile->urx ; hi.lly = INT_MIN ; largest_area = 0.0 ; area = 0.0 ; match_tile = NULL ; for(otile=(TILE_BOX *)Yrbtree_interval(tile_memoryG,&lo,&hi,TRUE); otile ; otile=(TILE_BOX *)Yrbtree_interval(tile_memoryG,&lo,&hi,FALSE)){ if(!(otile->allocated)){ /* it has already been deleted */ continue ; } if( overlapy = projectY( ntile->lly,ntile->ury,otile->lly-1,otile->ury+1)){ if( overlapy == TOUCH ){ continue ; } if( overlapx = projectX( ntile->llx,ntile->urx,otile->llx-1,otile->urx+1 )){ if( overlapx == TOUCH ){ continue ; } switch( overlapy ){ case OVERLAP1: /* complete overlap in y direction */ deltay = (ntile->ury - ntile->lly ) ; switch( overlapx ){ case OVERLAP1: area = (ntile->urx - ntile->llx) * deltay ; break ; case OVERLAP2: /* old tile to the right */ area = (ntile->urx - otile->llx) * deltay ; break ; case OVERLAP3: /* old tile to the left */ area = (otile->urx - ntile->llx) * deltay ; break ; } /* end switch( overlapx ... */ break ; case OVERLAP2: /* old tile above new tile */ deltay = (ntile->ury - otile->lly ) ; switch( overlapx ){ case OVERLAP1: area = (ntile->urx - ntile->llx) * deltay ; break ; case OVERLAP2: /* old tile to the right */ area = (ntile->urx - otile->llx) * deltay ; break ; case OVERLAP3: /* old tile to the left */ area = (otile->urx - ntile->llx) * deltay ; break ; } /* end switch( overlapx ... */ break ; case OVERLAP3: deltay = (otile->ury - ntile->lly ) ; switch( overlapx ){ case OVERLAP1: area = (ntile->urx - ntile->llx) * deltay ; break ; case OVERLAP2: /* old tile to the right */ area = (ntile->urx - otile->llx) * deltay ; break ; case OVERLAP3: /* old tile to the left */ area = (otile->urx - ntile->llx) * deltay ; break ; } /* end switch( overlapx ... */ break ; } /* end switch( overlapy... */ } /* end if( overlapx = projectX... */ } /* end if( overlapy = projectY... */ if( area > largest_area ){ largest_area = area ; match_tile = otile ; } } /* end of Yrbtree_interval search */ if( match_tile ){ /* then it is safe to inherit properties */ ntile->numrows = match_tile->numrows ; ntile->class = match_tile->class ; ntile->actual_row_height = match_tile-> actual_row_height ; ntile->add_no_more_than = match_tile->add_no_more_than ; ntile->channel_separation = match_tile->channel_separation ; ntile->min_length = match_tile->min_length ; ntile->row_start = match_tile->row_start ; ntile->illegal = match_tile->illegal ; ntile->force = match_tile->force ; ntile->mirror = match_tile->mirror ; /* the tricky one max length */ if( match_tile->max_length > ntile->urx - ntile->llx - ntile->row_start - spacingG ){ /* we need to reset the maximum length */ ntile->max_length = ntile->urx - ntile->llx - ntile->row_start - 2*spacingG ; } else { ntile->max_length = match_tile->max_length ; } } } /* end loop on ntiles */ } /* end reset_tile_parameters */ graywolf-0.1.4+20170307gite1bf319/src/genrows/genrows.dialog000066400000000000000000000051621305746555600231100ustar00rootroot00000000000000numfields;39 # "@(#) genrows.dialog (Yale) version 3.4 1/25/91" # Here is how you make a dialog box. # Semicolons are delimiters # field;fieldnumber;xpos;ypos;init string;field length; # (continued) field type;color;case toggle # Field types are # accept - mandatory # reject - mandatory # label - write only field. # input - read write field # case - a set of case field to follow # the first field in the list is the initial case. # clabel - one of the case fields. # field number must start with 0 field;0; 5;1 ; ACCEPT ; 8;accept;green field;1; 25;1 ; CANCEL ; 8;reject;red field;2; 15;2 ;Tile Edit; 9;label;red field;3; 5;3 ;Tile :; 6;label;blue field;4; 5;4 ;Left :; 6;label;blue field;5; 5;5 ;Bottom:; 6;label;blue field;6; 5;6 ;Right :; 6;label;blue field;7; 5;7 ;Top :; 6;label;blue field;8; 5;9 ;Legal Tile; 10;case;blue;9,10 field;9; 25;9 ;YES; 3;clabel;green field;10; 31;9 ;NO; 2;clabel;red field;11; 5;10 ;Row Height :;21;label;blue field;12; 25;10 ; ; 8;input;blue field;13; 5;11 ;Max. No. of Rows :;21;label;blue field;14; 25;11 ; ; 8;input;blue field;15; 5;12 ;Number of Rows :;21;label;blue field;16; 25;12 ; ; 8;input;blue field;17; 5;13 ;Force No. of Rows :;19;case;blue;17,16 field;18; 25;13 ;YES; 3;clabel;green field;19; 31;13 ;NO; 2;clabel;red field;20; 5;14 ;Min. length of row:;21;label;blue field;21; 25;14 ; ; 8;input;blue field;22; 5;15 ;Start of row :;21;label;blue field;23; 25;15 ; ; 8;input;blue field;24; 5;16 ;End of row :;21;label;blue field;25; 25;16 ; ; 8;input;blue field;26; 5;17 ;Channel separation:;21;label;blue field;27; 25;17 ; ; 8;input;blue field;28; 5;18 ;Default Class :;21;label;blue field;29; 25;18 ; ; 8;input;blue field;30; 5;19 ;Mirror rows :;19;case;blue;32,31 field;31; 25;19 ;YES; 3;clabel;green field;32; 31;19 ;NO; 2;clabel;red # directions field;33;1;21;To change case fields put pointer;35;label;blue field;34;1;22;in window and click. To change;35;label;blue field;35;1;23;input fields put pointer in window;35;label;blue field;36;1;24;and back up over current contents;35;label;blue field;37;1;25;using the delete key. After modifying;35;label;blue field;38;1;26;the field, hit the return key.;35;label;blue graywolf-0.1.4+20170307gite1bf319/src/genrows/genrows_menu000066400000000000000000000056641305746555600227050ustar00rootroot00000000000000# # Copyright (C) 1991 Yale University # # This work is distributed in the hope that it will be useful; you can # redistribute it and/or modify it under the terms of the # GNU General Public License as published by the Free Software Foundation; # either version 2 of the License, # or any later version, on the following conditions: # # (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS # ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, # SALE OR # OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY # PATENT OR # OTHER RIGHTS NOT VESTED IN YALE. # # (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND # WARRANTIES # WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, # INCLUDING, # BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A # PARTICULAR # PURPOSE. # # (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES # WHATSOEVER TO # ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN # ARTICLE # (a) AND (b) above. # # (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, # EMPLOYEES AND # AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR # INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE # ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE # POSSIBILITY OF THE FOREGOING. # # genrows menu file. # "@(#) genrows_menu (Yale) version 3.15 9/21/91" # # Comments start with a sharp # MENU is a keyword must be capitalized. # Everything in this file is case sensitive. # Fields are separated by commas. # Format: # MENU,menuName - followed by list of entries for this menu # - one on each line. # Normal menu entry - MenuEntry,FunctionNumber # Boolean menu entry - # TrueMenuEntry,FunctionNumber1,FalseMenuEntry,FunctionNumber2,Init # where Init is the initial state and is 1 for True and 0 for False. # # Menu are placed on the screen in a left to right order according # to the order in this file. # MENU,CONTROL Auto Redraw On,1,Auto Redraw Off,2,1 Close Graphics,3 Colors,4 Continue Pgm,5 Dump Graphics,6 FullView,7 Redraw,8 Tell Point,9 Translate,10 Zoom,11 Cancel,0 MENU,EDIT Align Macro in X,12 Align Macro in Y,13 Align Rows,14 Edit Macro,16 Edit Row,15 Edit Tile,17 Keep Short Row,18,Discard Short Row,19,0 Memory On,51,Memory Off,52,1 Modify Core Area,20 Move Macro,21 Numrows,22 Redo,23 Restore State,24 Save State,25 Undo,27 Cancel,0 MENU,MERGE Divide Tile Left_Right,28 Divide Tile Up_Down,29 Limit Merges,30,Unlimit Merges,31,0 Merge Downward,32 Merge Left,33 Merge Right,34 Merge Upward,35 Reset Tiles,36 Cancel,0 MENU,DRAW Draw Labels,37,Ignore Labels,38,0 Draw Macros,39,Ignore Macros,40,1 Draw Orient,49,Ignore Orient,50,0 Draw Rows,41,Ignore Rows,42,1 Draw Tiles,43,Ignore Tiles,44,1 Cancel,0 MENU,PARAMETERS Feed Percentage,45 Min. Row Length,46 Row Separation,47 Set Spacing,48 Cancel,0 graywolf-0.1.4+20170307gite1bf319/src/genrows/globals.h000066400000000000000000000141331305746555600220350ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: globals.h DESCRIPTION:This file contains the global definitions and typedefs for the genrow program. CONTENTS: DATE: Aug 9, 1989 REVISIONS: Feb 28, 1990 - added new fields to tiles for graphics. Dec 7, 1990 - added force field and new variables for performing merges. Fri Jan 25 17:50:54 PST 1991 - added mirror row feature. Sat Feb 23 00:34:11 EST 1991 - added no macro move global. Thu Mar 7 03:11:42 EST 1991 - added num_rowsG global. Wed Apr 17 22:39:04 EDT 1991 - added wait_for_user global and orientation field for macro. ----------------------------------------------------------------- */ #ifndef GLOBALS_H #define GLOBALS_H #ifndef lint static char SccsglobalsId[] = "@(#) globals.h (Yale) version 3.11 5/14/92" ; #endif #ifndef GLOBAL_DEFS #define EXTERN extern #else #define EXTERN #endif /* remove graphics lines of code if compile switch is on */ #ifdef NOGRAPHICS #define G(x_xz) #else #define G(x_xz) x_xz #endif /* NOGRAPHICS */ #define START 1 #define END 2 #define NOTHING 3 #define FROM_LEFT 4 #define FROM_RIGHT 5 #define FROM_TOP 6 #define FROM_BOTTOM 7 #define TO_LEFT 8 #define TO_RIGHT 9 #define TO_TOP 10 #define TO_BOTTOM 11 #define MAYBE_START 12 #define MAYBE_END 13 #define MERGED_NONE 0 #define MERGED_UP 1 #define MERGED_DOWN 2 #define MERGED_LEFT 3 #define MERGED_RITE 4 typedef struct tile_box { INT name ; /* index of the tile */ INT llx ; INT lly ; INT urx ; INT ury ; INT numrows ; INT class ; INT actual_row_height ; INT add_no_more_than ; /* the xspan of the tile */ INT channel_separation ; INT min_length ; /* the size of the minimum valid row */ INT max_length ; /* the maximum length of the block normally tile width - 2 */ INT row_start ; /* offset from the beginning of the tile */ INT merged ; /* direction of the merge */ BOOL illegal ; /* FALSE means a legal tile to use */ BOOL force ; /* force the number of rows */ BOOL mirror ; /* mirror rows ?? */ BOOL allocated ; /* whether tile is currently allocated or freed */ struct tile_box *next ; struct tile_box *prev ; } TILE_BOX ; typedef struct macro_tile { INT l ; INT r ; INT b ; INT t ; struct macro_tile *next ; } MACRO_TILE ; typedef struct vertex_box { INT x ; INT y ; INT class ; INT macro ; struct vertex_box *next ; } *VERTEXPTR, VERTEX_BOX ; typedef struct macro_rec { MACRO_TILE *tiles ; /* the tiles of the macro */ INT num_vertices ; /* number of vertices on macro */ VERTEXPTR *vertices ; /* the vertices of a macro */ INT xcenter ; INT ycenter ; INT xcenter_orig ; INT ycenter_orig ; INT left ; INT right ; INT bottom ; INT top ; INT orient ; } MACROBOX, *MACROPTR ; typedef struct row_box { INT llx ; INT lly ; INT urx ; INT ury ; INT class ; INT seg ; BOOL mirror ; /* mirror rows ?? */ struct row_box *next_row ; struct row_box *next_segment ; } ROW_BOX ; /* ********************** global variables ************************ */ /* GENERAL GLOBAL VARIABLES */ EXTERN char *cktNameG ; EXTERN BOOL graphicsG ; /* TRUE if graphics are requested */ /* DATA GLOBAL VARIABLES */ EXTERN TILE_BOX *tile_listG ; /* head of list of tiles */ EXTERN TILE_BOX *last_tileG ; /* end of list of tiles */ EXTERN TILE_BOX *start_tileG; /* current start of tiles */ EXTERN MACROPTR *macroArrayG ; EXTERN MACROPTR *mergeArrayG ; /* tiles that the user merged */ EXTERN INT num_macrosG ; /* number of macros given */ EXTERN INT num_mergedG ; /* number of merged tiles given */ EXTERN INT num_rowsG ; /* user specified the number of rows */ EXTERN INT feeds_per_segG ; /* feed length per segment */ EXTERN INT flip_alternateG; /* flip alternate rows beginning at 1 or 2 */ EXTERN INT spacingG ; /* spacing to macros */ EXTERN BOOL shortRowG ; /* whether to keep short row */ EXTERN BOOL invalidG ; /* whether configuration is ok */ EXTERN BOOL limitMergeG ; /* whether to limit merge to 1 step */ EXTERN BOOL noMacroMoveG ; /* when TRUE macros may not move */ EXTERN BOOL wait_for_userG; /* normally wait for user */ EXTERN BOOL last_chanceG; /* "last chance" timeout */ EXTERN BOOL memoryG ; /* try to remember last state */ EXTERN BOOL no_outputG ; /* when TRUE no .blk file */ /* ********************** end global variables ******************** */ #endif /* GLOBALS_H */ graywolf-0.1.4+20170307gite1bf319/src/genrows/macro.dialog000066400000000000000000000035531305746555600225270ustar00rootroot00000000000000numfields;36 # "@(#) macro.dialog (Yale) version 1.2 4/17/91" # Here is how you make a dialog box. # Semicolons are delimiters # field;fieldnumber;xpos;ypos;init string;field length; # (continued) field type;color;case toggle # Field types are # accept - mandatory # reject - mandatory # label - write only field. # input - read write field # case - a set of case field to follow # the first field in the list is the initial case. # clabel - one of the case fields. # field number must start with 0 field;0; 5;1 ; ACCEPT ; 8;accept;green field;1; 25;1 ; CANCEL ; 8;reject;red field;2; 15;2 ;Macro Edit; 9;label;red field;3; 5;4 ;Coordinates; 11;label;blue field;4; 5;5 ;-----------; 11;label;black field;5; 5;6 ;X :; 9;label;blue field;6; 25;6 ; ; 8;input;blue field;7; 5;7 ;Y :; 9;label;blue field;8; 25;7 ; ; 8;input;blue field;9; 5;8 ;Delta X :; 9;label;blue field;10; 25;8 ; ; 8;input;blue field;11; 5;9 ;Delta Y :; 9;label;blue field;12; 25;9 ; ; 8;input;blue field;13;5;10;Orient:;7;case;blue;14,15,16,17,18,19,20,21 field;14;25;10;0;1;clabel;blue field;15;26;10;1;1;clabel;blue field;16;27;10;2;1;clabel;blue field;17;28;10;3;1;clabel;blue field;18;29;10;4;1;clabel;blue field;19;30;10;5;1;clabel;blue field;20;31;10;6;1;clabel;blue field;21;32;10;7;1;clabel;blue # directions field;23;1;13;To change case fields put pointer;35;label;blue field;24;1;14;in window and click. To change;35;label;blue field;25;1;15;input fields put pointer in window;35;label;blue field;26;1;16;and back up over current contents;35;label;blue field;27;1;17;using the delete key. After modifying;35;label;blue field;28;1;18;the field, hit the return key.;35;label;blue graywolf-0.1.4+20170307gite1bf319/src/genrows/main.c000066400000000000000000000206711305746555600213350ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: main.c DESCRIPTION:This file contains the main control structure for generating standard cell rows. CONTENTS: main() DATE: Aug 9, 1989 - original coding. REVISIONS: Feb 7, 1990 - took total_row_length out of procedure calls. Mon Jan 7 18:27:31 CST 1991 - remove .undo and .redo files after execution. Automatically, save a restart file at end. Sat Jan 26 16:28:34 PST 1991 - moved force rows to main routine. Sat Feb 23 00:35:50 EST 1991 - added no macro move flag. Thu Mar 7 03:12:20 EST 1991 - now allow user to set number of rows in standard cell case. Wed Apr 17 22:40:01 EDT 1991 - added conditional compile for debugging X. Sat Sep 21 15:48:12 EDT 1991 - added memory functionality. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) main.c (Yale) version 3.10 9/21/91" ; #endif #define GLOBAL_DEFS #define EXPECTEDMEMORY ( 512 * 1024 ) #define VERSION "v1.0" #include #include #include #include #include #include #include /* NOTE ****** macros cannot overlap !!! ****** */ /* NOTE: time efficiencies have been completely ignored during the development of these algorithms. At this point, I am only interested in EFFECTIVE and ROBUST functionality. ---Carl Sechen */ main( argc, argv ) int argc ; char *argv[] ; { FILE *fp ; int yaleIntro() ; char filename[LRECL] ; /* used for input filename */ char *ptr ; /* used to parse command line */ int windowId ; /* window id */ BOOL parasite ; /* true if window inheritance is on */ BOOL debug ; /* true if debug is requested */ BOOL force_tiles() ; /* returns true if last tile is forced */ /* ********************** start initialization *********************** */ #ifdef DEBUGX extern int _Xdebug ; _Xdebug = TRUE ; #endif /* start up cleanup handler */ YINITCLEANUP( "config", NULL, MAYBEDUMP ) ; Yinit_memsize( EXPECTEDMEMORY ) ; if( argc < 2 || argc > 4 ){ syntax() ; } else { debug = FALSE ; parasite = FALSE ; windowId = 0 ; noMacroMoveG = FALSE ; #ifndef NOGRAPHICS graphicsG = TRUE ; #else graphicsG = FALSE ; #endif if( *argv[1] == '-' ){ for( ptr = ++argv[1]; *ptr; ptr++ ){ switch( *ptr ){ case 'd': debug = TRUE ; YsetDebug( TRUE ) ; break ; case 'f': noMacroMoveG = TRUE ; break ; case 'n': graphicsG = FALSE ; break ; case 'w': parasite = TRUE ; break ; default: sprintf( YmsgG,"Unknown option:%c\n", *ptr ) ; M(ERRMSG,"main",YmsgG); syntax() ; } } YdebugMemory( debug ) ; /* handle I/O requests */ cktNameG = Ystrclone( argv[2] ); YinitProgram( "config", VERSION, yaleIntro ); /* now tell the user what he picked */ M(MSG,NULL,"\n\nconfig switches:\n" ) ; if( debug ){ YsetDebug( TRUE ) ; M(MSG,NULL,"\tdebug on\n" ) ; } if( graphicsG ){ M(MSG,NULL,"\tGraphics mode on\n" ) ; } else { M(MSG,NULL,"\tGraphics mode off\n" ) ; } if( parasite ){ M(MSG,NULL,"\tconfig will inherit window\n" ) ; /* look for windowid */ if( argc != 4 ){ M(ERRMSG,"main","Need to specify windowID\n" ) ; syntax() ; } else { windowId = atoi( argv[3] ) ; } } if( noMacroMoveG ){ M(MSG,NULL,"\tconfig will not alloc macro moves\n" ) ; } M(MSG,NULL,"\n" ) ; } else if( argc == 2 ){ /* order is important here */ YdebugMemory( FALSE ) ; cktNameG = Ystrclone( argv[1] ); YinitProgram( "config", VERSION, yaleIntro ); } else { syntax() ; } } init_data_structures() ; G( initgraphics( argc, argv, windowId ) ) ; /* ********************** end initialization ************************* */ sprintf( filename, "%s.mver", cktNameG ) ; fp = TWOPEN( filename, "r", ABORT ) ; /* actual_row_heightS is the default used for rows placed across the top of the core--these are NOT generated from a tile */ read_vertices(fp,TRUE) ; TWCLOSE(fp); /* now safe to read parameter file */ readpar() ; build_macros() ; process_vertices() ; D( "genrows/main", print_vertices() ) ; process_tiles() ; D( "genrows/main", print_tiles() ) ; merge_tiles() ; D( "genrows/main", print_tiles() ) ; check_tiles() ; /* *************************************************************** */ /* THE USER SHOULD BE ABLE TO DO: (1) Be able to divide a tile into two parts, separated by a horizontal line -- when the rows above should have a higher height, for example. To divide a tile, simply call the function: divide_tile( tile , horiz_line ) TILE_BOX *tile ; int horiz_line ; (2) Be able to expand a tile in any direction. (3) Be able to edit the actual_row_height. (4) Be able to edit the channel_separation. *BUT,THE check_tiles MUST BE CONDUCTED IF THE USER CHANGES ANYTHING IN (3) OR (4) (5) Be able to edit the min_length /* *************************************************************** */ /* make the rows once to see where the tiles are */ /* force the last tile with rows to line up */ remakerows() ; if( num_rowsG && num_macrosG == 0 ){ memoryG = FALSE ; calculate_numrows() ; memoryG = TRUE ; } if( force_tiles() ){ remakerows() ; } if( graphicsG ){ G( process_graphics() ) ; } /* end graphics switch */ if( graphicsG ){ G( TWcloseGraphics() ) ; } print_blk_file() ; /* now save a restart file */ sprintf( filename, "%s.gsav", cktNameG ) ; fp = TWOPEN( filename, "w", ABORT ) ; save_state(fp) ; TWCLOSE( fp ) ; /* now blow away do and undo files if they exist */ sprintf( filename, "%s.undo", cktNameG ) ; if( YfileExists( filename) ){ Yrm_files( filename ) ; } sprintf( filename, "%s.redo", cktNameG ) ; if( YfileExists( filename) ){ Yrm_files( filename ) ; } YexitPgm( PGMOK ) ; } /* end main */ yaleIntro() { fprintf(stdout,"\n%s\n",YmsgG) ; fprintf(stdout,"Row configuration program\n"); fprintf(stdout," Yale University\n"); } /* end yaleIntro */ /* give user correct syntax */ syntax() { M(ERRMSG,NULL,"\n" ) ; M(MSG,NULL,"Incorrect syntax. Correct syntax:\n"); sprintf( YmsgG, "\nconfig [-dnw] designName [windowId] \n" ) ; M(MSG,NULL,YmsgG ) ; M(MSG,NULL,"\twhose options are zero or more of the following:\n"); M(MSG,NULL,"\t\td - prints debug info and performs extensive\n"); M(MSG,NULL,"\t\t error checking\n"); M(MSG,NULL,"\t\tn - no graphics - the default is to open the\n"); M(MSG,NULL,"\t\t display and output graphics to an Xwindow\n"); M(MSG,NULL,"\t\tw - parasite mode - user must specify windowId\n"); YexitPgm(PGMFAIL); } /* end syntax */ graywolf-0.1.4+20170307gite1bf319/src/genrows/menus.h000066400000000000000000000060011305746555600215340ustar00rootroot00000000000000 /* TWmenu definitions */ #define TWNUMMENUS 52 #define AUTO_REDRAW_ON 1 #define AUTO_REDRAW_OFF 2 #define CLOSE_GRAPHICS 3 #define COLORS 4 #define CONTINUE_PGM 5 #define DUMP_GRAPHICS 6 #define FULLVIEW 7 #define REDRAW 8 #define TELL_POINT 9 #define TRANSLATE 10 #define ZOOM 11 #define CANCEL 0 #define ALIGN_MACRO_IN_X 12 #define ALIGN_MACRO_IN_Y 13 #define ALIGN_ROWS 14 #define EDIT_MACRO 16 #define EDIT_ROW 15 #define EDIT_TILE 17 #define KEEP_SHORT_ROW 18 #define DISCARD_SHORT_ROW 19 #define MEMORY_ON 51 #define MEMORY_OFF 52 #define MODIFY_CORE_AREA 20 #define MOVE_MACRO 21 #define NUMROWS 22 #define REDO 23 #define RESTORE_STATE 24 #define SAVE_STATE 25 #define UNDO 27 #define CANCEL 0 #define DIVIDE_TILE_LEFT_RIGHT 28 #define DIVIDE_TILE_UP_DOWN 29 #define LIMIT_MERGES 30 #define UNLIMIT_MERGES 31 #define MERGE_DOWNWARD 32 #define MERGE_LEFT 33 #define MERGE_RIGHT 34 #define MERGE_UPWARD 35 #define RESET_TILES 36 #define CANCEL 0 #define DRAW_LABELS 37 #define IGNORE_LABELS 38 #define DRAW_MACROS 39 #define IGNORE_MACROS 40 #define DRAW_ORIENT 49 #define IGNORE_ORIENT 50 #define DRAW_ROWS 41 #define IGNORE_ROWS 42 #define DRAW_TILES 43 #define IGNORE_TILES 44 #define CANCEL 0 #define FEED_PERCENTAGE 45 #define MIN_ROW_LENGTH 46 #define ROW_SEPARATION 47 #define SET_SPACING 48 #define CANCEL 0 static TWMENUBOX menuS[53] = { "CONTROL",0,0,1,0,0, "Auto Redraw On","Auto Redraw Off",1,0,1,2, "Close Graphics",0,0,0,3,0, "Colors",0,0,0,4,0, "Continue Pgm",0,0,0,5,0, "Dump Graphics",0,0,0,6,0, "FullView",0,0,0,7,0, "Redraw",0,0,0,8,0, "Tell Point",0,0,0,9,0, "Translate",0,0,0,10,0, "Zoom",0,0,0,11,0, "Cancel",0,0,0,0,0, "EDIT",0,0,1,0,0, "Align Macro in X",0,0,0,12,0, "Align Macro in Y",0,0,0,13,0, "Align Rows",0,0,0,14,0, "Edit Macro",0,0,0,16,0, "Edit Row",0,0,0,15,0, "Edit Tile",0,0,0,17,0, "Keep Short Row","Discard Short Row",0,0,18,19, "Memory On","Memory Off",1,0,51,52, "Modify Core Area",0,0,0,20,0, "Move Macro",0,0,0,21,0, "Numrows",0,0,0,22,0, "Redo",0,0,0,23,0, "Restore State",0,0,0,24,0, "Save State",0,0,0,25,0, "Undo",0,0,0,27,0, "Cancel",0,0,0,0,0, "MERGE",0,0,1,0,0, "Divide Tile Left_Right",0,0,0,28,0, "Divide Tile Up_Down",0,0,0,29,0, "Limit Merges","Unlimit Merges",0,0,30,31, "Merge Downward",0,0,0,32,0, "Merge Left",0,0,0,33,0, "Merge Right",0,0,0,34,0, "Merge Upward",0,0,0,35,0, "Reset Tiles",0,0,0,36,0, "Cancel",0,0,0,0,0, "DRAW ",0,0,1,0,0, "Draw Labels","Ignore Labels",0,0,37,38, "Draw Macros","Ignore Macros",1,0,39,40, "Draw Orient","Ignore Orient",0,0,49,50, "Draw Rows","Ignore Rows",1,0,41,42, "Draw Tiles","Ignore Tiles",1,0,43,44, "Cancel",0,0,0,0,0, "PARAMETERS ",0,0,1,0,0, "Feed Percentage",0,0,0,45,0, "Min. Row Length",0,0,0,46,0, "Row Separation",0,0,0,47,0, "Set Spacing",0,0,0,48,0, "Cancel",0,0,0,0,0, 0,0,0,0,0,0 } ; graywolf-0.1.4+20170307gite1bf319/src/genrows/merge.c000066400000000000000000000564441305746555600215170ustar00rootroot00000000000000/* * Copyright (C) 1990-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: merge.c DESCRIPTION:How to merge tiles together to make row configuration better. CONTENTS: DATE: Nov 29, 1990 REVISIONS: Fri Jan 25 17:50:54 PST 1991 - added mirror row feature. Sat Sep 21 15:41:10 EDT 1991 - updated for memory. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) merge.c (Yale) version 3.5 5/14/92" ; #endif #include #include #include #include static check_max_length(); static merge_adjacent_tiles(); merge_tiles() { TILE_BOX *tileptr ; /* current tile */ merge_adjacent_tiles() ; /* now see if we can merge the start tile */ if( start_tileG ){ merge_upward( start_tileG ) ; } } /* end merge_tiles */ merge_upward( begin_tile ) TILE_BOX *begin_tile ; { INT left ; /* left edge of merge tile */ INT right ; /* right edge of merge tile */ TILE_BOX *tileptr ; /* current tile */ TILE_BOX *temp ; /* temp pointers to tile */ TILE_BOX *tptr ; /* temp pointers to tile */ BOOL merge ; /* TRUE if we merged at least one tile */ /* we need to use the tile as a bound for left and right */ left = begin_tile->llx ; right = begin_tile->urx ; merge = FALSE ; for( tileptr=tile_listG;tileptr;tileptr=tileptr->next ){ /*********************************************************** * See if we have any overlap with any tile in the tile set * in the y direction. If so, we can use this as a new top * The tile's left edge must be <= left and the tile's right * edge must be >= to right. ***********************************************************/ if( tileptr == last_tileG || tileptr == begin_tile ){ continue ; } if( tileptr->llx > left ){ continue ; } if( tileptr->urx < right ){ continue ; } /* Does it touch the begin tile in the y direction ? */ if( projectY( tileptr->lly,tileptr->ury,begin_tile->lly,begin_tile->ury)){ /* this tile may be merged with the bottom tile */ if( begin_tile->ury < tileptr->ury ){ begin_tile->ury = tileptr->ury ; begin_tile->merged = MERGED_UP ; merge = TRUE ; /*************************************************** * Now check the four cases: * Case I: +--------------------------------+ + | +--------------------------------+ | | | | +-------------------+ ****************************************************/ if( tileptr->llx < left && tileptr->urx == right ){ tileptr->urx = left ; check_max_length( tileptr ) ; /*************************************************** * Case II: +--------------------------------+ + | +--------------------------------+ | | | | +-------------------+ ****************************************************/ } else if( tileptr->llx == left && tileptr->urx > right ){ tileptr->llx = right ; check_max_length( tileptr ) ; /*************************************************** * Case III: +--------------------------------+ + | +--------------------------------+ | | | | +-------------------+ ****************************************************/ } else if( tileptr->llx < left && tileptr->urx > right ){ /* in this case we need to add a new tile */ temp = tileptr->next ; tptr = tileptr->next = (TILE_BOX *) Ysafe_malloc( sizeof(TILE_BOX) ) ; tptr->name = 0 ; tptr->allocated = TRUE ; tptr->llx = tileptr->llx ; tptr->lly = tileptr->lly ; tptr->urx = left ; tptr->ury = tileptr->ury ; tptr->merged = MERGED_NONE ; tptr->actual_row_height = tileptr->actual_row_height ; tptr->channel_separation = tileptr->channel_separation ; tptr->min_length = tileptr->min_length ; tptr->max_length = tptr->urx - tptr->llx - 2 * spacingG ; tptr->row_start = 1 ; tptr->numrows = 0 ; tptr->illegal = FALSE ; tptr->add_no_more_than = 0 ; tptr->next = temp ; tptr->prev = tileptr ; temp->prev = tptr ; tptr->class = tileptr->class ; tptr->mirror = tileptr->mirror ; /* see if we need to reset last_tileG */ if(!(tptr->next)){ last_tileG = tptr ; } /* now reset tileptr values */ tileptr->llx = right ; check_max_length( tileptr ) ; /*************************************************** * Case IV: +-------------------+ + | +-------------------+ | | | | +-------------------+ ****************************************************/ } else if( tileptr->llx == left && tileptr->urx == right ){ /* merge these adjacent tiles; delete tileptr2 */ if( tileptr == tile_listG ) { tile_listG = tile_listG->next ; tile_listG->prev = NULL ; /* Ysafe_free( tileptr ) ; */ tileptr->allocated = FALSE ; } else { tileptr->prev->next = tileptr->next ; tileptr->next->prev = tileptr->prev ; temp = tileptr ; tileptr = tileptr->prev ; /* Ysafe_free( temp ) ; */ temp->allocated = FALSE ; } } /* end case IV */ if( limitMergeG ){ return ; } } } } if( merge ){ /* we merged tiles call merge right till we can't do no more */ merge_upward( begin_tile ) ; } } /* end merge_upward */ merge_downward( begin_tile ) TILE_BOX *begin_tile ; { INT left ; /* left edge of merge tile */ INT right ; /* right edge of merge tile */ TILE_BOX *tileptr ; /* current tile */ TILE_BOX *temp ; /* temp pointers to tile */ TILE_BOX *tptr ; /* temp pointers to tile */ BOOL merge ; /* TRUE if we merged at least one tile */ /* we need to use the tile as a bound for left and right */ left = begin_tile->llx ; right = begin_tile->urx ; merge = FALSE ; for( tileptr=last_tileG->prev;tileptr;tileptr=tileptr->prev ){ /*********************************************************** * See if we have any overlap with any tile in the tile set * in the y direction. If so, we can use this as a new top * The tile's left edge must be <= left and the tile's right * edge must be >= to right. ***********************************************************/ if( tileptr == last_tileG || tileptr == begin_tile ){ continue ; } if( tileptr->llx > left ){ continue ; } if( tileptr->urx < right ){ continue ; } /* Does it touch the begin tile in the y direction ? */ if( projectY( tileptr->lly,tileptr->ury,begin_tile->lly,begin_tile->ury)){ /* this tile may be merged with the bottom tile */ if( begin_tile->lly > tileptr->lly ){ begin_tile->lly = tileptr->lly ; begin_tile->merged = MERGED_DOWN ; merge = TRUE ; /*************************************************** * Now check the four cases: * Case I: +-------------------+ | | | | +--------------------------------+ + | +--------------------------------+ ****************************************************/ if( tileptr->llx < left && tileptr->urx == right ){ tileptr->urx = left ; check_max_length( tileptr ) ; /*************************************************** * Case II: +-------------------+ | | | | +--------------------------------+ + | +--------------------------------+ ****************************************************/ } else if( tileptr->llx == left && tileptr->urx > right ){ tileptr->llx = right ; check_max_length( tileptr ) ; /*************************************************** * Case III: +-------------------+ | | | | +--------------------------------+ + | +--------------------------------+ ****************************************************/ } else if( tileptr->llx < left && tileptr->urx > right ){ /* in this case we need to add a new tile */ temp = tileptr->next ; tptr = tileptr->next = (TILE_BOX *) Ysafe_malloc( sizeof(TILE_BOX) ) ; tptr->name = 0 ; tptr->allocated = TRUE ; tptr->llx = tileptr->llx ; tptr->lly = tileptr->lly ; tptr->urx = left ; tptr->ury = tileptr->ury ; tptr->merged = MERGED_NONE ; tptr->actual_row_height = tileptr->actual_row_height ; tptr->channel_separation = tileptr->channel_separation ; tptr->min_length = tileptr->min_length ; tptr->max_length = tptr->urx - tptr->llx - 2 * spacingG ; tptr->row_start = 1 ; tptr->numrows = 0 ; tptr->illegal = FALSE ; tptr->add_no_more_than = 0 ; tptr->class = tileptr->class ; tptr->mirror = tileptr->mirror ; tptr->next = temp ; tptr->prev = tileptr ; temp->prev = tptr ; /* see if we need to reset last_tileG */ if(!(tptr->next)){ last_tileG = tptr ; } /* now reset tileptr values */ tileptr->llx = right ; check_max_length( tileptr ) ; /*************************************************** * Case IV: +-------------------+ | | | | +-------------------+ | | +-------------------+ ****************************************************/ } else if( tileptr->llx == left && tileptr->urx == right ){ /* merge these adjacent tiles; delete tileptr2 */ if( tileptr == tile_listG ) { tile_listG = tile_listG->next ; tile_listG->prev = NULL ; /* Ysafe_free( tileptr ) ; */ tileptr->allocated = FALSE ; } else { tileptr->prev->next = tileptr->next ; tileptr->next->prev = tileptr->prev ; temp = tileptr ; tileptr = tileptr->next ; /* Ysafe_free( temp ) ; */ temp->allocated = FALSE ; } } /* end case IV */ if( limitMergeG ){ return ; } } } } if( merge ){ /* we merged tiles call merge right till we can't do no more */ merge_downward( begin_tile ) ; } } /* end merge_downward */ merge_right( begin_tile ) TILE_BOX *begin_tile ; { INT bottom ; /* bottom edge of merge tile */ INT top ; /* top edge of merge tile */ TILE_BOX *tileptr ; /* current tile */ TILE_BOX *temp ; /* temp pointers to tile */ TILE_BOX *tptr ; /* temp pointers to tile */ BOOL merge ; /* TRUE if we merged at least one tile */ /* we need to use the tile as a bound for bottom and top */ bottom = begin_tile->lly ; top = begin_tile->ury ; merge = FALSE ; for( tileptr=tile_listG;tileptr;tileptr=tileptr->next ){ /*********************************************************** * See if we have any overlap with any tile in the tile set * in the x direction. If so, we can use this as a new right * The tile's bottom edge must be <= bottom and the tile's top * edge must be >= to top. ***********************************************************/ if( tileptr == last_tileG || tileptr == begin_tile ){ continue ; } if( tileptr->lly > bottom ){ continue ; } if( tileptr->ury < top ){ continue ; } /* Does it touch the begin tile in the y direction ? */ if( projectX( tileptr->llx,tileptr->urx,begin_tile->llx,begin_tile->urx)){ /* this tile may be merged with the right tile */ if( begin_tile->urx < tileptr->urx ){ begin_tile->urx = tileptr->urx ; begin_tile->merged = MERGED_RITE ; merge = TRUE ; check_max_length( begin_tile ) ; /*************************************************** * Now check the four cases: * Case I: +-------------------+-------------------+ + begin | tileptr | +-------------------+ | | | +-------------------+ ****************************************************/ if( tileptr->lly < bottom && tileptr->ury == top ){ tileptr->ury = bottom ; check_max_length( tileptr ) ; /*************************************************** * Case II: +-------------------+ | | +-------------------+ | + begin | tileptr | +-------------------+-------------------+ ****************************************************/ } else if( tileptr->lly == bottom && tileptr->ury > top ){ tileptr->lly = top ; check_max_length( tileptr ) ; /*************************************************** * Case III: +-------------------+ +-------------------+ | + begin | tileptr | +-------------------+ | +-------------------+ new tile here ****************************************************/ } else if( tileptr->lly < bottom && tileptr->ury > top ){ /* in this case we need to add a new tile */ temp = tileptr->next ; tptr = tileptr->next = (TILE_BOX *) Ysafe_malloc( sizeof(TILE_BOX) ) ; tptr->name = 0 ; tptr->allocated = TRUE ; tptr->llx = tileptr->llx ; tptr->lly = tileptr->lly ; tptr->urx = tileptr->urx ; tptr->ury = bottom ; tptr->merged = MERGED_NONE ; tptr->actual_row_height = tileptr->actual_row_height ; tptr->channel_separation = tileptr->channel_separation ; tptr->min_length = tileptr->min_length ; tptr->max_length = tptr->urx - tptr->llx - 2 * spacingG ; tptr->row_start = 1 ; tptr->numrows = 0 ; tptr->illegal = FALSE ; tptr->add_no_more_than = 0 ; tptr->next = temp ; tptr->prev = tileptr ; temp->prev = tptr ; tptr->class = tileptr->class ; tptr->mirror = tileptr->mirror ; /* see if we need to reset last_tileG */ if(!(tptr->next)){ last_tileG = tptr ; } /* now reset tileptr values */ tileptr->lly = top ; check_max_length( tileptr ) ; /*************************************************** * Case IV: +-------------------+-------------------+ + begin | tileptr | +-------------------+-------------------+ ****************************************************/ } else if( tileptr->lly == bottom && tileptr->ury==top ){ /* merge these adjacent tiles; delete tileptr2 */ if( tileptr == tile_listG ) { tile_listG = tile_listG->next ; tile_listG->prev = NULL ; /* Ysafe_free( tileptr ) ;*/ tileptr->allocated = FALSE ; tileptr = tile_listG ; } else { tileptr->prev->next = tileptr->next ; tileptr->next->prev = tileptr->prev ; temp = tileptr ; tileptr = tileptr->prev ; /* Ysafe_free( temp ) ; */ temp->allocated = FALSE ; } } /* end case IV */ if( limitMergeG ){ return ; } } } } if( merge ){ /* we merged tiles call merge right till we can't do no more */ merge_right( begin_tile ) ; } } /* end merge_right */ merge_left( begin_tile ) TILE_BOX *begin_tile ; { INT bottom ; /* bottom edge of merge tile */ INT top ; /* top edge of merge tile */ TILE_BOX *tileptr ; /* current tile */ TILE_BOX *temp ; /* temp pointers to tile */ TILE_BOX *tptr ; /* temp pointers to tile */ BOOL merge ; /* TRUE if we merged at least one tile */ /* we need to use the tile as a bound for bottom and top */ bottom = begin_tile->lly ; top = begin_tile->ury ; merge = FALSE ; for( tileptr=tile_listG;tileptr;tileptr=tileptr->next ){ /*********************************************************** * See if we have any overlap with any tile in the tile set * in the x direction. If so, we can use this as a new right * The tile's bottom edge must be <= bottom and the tile's top * edge must be >= to top. ***********************************************************/ if( tileptr == last_tileG || tileptr == begin_tile ){ continue ; } if( tileptr->lly > bottom ){ continue ; } if( tileptr->ury < top ){ continue ; } /* Does it touch the begin tile in the y direction ? */ if( projectX( tileptr->llx,tileptr->urx,begin_tile->llx,begin_tile->urx)){ /* this tile may be merged with the right tile */ if( begin_tile->llx > tileptr->llx ){ begin_tile->llx = tileptr->llx ; begin_tile->merged = MERGED_LEFT ; merge = TRUE ; check_max_length( begin_tile ) ; /*************************************************** * Now check the four cases: * Case I: +-------------------+-------------------+ | tileptr | begin | | +-------------------+ +-------------------+ ****************************************************/ if( tileptr->lly < bottom && tileptr->ury == top ){ tileptr->ury = bottom ; check_max_length( tileptr ) ; /*************************************************** * Case II: +-------------------+ | +-------------------+ | tileptr | begin | +-------------------+-------------------+ ****************************************************/ } else if( tileptr->lly == bottom && tileptr->ury > top ){ tileptr->lly = top ; check_max_length( tileptr ) ; /*************************************************** * Case III: +-------------------+ | +-------------------+ | tileptr | begin | | +-------------------+ +-------------------+ new tile here ****************************************************/ } else if( tileptr->lly < bottom && tileptr->ury > top ){ /* in this case we need to add a new tile */ temp = tileptr->next ; tptr = tileptr->next = (TILE_BOX *) Ysafe_malloc( sizeof(TILE_BOX) ) ; tptr->name = 0 ; tptr->allocated = TRUE ; tptr->llx = tileptr->llx ; tptr->lly = tileptr->lly ; tptr->urx = tileptr->urx ; tptr->ury = bottom ; tptr->merged = MERGED_NONE ; tptr->actual_row_height = tileptr->actual_row_height ; tptr->channel_separation = tileptr->channel_separation ; tptr->min_length = tileptr->min_length ; tptr->max_length = tptr->urx - tptr->llx - 2 * spacingG ; tptr->row_start = 1 ; tptr->numrows = 0 ; tptr->illegal = FALSE ; tptr->add_no_more_than = 0 ; tptr->next = temp ; tptr->prev = tileptr ; temp->prev = tptr ; tptr->class = tileptr->class ; tptr->mirror = tileptr->mirror ; /* see if we need to reset last_tileG */ if(!(tptr->next)){ last_tileG = tptr ; } /* now reset tileptr values */ tileptr->lly = top ; check_max_length( tileptr ) ; /*************************************************** * Case IV: +-------------------+-------------------+ + tileptr | begin | +-------------------+-------------------+ ****************************************************/ } else if( tileptr->lly == bottom && tileptr->ury==top ){ /* merge these adjacent tiles; delete tileptr2 */ if( tileptr == tile_listG ) { tile_listG = tile_listG->next ; tile_listG->prev = NULL ; /* Ysafe_free( tileptr ) ; */ tileptr->allocated = FALSE ; tileptr = tile_listG ; } else { tileptr->prev->next = tileptr->next ; tileptr->next->prev = tileptr->prev ; temp = tileptr ; tileptr = tileptr->prev ; /* Ysafe_free( temp ) ; */ temp->allocated = FALSE ; } } /* end case IV */ if( limitMergeG ){ return ; } } } } if( merge ){ /* we merged tiles call merge left till we can't do no more */ merge_left( begin_tile ) ; } } /* end merge_left */ static check_max_length( tileptr ) TILE_BOX *tileptr ; { INT length ; /* length of tile */ length = tileptr->urx - tileptr->llx - 2 * spacingG ; tileptr->max_length = length ; }/* end check_max_length */ renumber_tiles() { INT count ; /* count the tiles */ TILE_BOX *tileptr ; /* current tile */ count = 0 ; for( tileptr=tile_listG;tileptr;tileptr=tileptr->next ){ tileptr->name = ++count ; } } /* end renumber_tiles() */ static merge_adjacent_tiles() { TILE_BOX *tileptr1 , *tileptr2 , *tileptr ; REDO: for( tileptr1 = tile_listG;tileptr1->next;tileptr1 = tileptr1->next ){ // for( tileptr2=tile_listG;tileptr2->next;tileptr2=tileptr2->next ){ for( tileptr2=tile_listG;tileptr2;tileptr2=tileptr2->next ){ if( tileptr2 == tileptr1 ) { continue ; } if( tileptr1->llx == tileptr2->llx && tileptr1->urx == tileptr2->urx && tileptr1->ury == tileptr2->lly ) { /* merge these adjacent tiles; delete tileptr2 */ tileptr1->ury = tileptr2->ury ; if( tileptr2 == tile_listG ) { tile_listG = tile_listG->next ; tile_listG->prev = NULL ; /* Ysafe_free( tileptr2 ) ; */ tileptr2->allocated = FALSE ; goto REDO ; } else { tileptr = tile_listG ; while( tileptr->next != tileptr2 ) { tileptr = tileptr->next ; } tileptr->next = tileptr2->next ; if( tileptr2->next ){ tileptr2->next->prev = tileptr ; } /* Ysafe_free( tileptr2 ) ; */ tileptr2->allocated = FALSE ; goto REDO ; } } } /* end inner loop */ } /* end outer loop */ return ; }/* end merge_adjacent_tiles */ dtiles() { TILE_BOX *tptr ; /* current tile */ fprintf( stderr, "The forward tiles\n" ) ; for( tptr=tile_listG;tptr;tptr=tptr->next ){ fprintf( stderr, "\tTile:%d l:%5d b:%5d r:%5d t:%5d\n", tptr->name, tptr->llx, tptr->lly, tptr->urx, tptr->ury ) ; } fprintf( stderr, "The backward tiles\n" ) ; for( tptr=last_tileG;tptr;tptr=tptr->prev ){ fprintf( stderr, "\tTile:%d l:%5d b:%5d r:%5d t:%5d\n", tptr->name, tptr->llx, tptr->lly, tptr->urx, tptr->ury ) ; } } graywolf-0.1.4+20170307gite1bf319/src/genrows/readpar.c000066400000000000000000000216351305746555600220300ustar00rootroot00000000000000/* * Copyright (C) 1991-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: readpar.c DESCRIPTION:read parameter file CONTENTS: readpar( ) DATE: Sat Jan 26 12:48:32 PST 1991 REVISIONS: Sat Feb 23 00:35:01 EST 1991 - added wildcarding. Thu Mar 7 03:13:07 EST 1991 - added numrows keyword. Wed Apr 17 22:34:32 EDT 1991 - added rowSep keyword for consistency. Wed Jun 12 13:34:30 CDT 1991 - now read previous .out file for feed percentage. Fri Sep 6 15:13:23 CDT 1991 - now read previous row separation. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) readpar.c (Yale) version 1.9 5/14/92" ; #endif #include #include #include #include #include #include #define COMMENT '#' static BOOL abortS = FALSE ; static err_msg(); static get_defaults(); static int getnumRows(); readpar() { INT line ; INT temp ; INT numtokens ; INT numrows ; BOOL onNotOff ; BOOL wildcard ; BOOL feed_percent_default ; BOOL row_sep_default ; char design[LRECL] ; char **tokens ; char *lineptr ; DOUBLE tempf ; num_rowsG = 0 ; /* means number of rows not specified */ wait_for_userG = TRUE ; last_chanceG = TRUE ; flip_alternateG = 0 ; feed_percent_default = TRUE ; row_sep_default = TRUE ; no_outputG = FALSE ; M( MSG, NULL, "\n" ) ; Yreadpar_init( cktNameG, USER, GENR, FALSE ) ; while( tokens = Yreadpar_next( &lineptr, &line, &numtokens, &onNotOff, &wildcard )){ if( numtokens == 0 ){ /* skip over empty lines */ continue ; } else if( strcmp( tokens[0], "feed_percentage" ) == STRINGEQ ){ if( numtokens == 2 ){ tempf = atof( tokens[1] ) ; if( tempf < 0.0 ){ err_msg("feed_percentage") ; continue ; } set_feed_length( tempf ) ; feed_percent_default = FALSE ; } else { err_msg("feed_percentage") ; } } else if( strcmp( tokens[0], "minimum_row_len" ) == STRINGEQ ){ if( numtokens == 2 ){ temp = atoi( tokens[1] ) ; if( temp <= 0 ){ err_msg("minimum_row_len") ; continue ; } set_minimum_length( temp ) ; } else { err_msg("minimum_row_len") ; } } else if( strcmp( tokens[0], "rowSep" ) == STRINGEQ ){ if( numtokens >= 2 ){ tempf = atof( tokens[1] ) ; if( tempf < 0 ){ err_msg("rowSep") ; continue ; } temp = (numtokens == 3) ? (INT)atof(tokens[2]) : 0; set_row_separation( tempf, temp ) ; row_sep_default = FALSE ; } else { err_msg("rowSep") ; } } else if( strcmp( tokens[0], "row_to_tile_spacing" ) == STRINGEQ ){ if( numtokens == 2 ){ temp = atoi( tokens[1] ) ; if( temp < 0 ){ err_msg("row_to_tile_spacing") ; continue ; } spacingG = temp ; set_spacing() ; } else { err_msg("row_to_tile_spacing") ; } } else if( strcmp( tokens[0], "numrows" ) == STRINGEQ ){ if( numtokens == 2 ){ temp = atoi( tokens[1] ) ; if( temp < 0 ){ err_msg("numrows") ; continue ; } num_rowsG = temp ; } else { err_msg("numrows") ; } } else if( strcmp( tokens[0], "flip_alternate_rows" ) == STRINGEQ ){ if( numtokens == 2 ){ temp = atoi( tokens[1] ) ; if( temp < 0 || temp > 2 ){ err_msg("flip_alternate_rows") ; continue ; } flip_alternateG = temp ; } else { err_msg("flip_alternate_rows") ; } } else if( strcmp( tokens[0], "graphics.wait" ) == STRINGEQ ){ if( onNotOff ){ wait_for_userG = TRUE ; } else { wait_for_userG = FALSE ; } } else if( strcmp( tokens[0], "last_chance.wait" ) == STRINGEQ ){ if( onNotOff ){ last_chanceG = TRUE ; } else { last_chanceG = FALSE ; } } else if( strcmp( tokens[0], "no_blk_file" ) == STRINGEQ ){ if( onNotOff ){ no_outputG = TRUE ; } else { no_outputG = FALSE ; } /*** catch all ***/ } else if(!(wildcard)){ sprintf( YmsgG, "unexpected keyword in the %s.par file at line:%d\n\t%s\n", cktNameG, line, lineptr ); M( ERRMSG, "readpar", YmsgG ) ; Ymessage_error_count() ; abortS = TRUE ; } } /* end of parsing loop */ if( abortS ){ YexitPgm(PGMFAIL) ; } get_defaults( feed_percent_default, row_sep_default ) ; numrows = getnumRows() ; if( numrows ){ if( numrows != num_rowsG && num_rowsG ){ sprintf( YmsgG, "Number of row discrepancy between .row file(%d) and .par file(%d)\n", numrows, num_rowsG ) ; M( ERRMSG, "readpar", YmsgG ) ; M( ERRMSG, NULL, "Using value found in .row file\n" ) ; } num_rowsG = numrows ; } /* now check for user errors */ check_user_data() ; if( no_outputG ){ M( WARNMSG, "readpar", "No .blk file will be output.\n\n" ) ; } } /* end readpar */ static err_msg( keyword ) char *keyword ; { sprintf( YmsgG, "The value for %s was", keyword ); M( ERRMSG, "readpar", YmsgG ) ; sprintf( YmsgG, " not properly entered in the .par file\n"); M( ERRMSG, NULL, YmsgG ) ; abortS = TRUE ; }/* end err_msg */ static get_defaults( feed_percent_default, row_sep_default ) BOOL feed_percent_default, row_sep_default ; { FILE *fp ; char filename[LRECL] ; char buffer[LRECL] ; char *bufferptr ; DOUBLE tempf ; sprintf( filename, "%s.out", cktNameG ) ; if(!(fp = TWOPEN( filename, "r", NOABORT ))){ return ; } /* start at beginning and read till we find feed percentage */ while( bufferptr = fgets( buffer, LRECL, fp )){ /* remove leading blanks or tabs */ bufferptr = Yremove_lblanks( bufferptr ) ; if( strncmp( bufferptr, "Feed Percentage:", 16 ) == STRINGEQ ){ /* skip over Feed Percentage */ bufferptr += 16 ; /* remove any leading blanks */ bufferptr = Yremove_lblanks( bufferptr ) ; tempf = atof( bufferptr ) ; sprintf( YmsgG, "Found previous value for feed percentage:%4.2f\n", tempf ) ; M( MSG, NULL, YmsgG ) ; if( feed_percent_default ){ set_feed_length( tempf ) ; } else { M( MSG,NULL,"Overridden by .par file value for feed percentage\n" ) ; } } if( strncmp( bufferptr, "Average Row Separation:", 23 ) == STRINGEQ ){ /* skip over Feed Percentage */ bufferptr += 23 ; /* remove any leading blanks */ bufferptr = Yremove_lblanks( bufferptr ) ; tempf = atof( bufferptr ) ; sprintf( YmsgG, "Found previous value for row separation:%4.2f\n", tempf ) ; M( MSG, NULL, YmsgG ) ; if( row_sep_default ){ set_row_separation( tempf, (INT)0 ) ; } else { M( MSG,NULL,"Overridden by .par file value for row separation.\n" ) ; } break ; } } TWCLOSE( fp ) ; } /* end get_defaults */ static int getnumRows() { char **tokens ; /* for parsing menu file */ INT numtokens ; /* number of tokens on the line */ int line ; /* count lines in input file */ char buffer[LRECL], *bufferptr = buffer ; char filename[LRECL]; FILE* fp; /* read net list file */ sprintf( filename, "%s.row", cktNameG ) ; fp = TWOPEN( filename,"r",NOABORT) ; if(!(fp)){ return(0) ; } line = 0 ; /*--- initialize the line counter ---*/ /*----------- parse file ------------*/ while( bufferptr = fgets( buffer, LRECL, fp )){ tokens = Ystrparser( bufferptr, "\t\n/ ", &numtokens ); if( numtokens == 0 ){ continue ; } line++; } /* end while... */ return(line) ; } /* end int getnumRows() */ graywolf-0.1.4+20170307gite1bf319/src/genrows/row.dialog000066400000000000000000000030071305746555600222270ustar00rootroot00000000000000numfields;18 # "@(#) row.dialog (Yale) version 1.3 1/25/91" # Here is how you make a dialog box. # Semicolons are delimiters # field;fieldnumber;xpos;ypos;init string;field length; # (continued) field type;color;case toggle # Field types are # accept - mandatory # reject - mandatory # label - write only field. # input - read write field # case - a set of case field to follow # the first field in the list is the initial case. # clabel - one of the case fields. # field number must start with 0 field;0; 5;1 ; ACCEPT ; 8;accept;green field;1; 25;1 ; CANCEL ; 8;reject;red field;2; 15;2 ;Row Edit; 8;label;red field;3; 5;4 ;Left :; 6;label;blue field;4; 5;5 ;Bottom :; 6;label;blue field;5; 5;6 ;Right :; 6;label;blue field;6; 5;7 ;Top :; 6;label;blue field;7; 5;8 ;Class :;21;label;blue field;8; 25;8 ; ; 8;input;blue field;9; 5;9 ;Mirror rows :;19;case;blue;11,10 field;10;25;9 ;YES; 3;clabel;green field;11;31;9 ;NO; 2;clabel;red # directions field;12;1;11;To change case fields put pointer;35;label;blue field;13;1;12;in window and click. To change;35;label;blue field;14;1;13;input fields put pointer in window;35;label;blue field;15;1;14;and back up over current contents;35;label;blue field;16;1;15;using the delete key. After modifying;35;label;blue field;17;1;16;the field, hit the return key.;35;label;blue graywolf-0.1.4+20170307gite1bf319/src/mc_compact/000077500000000000000000000000001305746555600206605ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/src/mc_compact/CMakeLists.txt000066400000000000000000000007421305746555600234230ustar00rootroot00000000000000 add_executable(mc_compact cdraw.c compactor.c io.c multi.c stdmacro.c changraph.c debug2.c movestrat2.c readcgraph.c xcompact.c cmain.c grid.c movestrat.c readtiles.c ycompact.c ${CMAKE_SOURCE_DIR}/src/date/date.c) target_link_libraries(mc_compact ${CMAKE_BINARY_DIR}/src/Ylib/libycadgraywolf.so) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include .) install(TARGETS mc_compact DESTINATION lib/graywolf/bin) graywolf-0.1.4+20170307gite1bf319/src/mc_compact/cdraw.c000066400000000000000000000414701305746555600221320ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: cdraw.c DESCRIPTION:This file contains graphic routines for compaction program. CONTENTS: DATE: Apr 17, 1989 REVISIONS: Apr 25, 1989 - added graphics loop to program. May 5, 1989 - added NOGRAPHICS conditional compile. Sun Nov 4 12:50:58 EST 1990 - set drawLabel back to correct initialization. Also added draw critical tiles. Sun Feb 17 19:37:33 EST 1991 - added 3D graphics. Sat Feb 23 00:47:48 EST 1991 - now draw the changraph. Fri Mar 29 14:13:22 EST 1991 - temp fix for 2D graphics avoids arbitrary edge explosion. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) cdraw.c version 7.5 3/29/91" ; #endif #ifndef NOGRAPHICS #include #include #include #include #include #include #define SLEEPTIME (unsigned) 2 #define DATADIR "./DATA" #define COMPACTMENU "compact_menu" /* #define DEVELOPMENU */ /* During development use TWread_menus in place of menuS */ /* to create menu record, ie. TWread_menus(COMPACTMENU) */ #ifdef DEVELOPMENU #define MENU TWread_menus(COMPACTMENU) #else #define MENU menuS #endif #include static BOOL drawLabelS = FALSE ; static BOOL drawEdgeS = FALSE ; static BOOL auto_drawS = TRUE ; static BOOL drawForwardS = TRUE ; static BOOL selectCellS = 0 ; static BOOL drawMovedS = TRUE ; static BOOL draw3DS = FALSE ; static BOOL drawCriticalS = FALSE ; static BOOL drawEdgeLabelS = FALSE ; static BOOL drawChanGraphS = TRUE ; static INT zspanS ; init_graphics( argc, argv, windowId ) INT argc, windowId ; char *argv[] ; { char *host, *Ygetenv() ; int xpandx, xpandy ; INT draw_the_data() ; /* we need to find host for display */ if(!(host = Ygetenv("DISPLAY"))) { M(WARNMSG,"init_graphics","Can't get environment variable "); M(MSG,NULL, "for display. Aborting graphics...\n\n" ) ; graphicsG = FALSE ; return ; } if( windowId ){ /* init windows as a parasite */ if( !( TWinitParasite(argc,argv,TWnumcolors(),TWstdcolors(), FALSE, MENU, draw_the_data, windowId ))){ M(ERRMSG,"initgraphics","Aborting graphics."); graphicsG = FALSE ; return ; } } else { if(!(TWinitGraphics(argc,argv,TWnumcolors(),TWstdcolors(), FALSE, MENU, draw_the_data ))){ M(ERRMSG,"init_graphics","Aborting graphics."); graphicsG = FALSE ; return ; } xpandx = blockrG - blocklG ; xpandy = blocktG - blockbG ; zspanS = MIN( xpandx, xpandy ) ; xpandx /= 2 ; xpandx /= 2 ; TWsetwindow( blocklG-xpandx, blockbG-xpandy, blockrG+xpandx, blocktG+xpandy ) ; TWdrawMenus() ; TWflushFrame() ; } } set_draw_critical( flag ) BOOL flag ; { if( YdebugAssert() ){ /* in debug mode, I always want to look at moved cells */ drawCriticalS = FALSE ; } else { drawCriticalS = flag ; } } /* end set_draw_critical */ /* draw_the_data routine draws compaction graph */ INT draw_the_data() { INT i ; INT toX, toY, fromX, fromY, sinkTile ; INT color ; static BOOL firstL = TRUE ; unsigned sleep() ; char label[LRECL] ; char *labelptr ; COMPACTPTR tptr, t ; ECOMPBOXPTR eptr ; /* graphics is turned off */ if( !graphicsG ){ return ; } if( firstL && numcellsG ){ zspanS = ROUND( (DOUBLE) zspanS / (DOUBLE) numcellsG / 10.0 ) ; firstL = FALSE ; } TWstartFrame() ; if( drawChanGraphS ){ draw_changraph() ; } /* first draw the tiles */ for( i=1;i<=numtilesG;i++){ t = tileNodeG[i] ; if( t->type || t->cell == selectCellS ){ /* stdcells or selected cells */ color = TWRED ; } else if( drawCriticalS && (t->criticalX || t->criticalY) ){ /* criticalS is turned on by entry into compaction cycle.*/ color = TWVIOLET ; } else if( !drawCriticalS && drawMovedS && t->moved ){ /* in debug mode we look at moved tiles */ color = TWVIOLET ; } else { color = TWGREEN ; } if( drawLabelS ){ sprintf( label, "C%d:T%d", t->cell, i ) ; labelptr = label ; } else { labelptr = NIL(char *) ; } if( draw3DS ){ TW3Darb_init() ; TW3Darb_addpt( t->l, t->b, t->cell * zspanS ) ; TW3Darb_addpt( t->l, t->t, t->cell * zspanS ) ; TW3Darb_addpt( t->r, t->t, t->cell * zspanS ) ; TW3Darb_addpt( t->r, t->b, t->cell * zspanS ) ; TW3DdrawArb( i, color, labelptr ) ; } else { TWarb_init() ; TWarb_addpt( t->l, t->b ) ; TWarb_addpt( t->l, t->t ) ; TWarb_addpt( t->r, t->t ) ; TWarb_addpt( t->r, t->b ) ; TWdrawArb( i, color, labelptr ) ; } } /* end drawing the tiles */ /* nets are the edges between the cells */ /* -------------------------------------------------------------- space requirements also include 2 sources and 2 sinks: xSource = 0, xsink = numtilesG+1, ysource = numtilesG + 2, and ysink = numtilesG + 3 positions in the tileNode array. */ if( drawEdgeS && drawForwardS ){ /****************** XGRAPH *******************************/ sinkTile = numtilesG+1; for( eptr = xGraphG[0]->xadjF ;eptr; eptr=eptr->next){ fromX = xGraphG[0]->l ; fromY = (blockbG + blocktG) / 2 ; tptr = tileNodeG[eptr->node] ; toX = tptr->l ; toY = (tptr->b + tptr->t) / 2 ; if( drawEdgeLabelS ){ sprintf( label, "%d", eptr->constraint ); labelptr = label ; } else { labelptr = NIL(char *) ; } TWdrawNet( 0, fromX,fromY,toX,toY, TWRED, labelptr ) ; } for( i=1;i<=numtilesG;i++){ for( eptr = xGraphG[i]->xadjF ;eptr; eptr=eptr->next){ fromX = xGraphG[i]->l ; fromY = (xGraphG[i]->b + xGraphG[i]->t) / 2 ; tptr = tileNodeG[eptr->node] ; toX = tptr->l ; if( eptr->node != sinkTile ){ toY = (tptr->b + tptr->t) / 2 ; } else { toY = (blockbG + blocktG) / 2 ; } sprintf( label, "%d", eptr->constraint ); if( drawEdgeLabelS ){ sprintf( label, "%d", eptr->constraint ); labelptr = label ; } else { labelptr = NIL(char *) ; } TWdrawNet( i,fromX,fromY,toX,toY, TWRED, labelptr ) ; } } /****************** YGRAPH *******************************/ sinkTile = numtilesG + 3 ; for( eptr = yGraphG[0]->yadjF ;eptr; eptr=eptr->next){ fromY = yGraphG[0]->b ; fromX = (blocklG + blockrG) / 2 ; tptr = tileNodeG[eptr->node] ; toY = tptr->b ; toX = (tptr->l + tptr->r) / 2 ; if( drawEdgeLabelS ){ sprintf( label, "%d", eptr->constraint ); labelptr = label ; } else { labelptr = NIL(char *) ; } TWdrawNet( 0,fromX,fromY,toX,toY, TWBLUE, labelptr ) ; } for( i=1;i<=numtilesG;i++){ for( eptr = yGraphG[i]->yadjF ;eptr; eptr=eptr->next){ fromY = yGraphG[i]->b ; fromX = (yGraphG[i]->l + yGraphG[i]->r) / 2 ; tptr = tileNodeG[eptr->node] ; toY = tptr->b ; if( eptr->node != sinkTile ){ toX = (tptr->l + tptr->r) / 2 ; } else { toX = (blocklG + blockrG) / 2 ; } if( drawEdgeLabelS ){ sprintf( label, "%d", eptr->constraint ); labelptr = label ; } else { labelptr = NIL(char *) ; } TWdrawNet( i,fromX,fromY,toX,toY, TWBLUE, labelptr ) ; } } } else if( drawEdgeS && !drawForwardS ){ /****************** XGRAPH *******************************/ sinkTile = numtilesG + 1 ; for( eptr = xGraphG[sinkTile]->xadjB ;eptr; eptr=eptr->next){ fromX = xGraphG[sinkTile]->l ; fromY = (blockbG + blocktG) / 2 ; tptr = tileNodeG[eptr->node] ; toX = tptr->l ; toY = (tptr->b + tptr->t) / 2 ; sprintf( label, "%d", eptr->constraint ); if( drawEdgeLabelS ){ sprintf( label, "%d", eptr->constraint ); labelptr = label ; } else { labelptr = NIL(char *) ; } TWdrawNet( 0, fromX,fromY,toX,toY, TWRED, labelptr ) ; } for( i=1;i<=numtilesG;i++){ for( eptr = xGraphG[i]->xadjB ;eptr; eptr=eptr->next){ fromX = xGraphG[i]->l ; fromY = (xGraphG[i]->b + xGraphG[i]->t) / 2 ; tptr = tileNodeG[eptr->node] ; toX = tptr->l ; if( eptr->node != sinkTile ){ toY = (tptr->b + tptr->t) / 2 ; } else { toY = (blockbG + blocktG) / 2 ; } if( drawEdgeLabelS ){ sprintf( label, "%d", eptr->constraint ); labelptr = label ; } else { labelptr = NIL(char *) ; } TWdrawNet( i,fromX,fromY,toX,toY, TWRED, labelptr ) ; } } /****************** YGRAPH *******************************/ sinkTile = numtilesG + 3 ; for( eptr = tileNodeG[sinkTile]->yadjB ;eptr; eptr=eptr->next){ fromY = tileNodeG[sinkTile]->t ; fromX = (blocklG + blockrG) / 2 ; tptr = tileNodeG[eptr->node] ; toY = tptr->t ; toX = (tptr->l + tptr->r) / 2 ; if( drawEdgeLabelS ){ sprintf( label, "%d", eptr->constraint ); labelptr = label ; } else { labelptr = NIL(char *) ; } TWdrawNet( 0,fromX,fromY,toX,toY, TWBLUE, labelptr ) ; } for( i=1;i<=numtilesG;i++){ for( eptr = yGraphG[i]->yadjB ;eptr; eptr=eptr->next){ fromY = yGraphG[i]->t ; fromX = (yGraphG[i]->l + yGraphG[i]->r) / 2 ; tptr = tileNodeG[eptr->node] ; toY = tptr->t ; if( eptr->node != sinkTile ){ toX = (tptr->l + tptr->r) / 2 ; } else { toX = (blocklG + blockrG) / 2 ; } if( drawEdgeLabelS ){ sprintf( label, "%d", eptr->constraint ); labelptr = label ; } else { labelptr = NIL(char *) ; } TWdrawNet( i,fromX,fromY,toX,toY, TWBLUE, labelptr ) ; } } } /* end draw backward case */ if( draw3DS ){ TW3DdrawAxis() ; } TWflushFrame() ; D( "draw_the_data", sleep( SLEEPTIME ) ) ; } /* end draw_the_data */ /* heart of the graphic system processes user input */ process_graphics() { int x1, y1, x2, y2 ; /* coordinates for fixing cells and neighhds */ INT x, y ; /* coordinates from pointer */ int i ; /* temp variable */ int selection ; /* the users pick */ char *reply ; /* user reply to a querry */ BOOL ok ; /* loop until this value is true */ BOOL movedCell ; /* lets us know whether we have to update cellbins */ INFOPTR stretch_edge ; /* the edge to be ref. for stretch */ INFOPTR get_closest_edge() ; /* data might have changed so show user current config */ /* any function other that the draw controls need to worry about */ /* this concurrency problem - show user current config */ draw_the_data() ; /* use TWcheckExposure to flush exposure events since we just */ /* drew the data */ TWcheckExposure() ; TWmessage( "TimberWolfMC is waiting for your response..." ) ; selection = CANCEL ; while( selection != CONTINUE_PROG ){ /* loop until exit */ selection = TWcheckMouse() ; switch( selection ){ case CANCEL: /* do nothing */ break ; case REDRAW: draw_the_data() ; /* use TWcheckExposure to flush exposure events since */ /* we just drew the data */ TWcheckExposure() ; break ; case ZOOM: TWzoom() ; break ; case FULLVIEW: TWfullView() ; break ; case CONTINUE_PROG: break ; case AUTO_REDRAW_ON: auto_drawS = TRUE ; break ; case AUTO_REDRAW_OFF: auto_drawS = FALSE ; break ; case CLOSE_GRAPHICS: TWcloseGraphics() ; /* update all costs and reload cells */ graphicsG = FALSE ; return ; case DRAW_LABELS: drawLabelS = TRUE ; TWmessage( "Labels will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_LABELS: drawLabelS = FALSE ; TWmessage( "Labels will be omitted from drawing" ) ; TWforceRedraw() ; break ; case DRAW_EDGES: drawEdgeS = TRUE ; TWmessage( "Edges will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_EDGES: drawEdgeS = FALSE ; TWmessage( "Edges will be omitted from drawing" ) ; TWforceRedraw() ; break ; case COLORS: TWtoggleColors() ; break ; case DRAW_EDGE_LABELS: drawEdgeLabelS = TRUE ; TWmessage( "Edge constraint labels will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_EDGE_LABELS: drawEdgeLabelS = FALSE ; TWmessage( "Edge constraint labels will be ignored" ) ; TWforceRedraw() ; break ; case DRAW_FORWARD: drawForwardS = TRUE ; TWmessage( "Forward edges will be drawn" ) ; TWforceRedraw() ; break ; case DRAW_BACKWARD: drawForwardS = FALSE ; TWmessage( "Backward edges will be drawn" ) ; TWforceRedraw() ; break ; case TRANSLATE: TWtranslate() ; break ; case DUMP_GRAPHICS: /* now change mode to dump to file */ TWsetMode(1) ; /* dump the data to a file now instead of screen */ draw_the_data() ; /* restore the state to draw to screen */ TWsetMode(0) ; break ; case TELL_POINT: TWmessage( "Pick a point" ) ; TWgetPt( &x, &y ) ; sprintf( YmsgG,"The point is (%d,%d)",x,y ) ; TWmessage( YmsgG ) ; break ; case DUMP_STATE: output() ; break ; case HIGHLITE_CELL: reply = TWgetString( "Enter cell to highlite:" ) ; selectCellS = atof( reply ) ; if( selectCellS > 0 && selectCellS <= numcellsG ){ sprintf( YmsgG, "Selected cell is :%d", selectCellS ) ; TWmessage( YmsgG ) ; } else { TWmessage( "No valid cell selected" ) ; selectCellS = 0 ; } TWforceRedraw() ; break ; case DRAW_MOVED_TILES: drawMovedS = TRUE ; TWmessage( "Moved tiles will be highlighted" ) ; TWforceRedraw() ; break ; case IGNORE_MOVED_TILES: TWmessage( "Moved tiles will NOT be highlighted" ) ; drawMovedS = FALSE ; TWforceRedraw() ; break ; case SET__3D_CAMERA: TW3DsetCamera() ; draw3DS = TRUE ; break ; case NORMAL_VIEW: TW3Dnormal_view() ; draw3DS = FALSE ; break ; case FIND_EDGE: TWmessage( "Pick an edge" ) ; TWgetPt( &x, &y ) ; stretch_edge = get_closest_edge( x, y ) ; draw_the_data() ; TWmessage( "Pick move point" ) ; TWgetPt( &x, &y ) ; stretch_graph( stretch_edge, x, y ) ; stretch_edge->marked = FALSE ; TWforceRedraw() ; break ; } if( auto_drawS && TWcheckExposure() ){ draw_the_data() ; } } TWmessage("Continuing - to interupt program click on top menu window") ; } /* end process_graphics */ /* how to draw the channel graph */ draw_changraph() { INT i ; /* temp counter */ INT color ; /* color of edge */ CHANBOXPTR nptr ; /* pointer to channel graph */ CHANBOXPTR node1 ; /* pointer to channel graph */ CHANBOXPTR node2 ; /* pointer to channel graph */ INFOPTR eptr ; /* current edge */ char label_buf[LRECL] ; /* buffer for labels */ char *label ; /* label pointer */ INT x1, x2, y1, y2 ; /* points of trace line */ /* first draw the nodes */ for( i = 1; i <= numnodesG; i++ ){ nptr = changraphG[i] ; if( drawLabelS ){ label = label_buf ; sprintf( label, "N%d", i ) ; } else { label = NULL ; } TWdrawCell( i, nptr->xc-1, nptr->yc-1, nptr->xc+1, nptr->yc+1, TWRED, label ) ; } /* end draw of nodes */ /* now draw the edges */ for( i = 1; i <= numedgesG ; i++ ){ eptr = edgeArrayG[i] ; node1 = changraphG[eptr->node1] ; node2 = changraphG[eptr->node2] ; if( eptr->marked ){ color = TWYELLOW ; } else { color = TWMEDAQUA ; } TWdrawLine( i, node1->xc, node1->yc, node2->xc, node2->yc, color, NULL ) ; } /* end draw of edges */ } /* end draw_changraph */ #endif /* NOGRAPHICS */ graywolf-0.1.4+20170307gite1bf319/src/mc_compact/changraph.c000066400000000000000000000352341305746555600227660ustar00rootroot00000000000000/* * Copyright (C) 1991-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: changraph.c DESCRIPTION: CONTENTS: DATE: Mon Feb 18 00:08:29 EST 1991 REVISIONS: Fri Mar 29 14:16:57 EST 1991 - added cell edge tree data structure. Mon Aug 12 16:44:05 CDT 1991 - updated for new Yrbtree_init. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) changraph.c (Yale) version 1.4 5/21/92" ; #endif #include #include #include #include #include #include #include static INT horz_edgeS = 0 ; /* number of distinct horizontal edges */ static INT vert_edgeS = 0 ; /* number of distinct vertical edges */ static YTREEPTR horz_treeS ; /* tree of horizontal edges */ static YTREEPTR vert_treeS ; /* tree of vertical edges */ static YSETPTR nodesetS ; /* keep track of active nodes */ /* ***************************************************************** Initialize graph by adding creating memory for it. **************************************************************** */ init_graph( numnodes, numedges ) INT numnodes ; INT numedges ; { INT i ; /* allocate memory for channel graph array */ changraphG = (CHANBOXPTR *) Ysafe_malloc( (numnodes+1)*sizeof(CHANBOXPTR) ); for( i = 0; i <= numnodes; i++ ){ changraphG[i] = (CHANBOXPTR) Ysafe_malloc( sizeof(CHANBOX) ) ; changraphG[i]->adj = NULL ; } edgeArrayG = (INFOPTR *) Ysafe_malloc( (numedges+1)*sizeof(INFOBOX) ); /* copy to global variables */ numnodesG = numnodes ; numedgesG = numedges ; } /* end init_graph */ /* ***************************************************************** Build graph by first adding nodes and node information to it. **************************************************************** */ addNode( node, xc, yc ) INT node, xc, yc ; { CHANBOXPTR nptr ; ASSERTNRETURN( 1 <= node && node <= numnodesG, "addNode", "node out of range" ) ; nptr = changraphG[node] ; nptr->node = node ; nptr->xc = xc ; nptr->yc = yc ; } /* end addNode */ /* ***************************************************************** Build channel adjacency list by forming undirected graph. **************************************************************** */ addEdge( node1, node2, HnotV, cell_lb, cell_rt ) INT node1 ; INT node2 ; BOOL HnotV ; /* TRUE if horizontal FALSE if vertical */ INT cell_lb ; /* cell on left (bottom) for vert (horz) channel */ INT cell_rt ; /* cell on right (top) for vert (horz) channel */ { static edgeCountS = 0 ; /* current number of edges */ ADJPTR newfE, /* new forward edge */ temp ; /* temporary pointer to relink adjacency list */ ADJPTR findAdjPtr() ; /* returns an edge given two nodes */ INFOPTR iptr ; /* store this only once for each edge */ /* form an undirected graph */ /* create forward edge */ ASSERTNRETURN( 1 <= node1 && node1 <= numnodesG, "addEdge", "node out of range" ) ; ASSERTNRETURN( 1 <= node2 && node2 <= numnodesG, "addEdge", "node out of range" ) ; if( temp = changraphG[node1]->adj ){ /* insert at beginning of list */ newfE = changraphG[node1]->adj = (ADJPTR) Ysafe_malloc(sizeof(ADJBOX)) ; newfE->next = temp ; /* fix back link of temp */ ASSERT( temp->prev == NULL, "addEdge","temp->prev is not NULL" ); temp->prev = newfE ; } else { /* start adjacency list */ newfE = changraphG[node1]->adj = (ADJPTR) Ysafe_malloc(sizeof(ADJBOX)) ; newfE->next = NULL ; } newfE->prev = NULL ; /* load data now */ newfE->tnode = node2 ; newfE->fnode = node1 ; /* we only want to store one infobox record for each edge */ /* see if forward edge was previously formed */ if( temp = findAdjPtr( node2, node1 )){ ASSERTNRETURN( temp->info, "addEdge", "iptr NULL" ) ; newfE->info = iptr = temp->info ; /* set the loc, start, and end fields */ if( HnotV ){ /* guarantee that the loc is the lower number node */ if( node1 < node2 ){ iptr->loc = &(changraphG[node1]->yc) ; } else { iptr->loc = &(changraphG[node2]->yc) ; } if( changraphG[node1]->xc < changraphG[node2]->xc ){ iptr->start = &(changraphG[node1]->xc) ; iptr->end = &(changraphG[node2]->xc) ; } else { iptr->start = &(changraphG[node2]->xc) ; iptr->end = &(changraphG[node1]->xc) ; } } else { /* guarantee that the loc is the lower number node */ if( node1 < node2 ){ iptr->loc = &(changraphG[node1]->xc) ; } else { iptr->loc = &(changraphG[node2]->xc) ; } if( changraphG[node1]->yc < changraphG[node2]->yc ){ iptr->start = &(changraphG[node1]->yc) ; iptr->end = &(changraphG[node2]->yc) ; } else { iptr->start = &(changraphG[node2]->yc) ; iptr->end = &(changraphG[node1]->yc) ; } } return ; } else { iptr = newfE->info = (INFOPTR) Ysafe_malloc( sizeof(INFOBOX) ) ; edgeArrayG[++edgeCountS] = iptr ; /* determine number of unique edges for edge tree */ if( HnotV ){ horz_edgeS++ ; } else { vert_edgeS++ ; } } iptr->HnotV = HnotV ; iptr->cell_lb = cell_lb ; iptr->cell_rt = cell_rt ; iptr->node1 = MIN( node1, node2 ) ; iptr->node2 = MAX( node1, node2 ) ; iptr->marked = FALSE ; } /* end addEdge */ /* returns the adjacency pointer(edge) given two node of channel graph */ ADJPTR findAdjPtr( node1, node2 ) INT node1, node2 ; { ADJPTR curEdge ; for( curEdge=changraphG[node1]->adj;curEdge;curEdge=curEdge->next ){ if( curEdge->tnode == node2 ){ /* we found the edge */ return( curEdge ) ; } } /* if we didn't find the edge return NULL */ return( NULL ) ; } /* end findAdjPtr */ INT compare_edges( edge1, edge2 ) INFOPTR edge1, edge2 ; { /* explicitly enumerate cases to avoid wraparound */ if( *(edge1->loc) == *(edge2->loc) ){ /* in case of tie sort on start position */ if( *(edge1->start) == *(edge2->start) ){ return( 0 ) ; } else if( *(edge1->start) < *(edge2->start) ){ return( -1 ) ; } else { return( 1 ) ; } } else { /* sort by location */ if( *(edge1->loc) == *(edge2->loc) ){ return( 0 ) ; } else if( *(edge1->loc) < *(edge2->loc) ){ return( -1 ) ; } else { return( 1 ) ; } } } /* end compare_edges */ VOID print_edge( edge ) INFOPTR edge ; { fprintf( stderr, "edge %2d-%2d loc:%3d start:%3d end:%3d HnotV:%d\n", edge->node1, edge->node2, *(edge->loc), *(edge->start), *(edge->end), edge->HnotV ) ; } /* end print_edge */ build_trees() { INT i ; INFOPTR eptr ; /* current edge */ CELLBOXPTR cptr ; horz_treeS = Yrbtree_init( compare_edges ) ; vert_treeS = Yrbtree_init( compare_edges ) ; for( i = 1; i <= numedgesG ; i++ ){ eptr = edgeArrayG[i] ; if( eptr->HnotV ){ Yrbtree_insert( horz_treeS, eptr ) ; } else { Yrbtree_insert( vert_treeS, eptr ) ; } } /* end for loop */ D( "mc_compact/xtree", fprintf( stderr, "The horizontal edges:\n" ) ; Yrbtree_dump( horz_treeS, print_edge ) ; ) ; D( "mc_compact/ytree", fprintf( stderr, "The vertical edges:\n" ) ; Yrbtree_dump( vert_treeS, print_edge ) ; ) ; nodesetS = Yset_init( 1, numnodesG ) ; /* now build the edge trees for each cell */ for( i = 1; i <= numcellsG; i++ ){ cptr = cellarrayG[i] ; cptr->hedges = Yrbtree_init( compare_edges ) ; cptr->vedges = Yrbtree_init( compare_edges ) ; } for( i = 1; i <= numedgesG ; i++ ){ eptr = edgeArrayG[i] ; if( eptr->HnotV ){ /* horizontal edges */ if( eptr->cell_lb && eptr->cell_lb <= numcellsG ){ Yrbtree_insert( cellarrayG[eptr->cell_lb]->hedges, eptr); } if( eptr->cell_rt && eptr->cell_rt <= numcellsG ){ Yrbtree_insert( cellarrayG[eptr->cell_rt]->hedges, eptr); } } else { /* vertical edges */ if( eptr->cell_lb && eptr->cell_lb <= numcellsG ){ Yrbtree_insert( cellarrayG[eptr->cell_lb]->vedges, eptr); } if( eptr->cell_rt && eptr->cell_rt <= numcellsG ){ Yrbtree_insert( cellarrayG[eptr->cell_rt]->vedges, eptr); } } } } /* end build_trees */ /* given an x and y find the closest edge to the right or top */ INFOPTR get_closest_edge( x, y ) INT x, y ; { INFOBOX lo, hi ; /* set the bounds for the search */ INFOPTR edge ; /* current edge */ INFOPTR closest_edge ; /* save the closest edge */ BOOL start ; /* true if we intersect interval */ INT dist ; /* current distance to edge */ INT closest_dist ; /* best distance so far */ INT min ; /* minimum integer */ INT max ; /* maximum integer */ /* need these since loc, and start are defined as INT * */ /* they are defined that way because update edges will be */ /* much easier */ min = INT_MIN ; max = INT_MAX ; /* first look thru the horizontal tree */ lo.loc = &y ; lo.start = &min ; hi.loc = &max ; hi.start = &min ; closest_dist = INT_MAX ; closest_edge = NIL(INFOBOX *) ; start = FALSE ; /* no edge found yet */ for( edge = (INFOPTR) Yrbtree_interval(horz_treeS,&lo,&hi,TRUE); edge; edge = (INFOPTR) Yrbtree_interval(horz_treeS,&lo,&hi,FALSE) ){ if( *(edge->start) <= x && x <= *(edge->end) ){ dist = ABS( *(edge->loc) - y ) ; if( dist < closest_dist ){ closest_dist = dist ; closest_edge = edge ; } start = TRUE ; } else if( start ){ break ; } } /* next look thru the vertical tree */ lo.loc = &x ; lo.start = &min ; hi.loc = &max ; hi.start = &min ; start = FALSE ; /* no edge found yet */ for( edge = (INFOPTR) Yrbtree_interval(vert_treeS,&lo,&hi,TRUE); edge; edge = (INFOPTR) Yrbtree_interval(vert_treeS,&lo,&hi,FALSE) ){ if( *(edge->start) <= y && y <= *(edge->end) ){ dist = ABS( *(edge->loc) - x ) ; if( dist < closest_dist ){ closest_dist = dist ; closest_edge = edge ; } start = TRUE ; } else if( start ){ break ; } } if( closest_edge ){ closest_edge->marked = TRUE ; } return( closest_edge ) ; } /* end get_closest_edge */ stretch_graph( stretch_edge, x, y ) INFOPTR stretch_edge ; INT x, y ; { INFOBOX lo, hi ; /* set the bounds for the search */ INFOPTR edge ; /* the current pointer */ CHANBOXPTR nptr1 ; /* pointer to node 1 info */ CHANBOXPTR nptr2 ; /* pointer to node 2 info */ INT location ; /* location of the stretch_edge */ INT new_loc ; /* the new location of node */ INT delta ; /* the stretch or shrink amount */ INT min ; /* minimum integer */ INT max ; /* maximum integer */ /* need these since loc, and start are defined as (INT *) */ /* they are defined that way because update edges will be */ /* much easier */ min = INT_MIN ; max = INT_MAX ; /* use the nodeset to keep track of which nodes have already been */ /* updated */ Yset_empty( nodesetS ) ; if( stretch_edge->HnotV ){ delta = y - *(stretch_edge->loc) ; location = *(stretch_edge->loc) - 1 ; lo.loc = &location ; lo.start = &min ; hi.loc = &max ; hi.start = &min ; for( edge = (INFOPTR) Yrbtree_interval(horz_treeS,&lo,&hi,TRUE); edge; edge = (INFOPTR) Yrbtree_interval(horz_treeS,&lo,&hi,FALSE)){ /* check to see if this edge's location is valid */ /* node1 is always the location node */ if( Yset_member( nodesetS, edge->node1 ) ){ new_loc = *(edge->loc) ; } else { /* this node has not been updated yet */ /* update position of the edge */ new_loc = *(edge->loc) + delta ; } /* now update all the appropriate edges and nodes */ /* first the nodes */ nptr1 = changraphG[edge->node1] ; if( nptr1->yc != new_loc && !(Yset_member( nodesetS, edge->node1)) ){ nptr1->yc = new_loc ; Yset_add( nodesetS, edge->node1 ) ; } nptr2 = changraphG[edge->node2] ; if( nptr2->yc != new_loc && !(Yset_member( nodesetS, edge->node2)) ){ nptr2->yc = new_loc ; Yset_add( nodesetS, edge->node2 ) ; } } } else { delta = x - *(stretch_edge->loc) ; location = *(stretch_edge->loc) - 1 ; lo.loc = &location ; lo.start = &min ; hi.loc = &max ; hi.start = &min ; for( edge = (INFOPTR) Yrbtree_interval(vert_treeS,&lo,&hi,TRUE); edge; edge = (INFOPTR) Yrbtree_interval(vert_treeS,&lo,&hi,FALSE)){ /* check to see if this edge's location is valid */ /* node1 is always the location node */ if( Yset_member( nodesetS, edge->node1 ) ){ new_loc = *(edge->loc) ; } else { /* this node has not been updated yet */ /* update position of the edge */ new_loc = *(edge->loc) + delta ; } /* now update all the appropriate edges and nodes */ /* first the nodes */ nptr1 = changraphG[edge->node1] ; if( nptr1->xc != new_loc && !(Yset_member( nodesetS, edge->node1)) ){ nptr1->xc = new_loc ; Yset_add( nodesetS, edge->node1 ) ; } nptr2 = changraphG[edge->node2] ; if( nptr2->xc != new_loc && !(Yset_member( nodesetS, edge->node2)) ){ nptr2->xc = new_loc ; Yset_add( nodesetS, edge->node2 ) ; } } } } /* end stretch_graph */ graywolf-0.1.4+20170307gite1bf319/src/mc_compact/cmain.c000066400000000000000000000164211305746555600221170ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: cmain.c DESCRIPTION:This file contains main control routine for compaction program. CONTENTS: DATE: Apr 17, 1989 REVISIONS: Apr 30, 1989 - modified program for new library and added partion code to compactor. May 3, 1989 - changed to Y prefixes. May 6, 1989 - added no graphics compile switch Sat Feb 23 00:48:39 EST 1991 - added constraints flag. Fri Mar 29 14:17:51 EST 1991 - added DEBUGX switch and added path deck initialization. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) cmain.c (Yale) version 7.4 4/21/91" ; #endif #include #include #include #include #include #include #include #define COMPACT_DEFS #include #define EXPECTEDMEMORY (256 * 1024) /* 256k is more than enough */ main( argc , argv ) int argc ; char *argv[] ; { char *ptr ; int windowId ; #ifdef DEBUGX extern int _Xdebug ; _Xdebug = TRUE ; #endif /* start up cleanup handler */ YINITCLEANUP( argv[0], NULL, MAYBEDUMP ) ; Yinit_memsize( EXPECTEDMEMORY ) ; if( argc < 8 || argc > 10 ){ syntax() ; } else { graphicsG = TRUE ; alignG = FALSE ; compactG = TRUE ; parasiteG = FALSE ; partitionG = FALSE ; debugG = FALSE ; windowId = 0 ; constraintsG = FALSE ; if( *argv[1] == '-' ){ for( ptr = ++argv[1]; *ptr; ptr++ ){ switch( *ptr ){ case 'a': alignG = TRUE ; break ; case 'd': debugG = TRUE ; break ; case 'c': constraintsG = TRUE ; break ; case 'n': graphicsG = FALSE ; break ; case 'p': partitionG = TRUE ; break ; case 'v': compactG = FALSE ; break ; case 'w': parasiteG = TRUE ; break ; default: sprintf( YmsgG,"Unknown option:%c\n", *ptr ) ; M(ERRMSG,"main",YmsgG); syntax() ; } } YdebugMemory( debugG ) ; fprintf( stdout, "\n%s\n",YinitProgram(COMPACT,"v1.0",NULL) ) ; cktNameG = Ystrclone( argv[2] ); blockrG = atoi( argv[3] ) ; blocktG = atoi( argv[4] ) ; xgridG = atoi( argv[5] ) ; ygridG = atoi( argv[6] ) ; xspaceG = atoi( argv[7] ) ; yspaceG = atoi( argv[8] ) ; /* now tell the user what he picked */ M(MSG,NULL,"compactor switches:\n" ) ; if( compactG ){ M(MSG,NULL,"\tViolation removal and compaction\n" ) ; } else { M(MSG,NULL,"\tViolation removal only\n" ) ; } if( alignG ){ M(MSG,NULL,"\tCell will be aligned by channels.\n" ) ; } if( debugG ){ YsetDebug( TRUE ) ; M(MSG,NULL,"\tdebug on\n" ) ; } if( graphicsG ){ M(MSG,NULL,"\tGraphics mode on\n" ) ; } else { M(MSG,NULL,"\tGraphics mode off\n" ) ; } if( partitionG ){ M(MSG,NULL,"\tMacro cell placement algorithm on\n" ) ; } if( parasiteG ){ M(MSG,NULL,"\tCompactor will inherit window\n" ) ; /* look for windowid */ if( argc != 10 ){ M(ERRMSG,"compactor","Need to specify windowID\n" ) ; syntax() ; } else { windowId = atoi( argv[9] ) ; } } M(MSG,NULL,"\n" ) ; } else if( argc == 8 ){ cktNameG = Ystrclone( argv[1] ); blockrG = atoi( argv[2] ) ; blocktG = atoi( argv[3] ) ; xgridG = atoi( argv[4] ) ; ygridG = atoi( argv[5] ) ; xspaceG = atoi( argv[6] ) ; yspaceG = atoi( argv[7] ) ; YdebugMemory( FALSE ) ; fprintf( stdout, "\n%s\n",YinitProgram(COMPACT,"v1.0",NULL) ) ; } else { syntax() ; } } /* ********************** end initialization ************************* */ /* set core region */ blocklG = 0 ; blockbG = 0 ; blockmxG = blockrG / 2 ; blockmyG = blocktG / 2 ; /* turn on the graphics if requested */ if( graphicsG ){ G( init_graphics( argc, argv, windowId ) ) ; } readtiles() ; if( constraintsG ){ /* read the channel graph */ read_cgraph() ; build_trees() ; path_deckG = Ydeck_init() ; } if( graphicsG ){ G( draw_the_data() ) ; } grid_data() ; if( graphicsG ){ G( draw_the_data() ) ; } /* ------------------------------------------------------------------ Determine which compaction option is requested. The normal case is to remove violations and compact along the critical path. For the partition case we need to also handle the constraints placed on softcells versus hardcells. --------------------------------------------------------------------*/ if( partitionG ){ partition_compact() ; } else { /* normal case */ remove_violations() ; M(MSG,NULL,"Violation removal completed...\n") ; if( compactG ){ compact() ; } } output() ; if( graphicsG ){ G( TWcloseGraphics() ) ; } YexitPgm(PGMOK); } /* end main */ /* give user correct syntax */ syntax() { M(ERRMSG,NULL,"\n" ) ; M(MSG,NULL,"Incorrect syntax. Correct syntax:\n"); sprintf( YmsgG, "\n%s [-nwvp] designName blockr blockt xgrid ygrid xspace yspace [windowId] \n", COMPACT ); M(MSG,NULL,YmsgG ) ; M(MSG,NULL,"\twhose options are one or more of the following:\n"); M(MSG,NULL,"\t\tn - no graphics - the default is to open the\n"); M(MSG,NULL,"\t\t display and output graphics to an Xwindow\n"); M(MSG,NULL,"\t\tw - parasite mode - user must specify windowId\n"); M(MSG,NULL,"\t\tv - remove only violations - overlap between cells\n"); M(MSG,NULL,"\t\t - default is to perform compaction in addition\n"); M(MSG,NULL,"\t\td - prints debug info and performs extensive\n"); M(MSG,NULL,"\t\t error checking\n"); M(MSG,NULL,"\t\tp - partition algorithm is selected for placing\n"); M(MSG,NULL,"\t\t pads in stdcell context\n"); M(MSG,NULL,"\txgrid and ygrid force cells to specified grid positions\n"); M(MSG,NULL,"\tblockr and blockt are the maximum spans of core region\n"); YexitPgm(COMPACTFAIL); } graywolf-0.1.4+20170307gite1bf319/src/mc_compact/compact.h000066400000000000000000000314241305746555600224630ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- "@(#) compact.h version 7.5 11/8/91" FILE: compact.h DESCRIPTION:This file contains type declarations for the compaction routines. CONTENTS: DATE: Apr 8, 1988 REVISIONS: Oct 24, 1988 - added moved field to tilenode record for graph concurrency problem. Oct 29, 1988 - made PICKETBOX doubly linked list to facilitate deletes. Apr 17, 1989 - made modification to make compactor separate program. Also now handle multiple tile cells correctly. Apr 30, 1989 - added definitions to handle partition case. Sun Nov 4 12:50:58 EST 1990 - changed slack to be over cells not tiles. Sat Feb 23 00:49:20 EST 1991 - added constraint compaction data structures. Fri Mar 29 14:18:56 EST 1991 - added stretched to CELL box definition and added path_deck to definitions. Mon May 6 22:32:34 EDT 1991 - added gridding reference to cell fields. Fri Nov 8 18:16:21 EST 1991 - removed INT_SMALL and INT_LARGE definitions since gcc couldn't handle it. ----------------------------------------------------------------- */ #ifndef COMPACT_H #define COMPACT_H #ifndef COMPACT_DEFS #define EXTERN extern #else #define EXTERN #endif /* if not using makefile and debug is wanted add it here */ /* #define DEBUG */ /* remove graphics lines of code if compile switch is on */ #ifdef NOGRAPHICS #define G(x_xz) #else #define G(x_xz) x_xz #endif /* NOGRAPHICS */ #include #include #include #include #include /********************** DEFINE STATEMENTS *********************/ #define SOURCE 0 /* definitions in x and y graph */ #define SINK numtilesG+1 #define XSOURCE 0 /* relative to tileNodeG */ #define XSINK numtilesG+1 #define YSOURCE numtilesG+2 /* relative to tileNodeG */ #define YSINK numtilesG+3 #define XSOURCEC 0 #define XSINKC numcellsG+1 #define YSOURCEC numcellsG+2 #define YSINKC numcellsG+3 #define NODIRECTION 0 #define GOINGRIGHT 1 #define GOINGLEFT 2 #define CELLTYPE 0 /* used in determine macro placement */ #define STDCELLTYPE 1 #define XFORWARD 1 #define XBACKWARD 2 #define YFORWARD 3 #define YBACKWARD 4 #define COMPACT "mc.compactor" /* the program name */ #define CFAILBASE 16 /* program problem exit code */ #define COMPACTFAIL (CFAILBASE+1) /* catastrophic problem exit code */ #define NOTOUCH 0 /* tiles don't touch or overlap */ #define TOUCH -1 /* tiles touch but dont overlap */ #define OVERLAP1 1 /* tiles overlap completely */ #define OVERLAP2 2 /* tiles overlap to right (top) */ #define OVERLAP3 3 /* tiles overlap to left (bot) */ /* memory usage macro */ #define MEMUSAGE { sprintf( YmsgG,"Current memory usage:%d\n", \ YgetCurMemUse() ) ;\ M( MSG, NULL, YmsgG ) ; } /* macro to speed division by 2 */ #define DIVIDED_BY_2 >> 1 typedef struct picketbox { /* use for both x and y graph */ union { INT top ; /* xgraph */ INT rght ; /* ygraph */ } pt1 ; union { INT bot ; /* xgraph */ INT lft ; /* ygraph */ } pt2 ; INT node ; struct picketbox *next ; struct picketbox *prev ; } PICKETBOX, *PICKETPTR ; typedef struct errorbox { INT nodeI ; INT nodeJ ; struct errorbox *next ; } ERRORBOX, *ERRORPTR ; typedef struct ecompbox { INT constraint ; INT node ; BOOL marked ; struct ecompbox *next ; } ECOMPBOX, *ECOMPBOXPTR ; typedef struct node { /* the nodes or tiles of a cell */ INT node ; struct node *next ; } NODEBOX, *NODEPTR ; typedef struct cellbox { INT xcenter ; /* the center of the cell */ INT ycenter ; INT l ; /* the extent of the cell bounding box */ INT r ; /* global position */ INT b ; INT t ; INT l_rel ; /* the extent of the cell bounding box */ INT r_rel ; /* relative to center of cell */ INT b_rel ; INT t_rel ; INT cellnum ; /* TimberwolfMC cell number */ INT xmin ; /* the minimum x you can place the cell */ INT xmax ; /* the maximum x you can place the cell */ INT ymin ; /* the minimum y you can place the cell */ INT ymax ; /* the maximum y you can place the cell */ INT xlo ; /* one of the leftest nodes of the cell rel to l */ INT xhi ; /* one of the rightest nodes of the cell rel to l*/ INT ylo ; /* one of the lowest nodes of the cell rel to b */ INT yhi ; /* one of the highest nodes of the cell rel to b */ INT xoffset ; /* offset for cell gridding */ INT yoffset ; /* offset for cell gridding */ BOOL children ; BOOL type ; /* whether a hard or soft cell */ BOOL multi ; /* whether cell has multiple tiles */ BOOL stretched ; /* whether cell graph has been stretched */ NODEPTR tiles ; /* the tiles belonging to this cell */ YTREEPTR hedges ; /* horz edges of the channel graph touching cell */ YTREEPTR vedges ; /* vert edges of the channel graph touching cell */ } CELLBOX, *CELLBOXPTR ; typedef struct compactbox { INT cell ; INT node ; INT l ; /* global position of tile */ INT b ; INT r ; INT t ; INT l_rel ; /* relative postion of tile */ INT b_rel ; INT r_rel ; INT t_rel ; INT xspan ; /* xpan of tile r_rel - l_rel */ INT yspan ; /* xpan of tile t_rel - b_rel */ BOOL criticalX ; /* on the critical list */ BOOL criticalY ; BOOL moved ; /* whether cell has been moved in movestrategy */ INT xvalueMin ; /* for longest path calculations */ INT xvalueMax ; INT yvalueMin ; INT yvalueMax ; INT pathx ; INT pathy ; BOOL type ; /* whether a hard or soft tile */ BOOL multi ; /* whether cell has multiple tiles */ INT xancestrF ; INT xancestrB ; INT yancestrF ; INT yancestrB ; INT direction ; /* current direction cell is moving */ ECOMPBOXPTR xadjF; /* the edges in the graph */ ECOMPBOXPTR xadjB; ECOMPBOXPTR yadjF; ECOMPBOXPTR yadjB; } COMPACTBOX, *COMPACTPTR ; typedef struct { /* information for edge - store 1 per edge */ INT node1 ; /* the two nodes of the edge */ INT node2 ; INT cell_lb ; /* cell on left/bottom if non-zero - cellnum ow */ INT cell_rt ; /* cell on right/top if non-zero - cellnum o.w. */ BOOL HnotV ; /* true if edge horizontal - false if vertical */ INT *loc ; /* constant part of coordinate */ INT *start ; /* start of edge */ INT *end ; /* end coordinate of edge */ BOOL marked ; /* whether this edge is marked */ } INFOBOX, *INFOPTR ; typedef struct adjptr { /* added adjacency list augmenting adj matrix */ int tnode ; /* to node - head of edge */ int fnode ; /* from node - tail of edge */ INFOPTR info ; /* all the details of the edge store only once */ struct adjptr *next ; /* doubly linked list of edge's */ struct adjptr *prev ; } ADJBOX, *ADJPTR ; typedef struct { /* a node of channel graph uses following data */ INT node ; /* self index */ INT xc ; /* center of node for channel graph */ INT yc ; ADJPTR adj ; /* edges connecting to this node */ } CHANBOX, *CHANBOXPTR ; typedef struct queue { INT data ; struct queue *next ; } QUEUEBOX, *QUEUEPTR ; /* --------------------------------------------------------------- MACRO DEFINITIONS FOR QUEUE USED IN LONGEST PATH ALGORITHM To function two variables queue and botqueue must be defined in routine. Currently uses safe_malloc routines but could be changed to memory pool if speed need. /* /* initialize queue */ #define INITQUEUE( queue, node ) \ { queue = (QUEUEPTR) Ysafe_malloc( sizeof(QUEUEBOX) ) ; \ queue->next = NULL ; \ botqueue = queue ; \ queue->data = node ; \ } /* top queue return the element at top of the queue */ #define TOPQUEUE( queue ) \ queue->data ;\ { QUEUEPTR temp = queue ; \ queue = queue->next ; \ Ysafe_free( temp ) ; \ } /* add a vertex to the end of the queue */ #define ADD2QUEUE( queue, node ) \ { if( queue ){ \ botqueue->next = (QUEUEPTR) Ysafe_malloc( sizeof(QUEUEBOX) ) ; \ botqueue = botqueue->next ; \ botqueue->next = NULL ; \ botqueue->data = node ; \ } else { \ INITQUEUE( queue, node ) ; \ } \ } /* ******************** GLOBAL VARIABLES *********************** */ /* the graph data structure */ EXTERN COMPACTPTR *tileNodeG ; /* array of pointers to nodes */ EXTERN COMPACTPTR *xGraphG ; /* array of nodes to x node ptrs */ EXTERN COMPACTPTR *yGraphG ; /* array of yGraph node pointers */ EXTERN YSETPTR tileSetG ; /* make set of tiles */ /* the size of the data */ EXTERN INT numcellsG ; /* number of cells to be compacted */ EXTERN INT numtilesG ; /* number of tiles to be compacted */ EXTERN INT last_tileG ; /* last tile in x or y graph */ EXTERN INT last_cellG ; /* last cell including sources and sinks */ EXTERN char *cktNameG ; /* the name of the circuit */ EXTERN CELLBOXPTR *cellarrayG ; /* the cell data */ EXTERN CELLBOXPTR *slackG ; /* array of cells sorted by slack */ EXTERN INT blockbG ; /* core bottom */ EXTERN INT blocklG ; /* core left */ EXTERN INT blockrG ; /* core right */ EXTERN INT blocktG ; /* core top */ EXTERN INT blockmxG ; /* core center */ EXTERN INT blockmyG ; /* core center */ EXTERN INT *ancestorG ; /* array of ancestor counts */ /* FOR THE CHANNEL GRAPH */ EXTERN INT numnodesG ; /* number of nodes in the channel graph */ EXTERN INT numedgesG ; /* number of edges in the channel graph */ EXTERN CHANBOXPTR *changraphG ; /* array of nodes of channel graph */ EXTERN INFOPTR *edgeArrayG ; /* array of edges of channel graph */ EXTERN YDECKPTR path_deckG ; /* list of nodes in critical path */ /* the user requests */ EXTERN BOOL alignG ; /* TRUE if channel are to be aligned */ EXTERN BOOL compactG ; /* TRUE if compaction is desired */ EXTERN BOOL graphicsG ; /* TRUE if graphics are desired */ EXTERN BOOL parasiteG ; /* TRUE if we want to inherit window */ EXTERN BOOL partitionG ; /* TRUE if partitioning is requested */ EXTERN BOOL constraintsG; /* TRUE if constraint graph is present */ EXTERN BOOL debugG ; /* TRUE if debug is requested */ EXTERN INT xgridG ; /* force cells to given x grid */ EXTERN INT ygridG ; /* force cells to given y grid */ EXTERN INT xspaceG ; /* xspacing between tiles of different cells */ EXTERN INT yspaceG ; /* yspacing between tiles of different cells */ #endif /* COMPACT_H */ graywolf-0.1.4+20170307gite1bf319/src/mc_compact/compactor.c000066400000000000000000000306501305746555600230170ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: compactor.c DESCRIPTION:This file contains main control for compaction algorithm. CONTENTS: DATE: Apr 8, 1988 REVISIONS: Nov 5, 1988 - free violations and modified position of sources and sinks. Dec 4, 1988 - corrected error in where to get data. Jan 15, 1989 - fixed constraint problem for softcells by saving contents of tilebox and set orig_ fields correctly for compaction cycle for softcells. Jan 25, 1989 - removed incorrect force of box size to block area and added \n for new message macro. Mar 11, 1989 - added graphics conditional compile and commented out compactor state dump. Mar 30, 1989 - changed tile datastructure. Apr 17, 1989 - changed compactor to independent program. Apr 30, 1989 - changed compaction algorithm so it is both easier to read and more robust. May 3, 1989 - changed to Y prefixes. Sun Nov 4 13:18:12 EST 1990 - added set_draw_critical for making a pretty picture. Fri Mar 29 14:25:29 EST 1991 - now save the critical path. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) compactor.c version 7.3 3/29/91" ; #endif #include #include remove_violations() { ERRORPTR violations, saveError, buildXGraph(), buildYGraph() ; /* --------------------------------------------------------------- VIOLATION REMOVAL CYCLE - iterate till all violations are removed */ while( TRUE ){ buildXGraph() ; violations = buildYGraph() ; if( violations ){ /* violations unresolved */ /* move strategy is to resolve overlap violations */ moveStrategy( violations ) ; } else { break ; /* exit loop */ } D( "mc_compact/remove_violations", MEMUSAGE ) ; /* G( ) is NOGRAPHICS conditional compile */ G( if( graphicsG && TWinterupt() ) ){ G( process_graphics() ) ; } G( draw_the_data() ) ; freeGraph(XFORWARD ) ; freeGraph(XBACKWARD ) ; freeGraph(YFORWARD ) ; freeGraph(YBACKWARD ) ; D( "mc_compact/remove_violations", MEMUSAGE ) ; } /* ----- END VIOLATION REMOVAL CYCLE ------ */ freeGraph(XFORWARD ) ; freeGraph(XBACKWARD ) ; freeGraph(YFORWARD ) ; freeGraph(YBACKWARD ) ; G( draw_the_data() ) ; } /* end remove_violations */ compact() { INT length ; /* length of longest path */ INT count ; /* number of compaction cycles */ ERRORPTR violations, saveError, buildXGraph(), buildYGraph() ; BOOL compactNotSat ; /* compaction criteria is not satisfied */ BOOL xNotY_toggle ; /* toggle between x and y compaction. */ /* --------------------------------------------------------------- COMPACTION CYCLE - iterate till all violations are removed and compaction criteria is satisfied. */ count = 0 ; compactNotSat = TRUE ; xNotY_toggle = TRUE ; if(!(debugG)) fprintf( stderr,"\nCompaction Begins...\n" ) ; while( compactNotSat ){ /* first build x and y graphs */ buildXGraph() ; violations = buildYGraph() ; if( violations ){ /* violations unresolved */ /* move strategy is to resolve overlap violations */ G( set_draw_critical( FALSE ) ) ; moveStrategy( violations ) ; fprintf( stderr,"V " ) ; D( "mc_compact/viofail", YexitPgm( PGMFAIL ) ; ) ; if( debugG ) { fprintf( stderr, "\n" ) ; } } else { G( set_draw_critical( TRUE ) ) ; if( xNotY_toggle ){ fprintf( stderr,"X " ) ; length = longestxPath( TRUE ) ; /* move strategy is to compact in x direction */ move_compactx( length ); xNotY_toggle = FALSE ; /* flip toggle */ } else { fprintf( stderr,"Y " ) ; length = longestyPath( TRUE ) ; /* move strategy is to compact in y direction */ move_compacty( length ); xNotY_toggle = TRUE ; /* flip toggle */ } compactNotSat = test_area() ; if( debugG) { fprintf( stderr, "\n" ) ; } } if( (!(debugG)) && (++count % 15) == 0 ){ fprintf( stderr, "\n" ) ; } D( "mc_compact/compact", MEMUSAGE ) ; /* G( ) is NOGRAPHICS conditional compile */ G( if( graphicsG && TWinterupt() ) ){ G( process_graphics() ) ; } G( draw_the_data() ) ; freeGraph(XFORWARD) ; freeGraph(XBACKWARD) ; freeGraph(YFORWARD) ; freeGraph(YBACKWARD) ; D( "mc_compact/compact", MEMUSAGE ) ; } /* ----- END COMPACTION CYCLE ------ */ if(!(debugG)){ fprintf( stderr, "\n\n" ) ; } /* grid the cells */ grid_data() ; /* make sure we have no violations */ remove_violations() ; /* show the results */ G( draw_the_data() ) ; } /* end compact */ freeGraph( direction ) INT direction ; { INT i ; ECOMPBOXPTR edge , saveEdge ; for( i=0 ; i<= last_tileG ; i++ ){ switch( direction ){ case XFORWARD: edge=xGraphG[i]->xadjF; xGraphG[i]->xadjF = NULL ; break ; case XBACKWARD: edge=xGraphG[i]->xadjB; xGraphG[i]->xadjB = NULL ; break ; case YFORWARD: edge=yGraphG[i]->yadjF; yGraphG[i]->yadjF = NULL ; break ; case YBACKWARD: edge=yGraphG[i]->yadjB; yGraphG[i]->yadjB = NULL ; break ; } /* free all the edges */ for( ;edge; ){ saveEdge = edge ; edge = edge->next ; Ysafe_free(saveEdge) ; } } /* end for loop */ } INT path(direction) INT direction ; { INT node ; INT source ; switch( direction ){ case XFORWARD : node = numtilesG + 1 ; if( constraintsG ){ Ydeck_empty( path_deckG, NIL(VOIDPTR)) ; } D( "mc_compact/path", printf("Longest path in xGraphG-Forward direction:\n" ) ) ; source = 0 ; /* print backwards so list is in correct order columatted */ while( node != source ){ D( "mc_compact/path", printf("Node:%2d cell:%2d xvalueMin:%4d\n", tileNodeG[node]->node, tileNodeG[node]->cell, tileNodeG[node]->xvalueMin ) ) ; tileNodeG[node]->criticalX = TRUE ; /* update node */ node = tileNodeG[node]->pathx ; if( constraintsG && node != source ){ Ydeck_push( path_deckG, (VOIDPTR) node ) ; } } return( tileNodeG[numtilesG+1]->xvalueMin ) ; case XBACKWARD: node = 0 ; D( "mc_compact/path", printf("Longest path in xGraphG-Backward direction:\n" ) ) ; source = numtilesG + 1 ; /* print backwards so list is in correct order columatted */ while( node != source ){ D( "mc_compact/path", printf("Node:%2d cell:%2d xvalueMax:%4d\n", tileNodeG[node]->node, tileNodeG[node]->cell, tileNodeG[node]->xvalueMax ) ) ; /* update node */ node = tileNodeG[node]->pathx ; } return( tileNodeG[0]->xvalueMax ) ; case YFORWARD : node = numtilesG + 3 ; if( constraintsG ){ Ydeck_empty( path_deckG, NIL(VOIDPTR)) ; } D( "mc_compact/path", printf("Longest path in yGraphG-Forward direction:\n" ) ); source = numtilesG + 2 ; /* print backwards so list is in correct order columatted */ while( node != source ){ D( "mc_compact/path", printf("Node:%2d cell:%2d yvalueMin:%4d\n", tileNodeG[node]->node, tileNodeG[node]->cell, tileNodeG[node]->yvalueMin ) ); tileNodeG[node]->criticalY = TRUE ; /* update node */ node = tileNodeG[node]->pathy ; if( constraintsG && node != source ){ Ydeck_push( path_deckG, (VOIDPTR) node ) ; } } return( tileNodeG[numtilesG+3]->yvalueMin ) ; case YBACKWARD: node = numtilesG + 2 ; D( "mc_compact/path", printf("Longest path in yGraphG-Backward direction:\n" ) ) ; source = numtilesG + 3 ; while( node != source ){ D( "mc_compact/path", printf("Node:%2d cell:%2d yvalueMax:%4d\n", tileNodeG[node]->node, tileNodeG[node]->cell, tileNodeG[node]->yvalueMax ) ) ; /* update node */ node = tileNodeG[node]->pathy ; } return( tileNodeG[numtilesG+2]->yvalueMax ) ; default: M(ERRMSG,"dpath","invalid direction in graph\n") ; return( 0 ) ; } } cleanupGraph( direction ) INT direction ; { INT i ; ECOMPBOXPTR edge , match, saveNode ; INT matchNode, sameNode ; for( i=0 ; i<= last_tileG ; i++ ){ switch( direction ){ case XFORWARD: edge=xGraphG[i]->xadjF; sameNode = xGraphG[i]->node ; break ; case XBACKWARD: edge=xGraphG[i]->xadjB; sameNode = xGraphG[i]->node ; break ; case YFORWARD: edge=yGraphG[i]->yadjF; sameNode = yGraphG[i]->node ; break ; case YBACKWARD: edge=yGraphG[i]->yadjB; sameNode = yGraphG[i]->node ; break ; } for( ;edge;edge=edge->next ){ matchNode = edge->node ; saveNode = edge ; for(match=edge->next; match ; ){ if( match->node == matchNode ){ D( "mc_compact/cleanupGraph", sprintf( YmsgG, "We discovered redundant edge-N%d -> N%d\n", sameNode, match->node ) ; M(MSG, NULL, YmsgG ) ) ; /* need to update ancestors */ /* the edge in question is sameNode:match->node */ switch( direction ){ case XFORWARD: tileNodeG[matchNode]->xancestrF-- ; break ; case XBACKWARD: tileNodeG[matchNode]->xancestrB-- ; break ; case YFORWARD: tileNodeG[matchNode]->yancestrF-- ; break ; case YBACKWARD: tileNodeG[matchNode]->yancestrB-- ; break ; } ASSERT( edge->constraint == match->constraint, "cleanupGraph", "Redundant edges have mismatching constraints\n"); /* now delete */ saveNode->next = match->next ; Ysafe_free( match ) ; /* update loop */ match = saveNode->next ; } else if( match->node == sameNode){ /* a node constrainted to itself delete it. */ D( "mc_compact/cleanupGraph", sprintf( YmsgG, "We discovered redundant edge-N%d -> N%d\n", sameNode, match->node ) ; M(MSG, NULL, YmsgG ) ) ; /* need to update ancestors */ /* the edge in question is sameNode:match->node */ switch( direction ){ case XFORWARD: tileNodeG[sameNode]->xancestrF-- ; break ; case XBACKWARD: tileNodeG[sameNode]->xancestrB-- ; break ; case YFORWARD: tileNodeG[sameNode]->yancestrF-- ; break ; case YBACKWARD: tileNodeG[sameNode]->yancestrB-- ; break ; } /* now delete */ saveNode->next = match->next ; Ysafe_free( match ) ; /* update loop */ match = saveNode->next ; } else { /* edge is OK */ /* update loop */ saveNode = match ; match = match->next ; } } } } /* end for loop */ } /* find bounding box of tiles */ find_core( l, r, b, t ) INT *l, *r, *b, *t ; { INT i ; INT expand ; COMPACTPTR tile ; blocklG = INT_MAX ; blockbG = INT_MAX ; blockrG = INT_MIN ; blocktG = INT_MIN ; for( i=1; i <= numtilesG; i++ ){ tile = tileNodeG[i] ; blocklG = MIN( blocklG, tile->l ) ; blockbG = MIN( blockbG, tile->b ) ; blockrG = MAX( blockrG, tile->r ) ; blocktG = MAX( blocktG, tile->t ) ; } expand = (INT) ( 0.25 * (DOUBLE) ABS(blockrG - blocklG) ) ; *l = blocklG -= expand ; *r = blockrG += expand ; expand = (INT) ( 0.25 * (DOUBLE) ABS(blocktG - blockbG) ) ; *b = blockbG -= expand ; *t = blocktG += expand ; } /* end find_core */ graywolf-0.1.4+20170307gite1bf319/src/mc_compact/date.h000066400000000000000000000001071305746555600217440ustar00rootroot00000000000000#define DATE "@(#) Yale compilation date:Mon May 25 21:07:13 EDT 1992" graywolf-0.1.4+20170307gite1bf319/src/mc_compact/debug2.c000066400000000000000000000351371305746555600222050ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: debug2.c DESCRIPTION:more debug routines CONTENTS: DATE: Feb 13, 1988 REVISIONS: Jan 29, 1989 - changed msg to msgG and added \n's. Mar 30, 1989 - changed data structure of tiles. Apr 17, 1989 - moved from placer into indep. program. Apr 20, 1989 - now write debug to a file. Sun Nov 4 13:22:21 EST 1990 - added new debug function for displaying cell slacks. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) debug2.c version 7.1 11/10/90" ; #endif #include #include #include dumpxGraph() { int i ; ECOMPBOXPTR eptr ; FILE *fp ; int xmin, xmax ; /****************** XGRAPH *******************************/ fp = TWOPEN( "debug", "w", ABORT ) ; for( i=0;i<=last_tileG;i++){ fprintf( fp,"Node:%2d cell:%2d l:%5d r:%5d b:%5d t:%5d\n", tileNodeG[i]->node, tileNodeG[i]->cell, tileNodeG[i]->l, tileNodeG[i]->r, tileNodeG[i]->b, tileNodeG[i]->t ) ; fprintf( fp," xvMin:%d xvMax:%d yvMin:%d yvMax:%5d pathx:%d pathy:%d\n", tileNodeG[i]->xvalueMin, tileNodeG[i]->xvalueMax, tileNodeG[i]->yvalueMin, tileNodeG[i]->yvalueMax, tileNodeG[i]->pathx, tileNodeG[i]->pathy ) ; /* find window */ /* xmin is max of all left edges */ xmin = tileNodeG[i]->xvalueMin ; for( eptr = tileNodeG[i]->xadjB ;eptr; eptr=eptr->next){ xmin = MAX( xmin, tileNodeG[eptr->node]->xvalueMax ) ; } xmax = tileNodeG[i]->xvalueMax ; for( eptr = tileNodeG[i]->xadjF ;eptr; eptr=eptr->next){ xmax = MIN( xmax, tileNodeG[eptr->node]->xvalueMin ) ; } fprintf( fp,"xmin:%d xmax:%d\n",xmin, xmax ) ; fprintf( fp," xancF:%d xancB:%d yancF:%d yancB:%d\n", tileNodeG[i]->xancestrF, tileNodeG[i]->xancestrB, tileNodeG[i]->yancestrF, tileNodeG[i]->yancestrB ) ; fprintf( fp," Edges for node %d:\n", i ); for( eptr = tileNodeG[i]->xadjB ;eptr; eptr=eptr->next){ fprintf( fp," node %2d constraint:%d\n", eptr->node, eptr->constraint ) ; } fprintf( fp, "\n" ) ; } TWCLOSE( fp ) ; } BOOL dxancestors( numtiles, xGraph ) int numtiles ; COMPACTPTR *xGraph ; { int i, fcount = 0, bcount = 0 ; int fanc = 0 , banc = 0 ; int fnode = 0 , bnode = 0 ; ECOMPBOXPTR edge ; for( i=0;i<=numtiles; i++ ){ fanc += xGraph[i]->xancestrF ; fnode = 0 ; for( edge=xGraph[i]->xadjF;edge;edge=edge->next ){ fcount++ ; fnode++ ; } } for( i=0;i<=numtiles; i++ ){ banc += xGraph[i]->xancestrB ; bnode = 0 ; for( edge=xGraph[i]->xadjB;edge;edge=edge->next ){ bcount++ ; bnode++ ; } } if( fcount != bcount || fcount != fanc || bcount != banc ){ printf( "Forward edges:%d Backward edges:%d\n",fcount,bcount ) ; printf( "Forward nodes:%d Backward nodes:%d\n",fnode,bnode ) ; printf( "Forward ancestrs:%d Backward ancestrs:%d\n",fanc,banc ); return(FALSE) ; } return(TRUE) ; } dumpyGraph() { int i ; ECOMPBOXPTR eptr ; FILE *fp ; fp = TWOPEN( "debug", "w", ABORT ) ; /****************** YGRAPH *******************************/ /* SOURCE */ fprintf(fp,"Node:%2d cell:%2d l:%5d r:%5d b:%5d t:%5d\n", tileNodeG[numtilesG+2]->node, tileNodeG[numtilesG+2]->cell, tileNodeG[numtilesG+2]->l, tileNodeG[numtilesG+2]->r, tileNodeG[numtilesG+2]->b, tileNodeG[numtilesG+2]->t ) ; fprintf(fp," xvMin:%d xvMax:%d yvMin:%d yvMax:%5d pathx:%d pathy:%d\n", tileNodeG[numtilesG+2]->xvalueMin, tileNodeG[numtilesG+2]->xvalueMax, tileNodeG[numtilesG+2]->yvalueMin, tileNodeG[numtilesG+2]->yvalueMax, tileNodeG[numtilesG+2]->pathx, tileNodeG[numtilesG+2]->pathy ) ; fprintf(fp," Edges for node %d:\n", numtilesG+2 ); for( eptr = tileNodeG[numtilesG+2]->yadjB ;eptr; eptr=eptr->next){ fprintf(fp," node %2d constraint:%d\n", eptr->node, eptr->constraint ) ; } for( i=1;i<=numtilesG;i++){ fprintf(fp,"Node:%2d cell:%2d l:%5d r:%5d b:%5d t:%5d\n", tileNodeG[i]->node, tileNodeG[i]->cell, tileNodeG[i]->l, tileNodeG[i]->r, tileNodeG[i]->b, tileNodeG[i]->t ) ; fprintf(fp," xvMin:%d xvMax:%d yvMin:%d yvMax:%5d pathx:%d pathy:%d\n", tileNodeG[i]->xvalueMin, tileNodeG[i]->xvalueMax, tileNodeG[i]->yvalueMin, tileNodeG[i]->yvalueMax, tileNodeG[i]->pathx, tileNodeG[i]->pathy ) ; fprintf(fp," Edges for node %d:\n", i ); for( eptr = tileNodeG[i]->yadjB ;eptr; eptr=eptr->next){ fprintf(fp," node %2d constraint:%d\n", eptr->node, eptr->constraint ) ; } } /* SINK */ fprintf(fp,"Node:%2d cell:%2d l:%5d r:%5d b:%5d t:%5d\n", tileNodeG[numtilesG+3]->node, tileNodeG[numtilesG+3]->cell, tileNodeG[numtilesG+3]->l, tileNodeG[numtilesG+3]->r, tileNodeG[numtilesG+3]->b, tileNodeG[numtilesG+3]->t ) ; fprintf(fp," xvMin:%d xvMax:%d yvMin:%d yvMax:%5d pathx:%d pathy:%d\n", tileNodeG[numtilesG+3]->xvalueMin, tileNodeG[numtilesG+3]->xvalueMax, tileNodeG[numtilesG+3]->yvalueMin, tileNodeG[numtilesG+3]->yvalueMax, tileNodeG[numtilesG+3]->pathx, tileNodeG[numtilesG+3]->pathy ) ; fprintf(fp," Edges for node %d:\n", i ); for( eptr = tileNodeG[numtilesG+3]->yadjB ;eptr; eptr=eptr->next){ fprintf(fp," node %2d constraint:%d\n", eptr->node, eptr->constraint ) ; } fprintf( fp, "\n" ) ; TWCLOSE( fp ) ; } ECOMPBOXPTR find_edge( node1, node2, direction ) int node1, node2 ; int direction ; { ECOMPBOXPTR eptr ; switch( direction ){ case XFORWARD: eptr = tileNodeG[node1]->xadjF; break ; case XBACKWARD: eptr = tileNodeG[node1]->xadjB; break ; case YFORWARD: eptr = tileNodeG[node1]->yadjF; break ; case YBACKWARD: eptr = tileNodeG[node1]->yadjB; break ; } for( ; eptr; eptr = eptr->next ){ if( eptr->node == node2 ){ return( eptr ) ; } } return( NULL ) ; } dycons() { int i, bcons ; ECOMPBOXPTR eptr, eptr2 ; /****************** YGRAPH *******************************/ /* SOURCE */ printf(" Edges for node %d:\n", numtilesG+2 ); for( eptr = tileNodeG[numtilesG+2]->yadjF ;eptr; eptr=eptr->next){ if( eptr2 = find_edge( eptr->node, numtilesG+2, YBACKWARD ) ){ bcons = eptr2->constraint ; } else { bcons = -1 ; } printf(" node %2d fconstraint:%d bconstraint:%d\n", eptr->node, eptr->constraint, bcons ) ; } for( i=1;i<=numtilesG;i++){ printf(" Edges for node %d:\n", i ); for( eptr = tileNodeG[i]->yadjF ;eptr; eptr=eptr->next){ if( eptr2 = find_edge( eptr->node, i, YBACKWARD ) ){ bcons = eptr2->constraint ; } else { bcons = -1 ; } printf(" node %2d fconstraint:%d bconstraint:%d\n", eptr->node, eptr->constraint, bcons ) ; } } /* SINK */ printf(" Edges for node %d:\n", i ); for( eptr = tileNodeG[numtilesG+3]->yadjF ;eptr; eptr=eptr->next){ if( eptr2 = find_edge( eptr->node, numtilesG+3, YBACKWARD ) ){ bcons = eptr2->constraint ; } else { bcons = -1 ; } printf(" node %2d fconstraint:%d bconstraint:%d\n", eptr->node, eptr->constraint, bcons ) ; } } dsort( numtiles, XNotY ) int numtiles ; BOOL XNotY ; { int i ; COMPACTPTR *ptr ; fprintf(stderr,"Dumping tileNodeG - node:cell...\n") ; ptr = tileNodeG ; for( i=1;i<=numtiles;i++ ){ fprintf(stderr, "%d:%d ", ptr[i]->node,ptr[i]->cell ) ; if( ( i % 10 ) == 0 ){ fprintf( stderr, "\n") ; } } fprintf(stderr,"\n") ; if( XNotY ){ fprintf(stderr,"\nDumping xGraph...\n") ; ptr = xGraphG ; } else { fprintf(stderr,"\nDumping yGraph...\n") ; ptr = yGraphG ; } for( i=0;i<=last_tileG;i++ ){ fprintf(stderr, "%d:%d ", ptr[i]->node,ptr[i]->cell ) ; if( i != 0 && ( i % 10 ) == 0 ){ fprintf( stderr, "\n") ; } } fprintf(stderr,"\n") ; } /* end numtiles */ dxancerr() { int i ; for( i=0;i<=last_tileG; i++ ){ if( xGraphG[i]->xancestrF != 0 ){ fprintf( stderr, "Tile:%d has %d forward ancestors\n", xGraphG[i]->node, xGraphG[i]->xancestrF ) ; } } for( i=0;i<=last_tileG; i++ ){ if( xGraphG[i]->xancestrB != 0 ){ fprintf( stderr, "Tile:%d has %d backward ancestors\n", xGraphG[i]->node, xGraphG[i]->xancestrB ) ; } } } dump_anc() { INT i ; INT last ; last = YSINK ; fprintf( stderr, "The ancestors for the tiles:\n" ) ; for( i = 0; i <= last; i++ ){ fprintf( stderr, "\ttile:%3d ancestors:%d\n", i, ancestorG[i] ) ; } } /* dump_anc */ dslack( XNotY, center, length ) BOOL XNotY ; BOOL center ; INT length ; { INT i ; INT count ; INT value ; NODEPTR nptr ; CELLBOXPTR cptr ; COMPACTPTR tptr ; if( XNotY ){ fprintf(stderr,"\nDumping xGraph slacks node:minslack-maxslack...\n") ; for( i=1;i<=numcellsG;i++ ){ cptr = slackG[i] ; fprintf(stderr, "%d:", tileNodeG[cptr->tiles->node]->cell ) ; fprintf(stderr, "%d-%d\n", cptr->xmin, cptr->xmax ) ; count = 0 ; for( nptr = cptr->tiles; nptr; nptr = nptr->next ){ tptr = tileNodeG[nptr->node] ; value = tptr->xvalueMin ; if( center ){ value -= tptr->l_rel ; } fprintf(stderr, "\t%d:%d-", tptr->node, value ) ; value = tptr->xvalueMax ; if( center ){ value -= tptr->l_rel ; } if( length ){ value = length - value ; } fprintf(stderr, "%d ", value ) ; if( (++count % 4) == 0 ){ fprintf( stderr, "\n") ; } } fprintf( stderr, "\n") ; } fprintf(stderr,"\n\n") ; } else { fprintf(stderr,"\nDumping yGraph slacks node:minslack-maxslack...\n") ; for( i=1;i<=numcellsG;i++ ){ cptr = slackG[i] ; fprintf(stderr, "%d:", tileNodeG[cptr->tiles->node]->cell ) ; fprintf(stderr, "%d-%d\n", cptr->ymin, cptr->ymax ) ; count = 0 ; for( nptr = cptr->tiles; nptr; nptr = nptr->next ){ tptr = tileNodeG[nptr->node] ; value = tptr->yvalueMin ; if( center ){ value -= tptr->b_rel ; } fprintf(stderr, "\t%d:%d-", tptr->node, value ) ; value = tptr->yvalueMax ; if( center ){ value -= tptr->b_rel ; } if( length ){ value = length - value ; } fprintf(stderr, "%d ", value ) ; if( (++count % 4) == 0 ){ fprintf( stderr, "\n") ; } } fprintf( stderr, "\n") ; } fprintf(stderr,"\n\n") ; } } /* end dslack */ dedges( cell, XnotY, forwardNotBack ) INT cell ; BOOL XnotY ; BOOL forwardNotBack ; { NODEPTR nptr ; CELLBOXPTR cptr ; COMPACTPTR tptr ; ECOMPBOXPTR eptr ; if( XnotY ){ if( forwardNotBack ){ fprintf( stderr, "X forward " ) ; } else { fprintf( stderr, "X backward " ) ; } } else { if( forwardNotBack ){ fprintf( stderr, "Y forward " ) ; } else { fprintf( stderr, "Y backward " ) ; } } fprintf( stderr, "edges for cell:%d :\n", cell ) ; for( nptr = cellarrayG[cell]->tiles; nptr ; nptr = nptr->next ){ tptr = tileNodeG[nptr->node] ; if( XnotY ){ if( forwardNotBack ){ eptr = tptr->xadjF; } else { eptr = tptr->xadjB; } } else { if( forwardNotBack ){ eptr = tptr->yadjF; } else { eptr = tptr->yadjB; } } for( ; eptr; eptr = eptr->next ){ fprintf( stderr, "\t %d --> %d \n", nptr->node, eptr->node ) ; } } fprintf( stderr, "\n\n" ) ; } dyancerr() { int i ; for( i=0;i<=last_tileG; i++ ){ if( yGraphG[i]->yancestrF != 0 ){ fprintf( stderr, "Tile:%d has %d forward ancestors\n", yGraphG[i]->node, yGraphG[i]->yancestrF ) ; } } for( i=0;i<=last_tileG; i++ ){ if( yGraphG[i]->yancestrB != 0 ){ fprintf( stderr, "Tile:%d has %d backward ancestors\n", yGraphG[i]->node, yGraphG[i]->yancestrB ) ; } } } check_xancestors() { INT i ; INT count ; COMPACTPTR tptr ; ECOMPBOXPTR eptr ; for( i=0;i<=last_tileG; i++ ){ count = 0 ; tptr = xGraphG[i] ; /* first check forward ancestors */ for( eptr = tptr->xadjB ;eptr; eptr=eptr->next){ count++ ; } if( tptr->xancestrF != count ){ fprintf( stderr, "ERROR:Mismatch in forward x ancestor count for node:%d\n", tptr->node ) ; fprintf( stderr, "\tdata:%d found:%d\n\n", tptr->xancestrF, count ) ; } /* next check backward ancestors */ count = 0 ; for( eptr = tptr->xadjF ;eptr; eptr=eptr->next){ count++ ; } if( tptr->xancestrB != count ){ fprintf( stderr, "ERROR:Mismatch in backward x ancestor count for node:%d\n", tptr->node ) ; fprintf( stderr, "\tdata:%d found:%d\n\n", tptr->xancestrB, count ) ; } } } /* end check_xancestors */ check_yancestors() { INT i ; INT count ; COMPACTPTR tptr ; ECOMPBOXPTR eptr ; for( i=0;i<=last_tileG; i++ ){ count = 0 ; tptr = yGraphG[i] ; /* first check forward ancestors */ for( eptr = tptr->yadjB ;eptr; eptr=eptr->next){ count++ ; } if( tptr->yancestrF != count ){ fprintf( stderr, "ERROR:Mismatch in forward y ancestor count for node:%d\n", tptr->node ) ; fprintf( stderr, "\tdata:%d found:%d\n\n", tptr->yancestrF, count ) ; } /* next check backward ancestors */ count = 0 ; for( eptr = tptr->yadjF ;eptr; eptr=eptr->next){ count++ ; } if( tptr->yancestrB != count ){ fprintf( stderr, "ERROR:Mismatch in backward y ancestor count for node:%d\n", tptr->node ) ; fprintf( stderr, "\tdata:%d found:%d\n\n", tptr->yancestrB, count ) ; } } } /* end check_yancestors */ graywolf-0.1.4+20170307gite1bf319/src/mc_compact/grid.c000066400000000000000000000101101305746555600217420ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: grid.c DESCRIPTION:grid the data to user specified grid. CONTENTS: grid_data( ) DATE: Apr 18, 1989 - origin prboard.c REVISIONS: Apr 30, 1989 - removed unnecessary variables. Mon May 6 22:33:51 EDT 1991 - no longer grid cells. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) grid.c version 7.2 5/6/91" ; #endif #include #include grid_data() { int xcenter , ycenter, remainder ; int cell, i ; int old_left, old_bottom ;/* orig xy center of cell before gridding */ int delta_x, delta_y ; /* delta to move cell lower left to grid */ int left, bottom ; /* sides of cell bounding box */ CELLBOXPTR cellptr ; COMPACTPTR t ; #ifdef LATER for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = cellarrayG[ cell ] ; /* get global coordinates */ old_left = left = cellptr->xoffset + cellptr->xcenter ; old_bottom = bottom = cellptr->yoffset + cellptr->ycenter ; /********* grid cell data *************/ /* set lower left corner to grid */ if( xgridG ){ /* only do if non zero */ /* do individual tests only one may be zero */ if( remainder = left % xgridG ){ /* fix x direction */ left += xgridG - remainder ; } } if( ygridG ){ /* only do if non zero */ if( remainder = bottom % ygridG ){ /* fix y direction */ bottom += ygridG - remainder ; } } /* now modify center of cell coordinates */ delta_x = left - old_left ; if( delta_x ){ fprintf( stderr, "Gridding cell %d in x direction...\n", cell ) ; } if( delta_y ){ fprintf( stderr, "Gridding cell %d in y direction...\n", cell ) ; } delta_y = bottom - old_bottom ; xcenter = cellptr->xcenter += delta_x ; ycenter = cellptr->ycenter += delta_y ; /* now modify bounding box of cell */ cellptr->l = cellptr->l_rel + xcenter ; cellptr->r = cellptr->r_rel + xcenter ; cellptr->b = cellptr->b_rel + ycenter ; cellptr->t = cellptr->t_rel + ycenter ; /******** end cell gridding ****** */ } /* end for loop */ /* now update all the tiles */ for( i = 1; i <= numtilesG; i++ ){ t = tileNodeG[i] ; cell = t->cell ; ASSERTNCONT( cell > 0 && cell <= numcellsG,"grid_data", "cell out of bounds" ) ; cellptr = cellarrayG[cell] ; xcenter = cellptr->xcenter ; ycenter = cellptr->ycenter ; t->l = t->l_rel + xcenter ; t->r = t->r_rel + xcenter ; t->b = t->b_rel + ycenter ; t->t = t->t_rel + ycenter ; } /* end update of tiles */ #endif } /* end grid_cells */ graywolf-0.1.4+20170307gite1bf319/src/mc_compact/io.c000066400000000000000000000442411305746555600214400ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: io.c DESCRIPTION:This file contains routines for handling I/O. The compactor writes and reads the same format. CONTENTS: DATE: Apr 17, 1989 REVISIONS: Apr 30, 1989 - added direction field for partitioning. Sun Nov 4 13:19:23 EST 1990 - rewrote for handling multiple tiles correctly. We now look at cell slack instead of tile slack. Mon May 6 22:34:31 EDT 1991 - added gridding reference. Fri Nov 8 18:16:21 EST 1991 - removed INT_SMALL and INT_LARGE definitions since gcc couldn't handle it. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) io.c version 7.5 5/21/92" ; #endif #include #include #include static INT boxLS, boxRS, boxTS, boxBS ; /* bounding box of tiles */ static INT celLS, celRS, celTS, celBS ; /* bounding box of cur cell */ static INT curCellS = 0 ; /* current cell */ static INT curTileS = 0 ; /* current tile */ static INT xcS, ycS ; /* current cell center */ static INT int_largeS, int_smallS ; /* used because of compiler bugs */ static BOOL errorFlagS = FALSE ; /* records fault condition */ static BOOL curCellTypeS ; /* hard or soft type */ static BOOL multiS ; /* cell has multiple tiles ??? */ static CELLBOXPTR ptrS ; /* pointer to current cell */ /* ***************** ERROR HANDLING ****************************** */ /* ERRORABORT is a macro which forces routines not to do any work */ /* when we find a syntax error in the input routine. */ #define ERRORABORT() \ { \ if( errorFlagS ){ \ return ; /* don't do any work for errors */ \ } \ } \ setErrorFlag() { errorFlagS = TRUE ; } /* ***************** ERROR HANDLING ****************************** */ init( numtiles, numcells ) INT numtiles, numcells ; { INT i ; /* save number of tiles in global for future use */ numtilesG = numtiles ; numcellsG = numcells ; last_tileG = numtilesG + 1 ; last_cellG = numcellsG + 3 ; /* initialize bounding box of tiles-need bounding box for source */ /* and sink positions */ boxLS = INT_MAX ; boxBS = INT_MAX ; boxRS = INT_MIN ; boxTS = INT_MIN ; /* allocate space for graph */ tileNodeG = (COMPACTPTR *) Ysafe_malloc( (numtilesG+1) * sizeof(COMPACTPTR) ); for( i = 1 ; i <= numtilesG ; i++ ){ tileNodeG[i] = (COMPACTPTR) Ysafe_malloc( sizeof(COMPACTBOX) ); } /* -------------------------------------------------------------- Now allocate space for xcenter and ycenter arrays which keep track of the cells center. Now make cells for source sink for x and y graphs. */ cellarrayG = (CELLBOXPTR *) Ysafe_malloc( (last_cellG+1)*sizeof(CELLBOXPTR) ) ; slackG = (CELLBOXPTR *) Ysafe_malloc( (numcellsG+1)*sizeof(CELLBOXPTR) ) ; for( i = 0; i <= numcellsG; i++ ){ slackG[i] = cellarrayG[i] = (CELLBOXPTR) Ysafe_calloc( 1, sizeof(CELLBOX)) ; } /* allocate room for the source and sink */ for( numcellsG+1; i <= last_cellG; i++ ){ cellarrayG[i] = (CELLBOXPTR) Ysafe_calloc( 1, sizeof(CELLBOX)) ; } } /* end init */ final_tiles() { INT i ; /* counter */ INT space ; /* counter */ INT count ; /* counter */ INT minx, maxx ; /* min and max x nodes of cell */ INT miny, maxy ; /* min and max y nodes of cell */ BOOL multi ; /* is tile one of multitile cell */ NODEPTR aptr ; /* current node */ COMPACTPTR tptr ; /* current tile */ COMPACTPTR *newArray ; /* temporarily build a new tile array */ CELLBOXPTR cptr ; /* current cell */ /* first count the number of tiles */ count = 0 ; for( i=1;i<=numcellsG;i++ ){ for( aptr = cellarrayG[i]->tiles;aptr; aptr = aptr->next ){ count++ ; } } numtilesG = count ; /* initialize the last tile convenience variable */ last_tileG = numtilesG + 1 ; /* otherwise begin realloc */ /* -------------------------------------------------------------- space requirements also include 2 sources and 2 sinks: xSource = 0, xsink = numtiles + 1, ysource = numtiles + 2, and ysink = numtiles + 3 positions in the tileNodeS array. */ space = numtilesG + 4 ; /* allocate space for tileNode array */ newArray = (COMPACTPTR *) Ysafe_malloc( space * sizeof(COMPACTPTR) ); ancestorG = (INT *) Ysafe_malloc( space * sizeof(INT) ) ; count = 0 ; for( i=1;i<=numcellsG;i++ ){ for( aptr = cellarrayG[i]->tiles;aptr; aptr = aptr->next ){ tptr = tileNodeG[aptr->node] ; ASSERTNCONT( tptr, "final_tiles", "tptr NULL\n" ) ; newArray[++count] = tptr ; aptr->node = count ; tptr->node = count ; } } /* now free the old tileNode array */ Ysafe_free( tileNodeG ) ; tileNodeG = newArray ; /* initialize the tile set */ tileSetG = Yset_init( 0, numtilesG+3 ) ; /* NOW create x and y graphs ie. clone them */ space = numtilesG + 2 ; xGraphG = (COMPACTPTR *) Ysafe_malloc( space * sizeof(COMPACTPTR) ) ; yGraphG = (COMPACTPTR *) Ysafe_malloc( space * sizeof(COMPACTPTR) ) ; for( i = 1; i< space; i++ ){ xGraphG[i] = tileNodeG[i] ; yGraphG[i] = tileNodeG[i] ; } /* now set the multi fields to be correct */ for( i=1;i<=numcellsG;i++ ){ count = 0 ; multi = FALSE ; cptr = cellarrayG[i] ; for( aptr = cptr->tiles;aptr; aptr = aptr->next ){ ASSERTNCONT( aptr->node > 0 && aptr->node <= numtilesG, "preprocess_multi", "tile out of bounds\n" ) ; if( ++count >= 2 ){ multi = TRUE ; break ; } } /* end loop on tiles */ cptr->multi = multi ; /* set the multi field and also the low and hi nodes for the tiles */ minx = INT_MAX ; miny = INT_MAX ; maxx = INT_MIN ; maxy = INT_MIN ; for( aptr = cptr->tiles;aptr; aptr = aptr->next ){ ASSERTNCONT( aptr->node > 0 && aptr->node <= numtilesG, "preprocess_multi", "tile out of bounds\n" ) ; tptr = tileNodeG[aptr->node] ; tptr->multi = multi ; /* now check on the lowest tiles */ if( tptr->l_rel < minx || (tptr->l_rel == minx && aptr->node < cptr->xlo) ){ minx = tptr->l_rel ; cptr->xlo = aptr->node ; } if( tptr->b_rel < miny || (tptr->b_rel == miny && aptr->node < cptr->ylo) ){ miny = tptr->b_rel ; cptr->ylo = aptr->node ; } if( tptr->l_rel > maxx || (tptr->l_rel == maxx && aptr->node > cptr->xhi) ){ maxx = tptr->l_rel ; cptr->xhi = aptr->node ; } if( tptr->b_rel > maxy || (tptr->b_rel == maxy && aptr->node > cptr->yhi) ){ maxy = tptr->b_rel ; cptr->yhi = aptr->node ; } } /* end loop on tiles */ } /* add node box to the sources and sinks */ /* XSOURCE */ aptr = cellarrayG[XSOURCEC]->tiles=(NODEPTR) Ysafe_malloc( sizeof(NODEBOX)) ; aptr->next = NIL(NODEBOX *) ; aptr->node = XSOURCE ; /* XSINK */ aptr = cellarrayG[XSINKC]->tiles = (NODEPTR) Ysafe_malloc( sizeof(NODEBOX) ) ; aptr->next = NIL(NODEBOX *) ; aptr->node = XSINK ; /* YSOURCE */ aptr = cellarrayG[YSOURCEC]->tiles= (NODEPTR) Ysafe_malloc( sizeof(NODEBOX)) ; aptr->next = NIL(NODEBOX *) ; aptr->node = YSOURCE ; /* YSINK */ aptr = cellarrayG[YSINKC]->tiles = (NODEPTR) Ysafe_malloc( sizeof(NODEBOX) ) ; aptr->next = NIL(NODEBOX *) ; aptr->node = YSINK ; } /* end final_tiles */ /* set the current cell */ initCell( celltype, cellnum, x, y, xoffset, yoffset ) INT celltype ; INT cellnum ; INT x, y ; INT xoffset, yoffset ; { ERRORABORT() ; if( ++curCellS > numcellsG ){ setErrorFlag() ; M(ERRMSG, "initCell", "Problem with cell number\n" ) ; return ; } ptrS = cellarrayG[curCellS] ; ptrS->type = curCellTypeS = celltype ; ptrS->cellnum = cellnum ; ptrS->xoffset = xoffset ; ptrS->yoffset = yoffset ; /* save center of cell in center arrays */ xcS = ptrS->xcenter = x ; ycS = ptrS->ycenter = y ; /* initialize tile list */ ptrS->tiles = NULL ; celLS = INT_MAX ; celBS = INT_MAX ; celRS = INT_MIN ; celTS = INT_MIN ; /* set multi tile counter to zero */ multiS = 0 ; } /* end initCell */ init_extra_tile( cell, type ) INT cell ; { curTileS = numtilesG ; numtilesG++ ; last_tileG = numtilesG + 1 ; tileNodeG = (COMPACTPTR *) Ysafe_realloc( tileNodeG, (numtilesG+1) * sizeof(COMPACTPTR) ); tileNodeG[numtilesG] = (COMPACTPTR) Ysafe_malloc( sizeof(COMPACTBOX) ); curCellS = cell ; ptrS = cellarrayG[curCellS] ; xcS = ptrS->xcenter ; ycS = ptrS->ycenter ; curCellTypeS = type ; } /* init_extra_tile */ /* initialize tile */ INT addtile( l, r, b, t ) INT l, r, b, t ; { COMPACTPTR tptr ; NODEPTR temp, nptr ; ERRORABORT() ; if( ++curTileS > numtilesG ){ setErrorFlag() ; M(ERRMSG, "addtile", "Problem with number of tiles\n" ) ; return ; } tptr = tileNodeG[curTileS] ; /* save relative positions */ tptr->l_rel = tptr->l = l ; tptr->r_rel = tptr->r = r ; tptr->b_rel = tptr->b = b ; tptr->t_rel = tptr->t = t ; tptr->xspan = r - l ; tptr->yspan = t - b ; /* find the cells bounding box */ celLS = MIN( l, celLS ) ; celBS = MIN( b, celBS ) ; celRS = MAX( r, celRS ) ; celTS = MAX( t, celTS ) ; /* now set global positions */ tptr->l += xcS ; tptr->r += xcS ; tptr->b += ycS ; tptr->t += ycS ; /* save bounding box of all tiles */ boxLS = MIN( tptr->l, boxLS ) ; boxBS = MIN( tptr->b, boxBS ) ; boxRS = MAX( tptr->r, boxRS ) ; boxTS = MAX( tptr->t, boxTS ) ; /* save the data */ tptr->node = curTileS ; tptr->cell = curCellS ; tptr->type = curCellTypeS ; tptr->multi = FALSE ; tptr->moved = FALSE ; tptr->xadjF = NULL ; tptr->xadjB = NULL ; tptr->yadjF = NULL ; tptr->yadjB = NULL ; tptr->direction = NODIRECTION ; /* now add tile to the list of tiles */ if( temp = ptrS->tiles ){ nptr = ptrS->tiles = (NODEPTR) Ysafe_malloc( sizeof(NODEBOX) ) ; nptr->next = temp ; } else { /* initialize list */ nptr = ptrS->tiles = (NODEPTR) Ysafe_malloc( sizeof(NODEBOX) ) ; nptr->next = NULL ; } /* now fill in the data */ nptr->node = curTileS ; /* now update multi tile counter */ multiS++ ; return( curTileS ) ; } /* end addtile */ endCell() { ERRORABORT() ; /* update the bounding box of the cell */ /* bounding box is used to force cell to grid */ ptrS->l_rel = celLS ; ptrS->r_rel = celRS ; ptrS->b_rel = celBS ; ptrS->t_rel = celTS ; ptrS->l = celLS + xcS ; ptrS->r = celRS + xcS ; ptrS->b = celBS + ycS ; ptrS->t = celTS + ycS ; /* note whether cell is multiple tile or not */ if( multiS > 1 ){ ptrS->multi = TRUE ; } else { ptrS->multi = FALSE ; } } /* end endCell */ process_tiles() { INT i ; COMPACTPTR t ; CELLBOXPTR cptr ; if( errorFlagS ){ YexitPgm( COMPACTFAIL ) ; } /* insure that box coordinates are not zero */ /* this insures that source and sink are outside core */ /* see addSourceNSink below for details */ if( boxLS == 0) boxLS-- ; if( boxRS == 0) boxRS++ ; if( boxBS == 0) boxBS-- ; if( boxTS == 0) boxTS++ ; /* update members of tileNode array to multi tile status */ for( i = 1; i <= numtilesG; i++ ){ t = tileNodeG[i] ; ASSERT( t->cell > 0 && t->cell <= numcellsG, "process_tiles", "cell out of bounds" ) ; cptr = cellarrayG[t->cell] ; if( cptr->multi ){ t->multi = TRUE ; } /* check for zero width tiles */ if( t->l == t->r ){ if( t->r >= cptr->xcenter ){ t->l-- ; t->l_rel-- ; } else { t->r++ ; t->r_rel++ ; } sprintf( YmsgG, "Zero width tile found for tile:%d\n", i ) ; M( MSG, "process_tiles", YmsgG ) ; } if( t->b == t->t ){ if( t->t >= cptr->ycenter ){ t->b-- ; t->b_rel-- ; } else { t->t++ ; t->t_rel++ ; } sprintf( YmsgG, "Zero width tile found for tile:%d\n", i ) ; M( MSG, "process_tiles", YmsgG ) ; } } multi_tiles() ; addSourceNSink() ; /* now xGraphS and yGraphS have all the tiles */ /* initialization complete */ } /* end process_tiles */ /* ADD source and sink nodes to both x and y graphs */ addSourceNSink() { COMPACTPTR source, sink ; INT x ; /* We do this little piece of code since a couple of stupid compilers */ /* can't do math correctly. Gcc being one of them. */ x = INT_MIN ; int_smallS = x / 2 ; x = INT_MAX ; int_largeS = x / 2 ; /*********** XGRAPH ***********/ /* add source and sink nodes for x graph */ source = xGraphG[0] = tileNodeG[0] = (COMPACTPTR) Ysafe_malloc( sizeof(COMPACTBOX) ) ; /* add 10% to make graph picture prettier */ source->l = boxLS - 0.5 * (DOUBLE) ABS(boxRS - boxLS) ; source->r = boxLS - 0.5 * (DOUBLE) ABS(boxRS - boxLS) ; source->b = int_smallS ; source->t = int_largeS ; source->l_rel = 0 ; source->r_rel = 0 ; source->b_rel = boxBS ; source->t_rel = boxTS ; source->node = 0 ; source->cell = XSOURCEC ; source->multi = FALSE ; source->type = CELLTYPE ; source->xadjF = NULL ; source->xadjB = NULL ; source->yadjF = NULL ; source->yadjB = NULL ; source->direction = NODIRECTION ; sink = xGraphG[last_tileG] = tileNodeG[last_tileG] = (COMPACTPTR) Ysafe_malloc( sizeof(COMPACTBOX) ) ; /* add 10% to make graph picture prettier */ sink->l = boxRS + 0.5 * (DOUBLE) ABS(boxRS - boxLS) ; sink->r = boxRS + 0.5 * (DOUBLE) ABS(boxRS - boxLS) ; sink->b = int_smallS ; sink->t = int_largeS ; sink->l_rel = 0 ; sink->r_rel = 0 ; sink->b_rel = boxBS ; sink->t_rel = boxTS ; sink->node = last_tileG ; sink->cell = XSINKC ; sink->multi = FALSE ; sink->type = CELLTYPE ; sink->xadjF = NULL ; sink->xadjB = NULL ; sink->yadjF = NULL ; sink->yadjB = NULL ; sink->direction = NODIRECTION ; /*********** YGRAPH ***********/ /* add source and sink nodes for y graph */ source = yGraphG[0] = tileNodeG[numtilesG+2] = (COMPACTPTR) Ysafe_malloc( sizeof(COMPACTBOX) ) ; /* add 10% to make graph picture prettier */ source->b = boxBS - 0.5 * (DOUBLE) ABS(boxTS - boxBS) ; source->t = boxBS - 0.5 * (DOUBLE) ABS(boxTS - boxBS) ; source->l = int_smallS ; source->r = int_largeS ; source->b_rel = 0 ; source->t_rel = 0 ; source->l_rel = boxLS ; source->r_rel = boxRS ; source->node = numtilesG + 2 ; source->cell = YSOURCEC ; source->multi = FALSE ; source->type = CELLTYPE ; source->xadjF = NULL ; source->xadjB = NULL ; source->yadjF = NULL ; source->yadjB = NULL ; source->direction = NODIRECTION ; sink = yGraphG[last_tileG] = tileNodeG[numtilesG+3] = (COMPACTPTR) Ysafe_malloc( sizeof(COMPACTBOX) ) ; /* add 10% to make graph picture prettier */ sink->b = boxTS + 0.5 * (DOUBLE) ABS(boxTS - boxBS) ; sink->t = boxTS + 0.5 * (DOUBLE) ABS(boxTS - boxBS) ; sink->l = int_smallS ; sink->r = int_largeS ; sink->b_rel = 0 ; sink->t_rel = 0 ; sink->l_rel = boxLS ; sink->r_rel = boxRS ; sink->node = numtilesG + 3 ; sink->cell = YSINKC ; sink->multi = FALSE ; sink->type = CELLTYPE ; sink->xadjF = NULL ; sink->xadjB = NULL ; sink->yadjF = NULL ; sink->yadjB = NULL ; sink->direction = NODIRECTION ; } /* addSourceNSink() */ /* ***************************************************************** OUTPUT routine - output the results. **************************************************************** */ output() { INT c ; INT tile ; INT old_cell ; FILE *fp ; COMPACTPTR t ; CELLBOXPTR cptr ; char filename[LRECL] ; sprintf( filename, "%s.mcpt", cktNameG ) ; fp = TWOPEN( filename, "w", ABORT ) ; /* account for sink tile */ fprintf( fp, "numtiles:%d numcells:%d\n", numtilesG, numcellsG ) ; old_cell = 0 ; for( tile = 1; tile <= numtilesG; tile++ ){ t = tileNodeG[tile] ; c = t->cell ; if( c != old_cell ){ /* update old_cell */ cptr = cellarrayG[c] ; old_cell = c ; /* determine cell type */ if( cptr->type == STDCELLTYPE ){ /* partitioned stdcell */ /* output cell heading then tile */ fprintf( fp, "stdcell %d x:%d y:%d offset:%d %d\n", cptr->cellnum, cptr->xcenter, cptr->ycenter, cptr->xoffset, cptr->yoffset ) ; } else { /* normal mc type - hard or soft cell */ /* output cell heading then tile */ fprintf( fp, "cell %d x:%d y:%d offset:%d %d\n", cptr->cellnum, cptr->xcenter, cptr->ycenter, cptr->xoffset, cptr->yoffset ) ; } } /* just output tile */ fprintf( fp, "l:%d r:%d b:%d t:%d\n", t->l_rel, t->r_rel, t->b_rel, t->t_rel ) ; } /* end cell loop */ TWCLOSE( fp ) ; } /* end output */ graywolf-0.1.4+20170307gite1bf319/src/mc_compact/menus.h000066400000000000000000000031401305746555600221560ustar00rootroot00000000000000 /* TWmenu definitions */ #define TWNUMMENUS 26 #define AUTO_REDRAW_ON 1 #define AUTO_REDRAW_OFF 2 #define CLOSE_GRAPHICS 3 #define COLORS 4 #define CONTINUE_PROG 5 #define DUMP_GRAPHICS 6 #define FULLVIEW 7 #define REDRAW 8 #define TRANSLATE 9 #define ZOOM 10 #define CANCEL 0 #define DRAW_EDGES 11 #define IGNORE_EDGES 12 #define DRAW_EDGE_LABELS 13 #define IGNORE_EDGE_LABELS 14 #define DRAW_FORWARD 15 #define DRAW_BACKWARD 16 #define DRAW_LABELS 17 #define IGNORE_LABELS 18 #define SET__3D_CAMERA 24 #define NORMAL_VIEW 25 #define CANCEL 0 #define DUMP_STATE 19 #define HIGHLITE_CELL 20 #define TELL_POINT 21 #define DRAW_MOVED_TILES 22 #define IGNORE_MOVED_TILES 23 #define FIND_EDGE 26 #define CANCEL 0 static TWMENUBOX menuS[27] = { "CONTROL",0,0,1,0,0, "Auto Redraw On","Auto Redraw Off",1,0,1,2, "Close Graphics",0,0,0,3,0, "Colors",0,0,0,4,0, "Continue Prog.",0,0,0,5,0, "Dump Graphics",0,0,0,6,0, "FullView",0,0,0,7,0, "Redraw",0,0,0,8,0, "Translate",0,0,0,9,0, "Zoom",0,0,0,10,0, "Cancel",0,0,0,0,0, "DRAW ",0,0,1,0,0, "Draw Edges","Ignore Edges",0,0,11,12, "Draw Edge Labels","Ignore Edge Labels",0,0,13,14, "Draw Forward","Draw Backward",1,0,15,16, "Draw Labels","Ignore Labels",0,0,17,18, "Set 3D Camera",0,0,0,24,0, "Normal View",0,0,0,25,0, "Cancel",0,0,0,0,0, "DEBUG ",0,0,1,0,0, "Dump State",0,0,0,19,0, "HighLite Cell",0,0,0,20,0, "Tell Point",0,0,0,21,0, "Draw Moved Tiles","Ignore Moved Tiles",1,0,22,23, "Find Edge",0,0,0,26,0, "Cancel",0,0,0,0,0, 0,0,0,0,0,0 } ; graywolf-0.1.4+20170307gite1bf319/src/mc_compact/movestrat.c000066400000000000000000000536321305746555600230610ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: movestrat.c DESCRIPTION:This file contains move strategy for compaction algorithm. CONTENTS: DATE: Apr 11, 1988 REVISIONS: Oct 24, 1988 - fixed +1 error. Now check for graph concurrency problem and now handle special case of plus overlap correctly. Nov 6, 1988 - now keep search coordinates inside core. Apr 18, 1989 - updated for multiple tile cells. Added update_cell_tiles. Apr 25, 1989 - added debug function for position update. Jun 21, 1989 - fixed infinite loop for multiple tiles. Oct 10, 1990 - fixed typo in find_yerror. Sun Feb 17 19:35:38 EST 1991 - fixed problem in find_bound when cells completely cover each other. We now always return 0 for minslack in X and Y backward searches. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) movestrat.c version 7.2 2/17/91" ; #endif #include #include /* -------------------------------------------------------------- space requirements also include 2 sources and 2 sinks: xSource = 0, xsink = numtiles + 1, ysource = numtiles + 2, and ysink = numtiles + 3 positions in the tileNode array. */ static int find_bound(); static int findxerror(); static int findyerror(); moveStrategy( violations ) ERRORPTR violations ; { COMPACTPTR tileL, tileR, tileB, tileT ; ECOMPBOXPTR edge ; ERRORPTR saveError ; /* static int find_bound(*/ /* tile, direction *//* ) ;*/ int spaceAvail, location, tileWidth ; int xerror, yerror, delta, cell ; int searchl, searchb, searcht, searchr ; int i ; /* initialize moved cell array to false */ for( i=1;i<=numtilesG;i++ ){ tileNodeG[i]->moved = FALSE ; } /* APPLY RULE OF MINIMUM PERTUBATION */ saveError = violations ; /* save for free below */ for( ;violations; violations= violations->next ){ if( tileNodeG[violations->nodeI]->moved ){ /* if this cell has already been moved we need to */ /* recalulate the graph continue with next violation */ continue ; } else { tileNodeG[violations->nodeI]->moved = TRUE ; } if( tileNodeG[violations->nodeJ]->moved ){ /* if this cell has already been moved we need to */ /* recalulate the graph continue with next violation */ continue ; } else { tileNodeG[violations->nodeJ]->moved = TRUE ; } /* assume tiles are sorted already */ tileL = tileNodeG[violations->nodeI] ; tileB = tileNodeG[violations->nodeI] ; tileR = tileNodeG[violations->nodeJ] ; tileT = tileNodeG[violations->nodeJ] ; xerror = findxerror( &tileL, &tileR ) ; yerror = findyerror( &tileB, &tileT ) ; if( xerror <= -xspaceG || yerror <= -yspaceG ){ /* the problem has previously been fixed */ /* go on to next one */ continue ; } /* used to be 0.8 * yerror */ if( xerror < yerror ){ /* x error */ /* try handling as 1-D case */ /* see which direction we have more room */ /* search to the left of the tile */ searchl = INT_MIN ; if( tileL->multi ){ /* substitute rightmost left tile */ searchl = find_bound( tileL, tileR->cell, XBACKWARD ) ; } else { /* single tile */ for( edge=tileL->xadjB;edge;edge=edge->next ){ location = tileNodeG[edge->node]->r ; searchl = MAX( searchl, location ) ; } } /* keep searchl inside the core */ searchl = MAX( searchl, blocklG ) ; /* search to the right of the cell */ searchr = INT_MAX ; if( tileR->multi ){ searchr = find_bound( tileR, tileL->cell, XFORWARD ) ; } else { for( edge=tileR->xadjF;edge;edge=edge->next ){ location = tileNodeG[edge->node]->l ; searchr = MIN( searchr, location ) ; } } /* keep searchr inside the core */ searchr = MIN( searchr, blockrG ) ; tileWidth = tileL->r - tileL->l + tileR->r - tileR->l + 2*xspaceG ; spaceAvail = searchr - searchl ; if( spaceAvail > tileWidth ){ /* we can resolve the problem */ /* we resolve by traveling left to right */ /* update cell positions */ if( tileL->l <= searchl ){ delta = searchl - tileL->l + xspaceG ; cell = tileL->cell ; update_cell_tiles( cell, delta, 0 ) ; } else if( tileWidth + tileL->l > searchr ){ /* above line is same as : tileL->r + tileR->r -tileR->l > searchr) don't move tileL if not necessary */ /* tileL needs to move so tileR will fit */ delta = searchr - (tileWidth + tileL->l) ; cell = tileL->cell ; update_cell_tiles( cell, delta, 0 ) ; } ASSERT( tileR->l <= tileL->r + xspaceG,"movestrat", "Logic error") ; delta = tileL->r - tileR->l + xspaceG ; cell = tileR->cell ; update_cell_tiles( cell, delta, 0 ) ; } else { /* --------------------------------------------- Always push cells to the right. This will guarantee that overlap will always be removed. Although this will have poor worst case time behavior, we want to insure minimum perturbation to the layout at this time. When all violations are removed we will compact. */ cell = tileR->cell ; if( xerror == 0 ){ /* always move at least one space */ xerror = xspaceG ; } delta = xerror + xspaceG ; update_cell_tiles( cell, delta, 0 ) ; } } else if( yerror <= xerror ){ /* y error */ /* try handling as 1-D case */ /* see which direction we have more room */ /* search to the bottom of the cell */ searchb = INT_MIN ; if( tileB->multi ){ searchb = find_bound( tileB, tileT->cell, YBACKWARD ) ; } else { for( edge=tileB->yadjB;edge;edge=edge->next ){ location = tileNodeG[edge->node]->t ; searchb = MAX( searchb, location ) ; } } /* keep searchb inside the core */ searchb = MAX( searchb, blockbG ) ; /* search to the top of the cell */ searcht = INT_MAX ; if( tileT->multi ){ searcht = find_bound( tileT, tileB->cell, YFORWARD ) ; } else { for( edge=tileT->yadjF;edge;edge=edge->next ){ location = tileNodeG[edge->node]->b ; searcht = MIN( searcht, location ) ; } } /* keep searcht inside the core */ searcht = MIN( searcht, blocktG ) ; tileWidth = tileB->t - tileB->b + tileT->t - tileT->b + 2*yspaceG ; spaceAvail = searcht - searchb ; if( spaceAvail > tileWidth ){ /* we can resolve the problem */ /* we resolve by traveling left to right */ /* update cell positions */ if( tileB->b <= searchb ){ /* tileB in error - def. need to move it */ delta = searchb - tileB->b + yspaceG ; cell = tileB->cell ; update_cell_tiles( cell, 0, delta ) ; } else if( tileWidth + tileB->b > searcht ){ /* above line is same as : tileB->t + tileT->t -tileT->b > searcht) don't move tileB if not necessary */ /* tileB needs to move so tileT will fit */ delta = searcht - (tileWidth + tileB->b ) ; cell = tileB->cell ; update_cell_tiles( cell, 0, delta ) ; } ASSERT( tileT->b <= tileB->t + yspaceG,"movestrat", "Logic error") ; delta = tileB->t - tileT->b + yspaceG ; cell = tileT->cell ; update_cell_tiles( cell, 0, delta ) ; } else { /* --------------------------------------------- Always push cells to the top. See above comments. */ cell = tileT->cell ; if( yerror == 0 ){ /* always move at least one space */ yerror = yspaceG ; } delta = yerror + yspaceG ; update_cell_tiles( cell, 0, delta ) ; } } } /* end for loop - done processing violations */ /* free violations */ /* free all the edges */ for(violations=saveError;violations; ){ saveError = violations ; violations = violations->next ; Ysafe_free(saveError) ; } } /* end moveStrategy */ /* HOW to update the tiles of the cells */ update_cell_tiles( cell, deltax, deltay ) int cell, deltax, deltay ; { CELLBOXPTR cellptr ; COMPACTPTR t ; NODEPTR tileptr ; int tile ; ASSERT( cell > 0 && cell <= numcellsG, "update_cell_tiles", "cell out of bounds" ) ; cellptr = cellarrayG[cell] ; cellptr->xcenter += deltax ; cellptr->ycenter += deltay ; cellptr->l += deltax ; cellptr->r += deltax ; cellptr->b += deltay ; cellptr->t += deltay ; /* go thru all the tiles of cell updating position */ for( tileptr = cellptr->tiles;tileptr;tileptr=tileptr->next ){ tile = tileptr->node ; ASSERT( tile > 0 && tile <= numtilesG, "update_cell_tiles", "tile out of bounds" ) ; t = tileNodeG[tile] ; t->l += deltax ; t->r += deltax ; t->b += deltay ; t->t += deltay ; t->moved = TRUE ; } /* end delta update */ D( "mc_compact/update_cell_tiles", dcheck_pos( cell ) ) ; } /* end update_cell_tiles */ BOOL dcheck_pos( cell ) int cell ; { #ifdef DEBUG CELLBOXPTR cptr ; COMPACTPTR t ; NODEPTR tileptr ; int tile, xc, yc ; cptr = cellarrayG[cell] ; xc = cptr->xcenter ; yc = cptr->ycenter ; ASSERT( cptr->l == xc + cptr->l_rel, "dcheck_pos", "cptr->l error\n"); ASSERT( cptr->r == xc + cptr->r_rel, "dcheck_pos", "cptr->r error\n"); ASSERT( cptr->b == yc + cptr->b_rel, "dcheck_pos", "cptr->b error\n"); ASSERT( cptr->t == yc + cptr->t_rel, "dcheck_pos", "cptr->t error\n"); /* go thru all the tiles of cell updating position */ for( tileptr = cptr->tiles;tileptr;tileptr=tileptr->next ){ tile = tileptr->node ; ASSERT( tile > 0 && tile <= numtilesG, "dcheck_pos", "tile out of bounds" ) ; t = tileNodeG[tile] ; ASSERT( t->l == xc + t->l_rel, "dcheck_pos", "t->l error\n"); ASSERT( t->r == xc + t->r_rel, "dcheck_pos", "t->r error\n"); ASSERT( t->b == yc + t->b_rel, "dcheck_pos", "t->b error\n"); ASSERT( t->t == yc + t->t_rel, "dcheck_pos", "t->t error\n"); } /* end tile check */ #endif /* DEBUG */ } /* end dcheck_pos */ static int find_bound( tile, avoid, direction ) COMPACTPTR tile ; int avoid ; /* avoid finding tile that you have error (cell #) */ int direction ; { int cell ; /* current cell of given tile */ int slack ; /* slack for this tile pair */ int minslack ; /* minimum slack over all constraints */ ECOMPBOXPTR edge ; /* current adjacent edge */ COMPACTPTR tptr ; /* current tile box in cell of interest */ COMPACTPTR tptr2; /* tile box for another cell */ NODEPTR tiles ; /* look at the tiles of the given cell */ minslack = INT_MAX ; cell = tile->cell ; /* look at each tile of the cell an find the minimum that it can move */ for( tiles = cellarrayG[cell]->tiles ;tiles; tiles = tiles->next ){ tptr = tileNodeG[tiles->node] ; switch( direction ){ case XFORWARD: for( edge = tptr->xadjF; edge ; edge=edge->next ){ tptr2 = tileNodeG[edge->node] ; if( tptr2->cell != avoid && tptr2->cell != cell ){ slack = tptr2->l - tptr->r - xspaceG ; minslack = MIN( slack, minslack ) ; } } break ; case XBACKWARD: for( edge = tptr->xadjB; edge ; edge =edge->next ){ tptr2 = tileNodeG[edge->node] ; if( tptr2->cell != avoid && tptr2->cell != cell ){ slack = tptr->l - tptr2->r - xspaceG ; minslack = MIN( slack, minslack ) ; } } break ; case YFORWARD: for( edge = tptr->yadjF; edge ; edge=edge->next ){ tptr2 = tileNodeG[edge->node] ; if( tptr2->cell != avoid && tptr2->cell != cell ){ slack = tptr2->b - tptr->t - yspaceG ; minslack = MIN( slack, minslack ) ; } } break ; case YBACKWARD: for( edge = tptr->yadjB; edge ; edge=edge->next ){ tptr2 = tileNodeG[edge->node] ; if( tptr2->cell != avoid && tptr2->cell != cell ){ slack = tptr->b - tptr2->t - yspaceG ; minslack = MIN( slack, minslack ) ; } } break ; } /* end switch */ } /* at list point slack has been calculated */ /* don't allow negative slack - this means tiles overlap */ if( minslack < 0 ){ minslack = 0 ; } /* this occurs when the cell is at the edge of the core */ /* give to the edge of the core region in forward directions */ if( minslack == INT_MAX ){ switch( direction ){ case XFORWARD: minslack = (INT) ( 0.25 * (DOUBLE) ABS(blockrG-blocklG)) ; break ; case XBACKWARD: minslack = 0 ; break ; case YFORWARD: minslack = (INT) ( 0.25 * (DOUBLE) ABS(blocktG-blockbG)) ; break ; case YBACKWARD: minslack = 0 ; break ; } /* end switch */ } /* now calculate how far the tile can move based on slack */ switch( direction ){ case XFORWARD: return( tile->r + minslack ) ; case XBACKWARD: return( tile->l - minslack ) ; case YFORWARD: return( tile->t + minslack ) ; case YBACKWARD: return( tile->b - minslack ) ; } /* end switch */ } /* end find_bound */ static int findxerror( tileL_addr, tileR_addr ) COMPACTPTR *tileL_addr, *tileR_addr ; { int x1 ; /* xerror */ int x2 ; /* xerror */ int cell ; /* current cell */ int slack ; /* distance from tileL */ int xerror ; /* overlap in x direction */ int overlap ; /* > 0 for overlap */ int maxslack ; /* the furthest from tileL */ COMPACTPTR tileL ; /* left tile */ COMPACTPTR tileR ; /* right tile */ COMPACTPTR tempTile ; /* current tile */ COMPACTPTR multiL ; /* rightmost tile of left cell */ COMPACTPTR multiR ; /* leftmost tile of right cell */ CELLBOXPTR cell1 ; /* assumed left cell */ CELLBOXPTR cell2 ; /* assumed right cell */ ECOMPBOXPTR edge ; /* assume tiles are correctly determined left and right */ /* we will verify and switch below */ tileL = *tileL_addr ; tileR = *tileR_addr ; cell1 = cellarrayG[tileL->cell] ; cell2 = cellarrayG[tileR->cell] ; /* determine left and right cells */ overlap = projectX( cell1->l, cell1->r, cell2->l, cell2->r ) ; switch( overlap ){ case OVERLAP1: /* -------------------------------------------------------- +--------------------------------+ | +---------------------+ | |cell | cell 1 | | | 2 +---------------------+ | +--------------------------------+ cell 1 is completely inside cell 2 find smaller dimension ----------------------------------------------------------- */ x1 = cell1->r - cell2->l ; /* move 1 to left if smaller */ x2 = cell2->r - cell1->l ; /* move 1 to right if smaller */ if( x1 <= x2 ){ xerror = x1 ; } else { xerror = x2 ; /* need to swap cells */ tileL = *tileR_addr ; tileR = *tileL_addr ; } break ; case OVERLAP2: /* -------------------------------------------------------- +--------------------------------+ | +-------------|--------+ | cell | cell 2 | | | 1 +-------------|--------+ +--------------------------------+ cell two is to right of cell 1 no need to swap ----------------------------------------------------------- */ xerror = cell1->r - cell2->l ; break ; case OVERLAP3: /* -------------------------------------------------------- +--------------------------------+ +-----|----------------+ | | | cell 2 | cell 1 | +-----|----------------+ | +--------------------------------+ cell one is to right of cell 1 need to swap ----------------------------------------------------------- */ /* need to swap cells */ tileL = *tileR_addr ; tileR = *tileL_addr ; xerror = cell2->r - cell1->l ; break ; } /* end switch on overlap of cells */ /* now find the tiles will help us remove the violations the most */ multiL = NULL ; multiR = NULL ; if( tileL->multi ){ /* search right for constraints within same cell */ /* and other cell overlapping with constraints */ /* find the rightmost tile touching tileR */ /* it will become the new tile to be moved */ cell = tileL->cell ; maxslack = 0 ; for( edge=tileL->xadjF;edge;edge=edge->next ){ tempTile = tileNodeG[ edge->node ] ; if( tempTile->cell == cell ){ overlap = projectY( tempTile->b, tempTile->t, tileR->b, tileR->t ) ; if( overlap > 0 ){ slack = tempTile->r - tileL->r ; if( slack > maxslack ){ maxslack = slack ; multiL = tempTile ; } } } } } if( tileR->multi ){ /* search right for constraints within same cell */ /* and other cell overlapping with constraints */ /* find the leftmost tile touching tileL */ /* it will become the new tile to be moved */ cell = tileR->cell ; maxslack = 0 ; for( edge=tileR->xadjB;edge;edge=edge->next ){ tempTile = tileNodeG[ edge->node ] ; if( tempTile->cell == cell ){ overlap = projectY( tempTile->b, tempTile->t, tileL->b, tileL->t ) ; if( overlap ){ slack = tileR->l - tempTile->l ; if( slack > maxslack ){ maxslack = slack ; multiR = tempTile ; } } } } } /* now return the tiles */ if( multiL ){ *tileL_addr = multiL ; } else { *tileL_addr = tileL ; } if( multiR ){ *tileR_addr = multiR ; } else { *tileR_addr = tileR ; } return( xerror ) ; } /* end findxerror */ static int findyerror( tileB_addr, tileT_addr ) COMPACTPTR *tileB_addr, *tileT_addr ; { int y1 ; /* yerror */ int y2 ; /* yerror */ int cell ; /* current cell */ int slack ; /* distance from tileB */ int yerror ; /* overlap in y direction */ int overlap ; /* > 0 for overlap */ int maxslack ; /* the furthest from tileB */ COMPACTPTR tileB ; /* bottom tile */ COMPACTPTR tileT ; /* top tile */ COMPACTPTR tempTile ; /* current tile */ COMPACTPTR multiB ; /* topmost tile of bottom cell */ COMPACTPTR multiT ; /* bottommost tile of top cell */ CELLBOXPTR cell1 ; /* assumed bottom cell */ CELLBOXPTR cell2 ; /* assumed top cell */ ECOMPBOXPTR edge ; /* assume tiles are correctly determined bottom and top */ /* we will verify and switch below */ tileB = *tileB_addr ; tileT = *tileT_addr ; cell1 = cellarrayG[tileB->cell] ; cell2 = cellarrayG[tileT->cell] ; /* determine bottom and top cells */ overlap = projectY( cell1->b, cell1->t, cell2->b, cell2->t ) ; /* see comments for findxerror */ switch( overlap ){ case OVERLAP1: y1 = cell1->t - cell2->b ; /* move 1 to bottom if smaller */ y2 = cell2->t - cell1->b ; /* move 1 to top if smaller */ if( y1 <= y2 ){ yerror = y1 ; } else { yerror = y2 ; /* need to swap cells */ tileB = *tileT_addr ; tileT = *tileB_addr ; } break ; case OVERLAP2: yerror = cell1->t - cell2->b ; break ; case OVERLAP3: /* need to swap cells */ tileB = *tileT_addr ; tileT = *tileB_addr ; yerror = cell2->t - cell1->b ; break ; } /* end switch on overlap of cells */ /* now find the tiles will help us remove the violations the most */ multiB = NULL ; multiT = NULL ; if( tileB->multi ){ /* search upward for constraints within same cell */ /* and other cell overlapping with constraints */ /* find the topmost tile touching tileB */ /* it will become the new tile to be moved */ cell = tileB->cell ; maxslack = 0 ; for( edge=tileB->yadjF;edge;edge=edge->next ){ tempTile = tileNodeG[ edge->node ] ; if( tempTile->cell == cell ){ overlap = projectX( tempTile->l, tempTile->r, tileT->l, tileT->r ) ; if( overlap > 0 ){ slack = tempTile->t - tileB->t ; if( slack > maxslack ){ maxslack = slack ; multiB = tempTile ; } } } } } if( tileT->multi ){ /* search downward for constraints within same cell */ /* and other cell overlapping with constraints */ cell = tileT->cell ; maxslack = 0 ; for( edge=tileT->yadjB;edge;edge=edge->next ){ tempTile = tileNodeG[ edge->node ] ; if( tempTile->cell == cell ){ overlap = projectX( tempTile->l, tempTile->r, tileB->l, tileB->r ) ; if( overlap > 0 ){ slack = tileT->b - tempTile->b ; if( slack > maxslack ){ maxslack = slack ; multiT = tempTile ; } } } } } /* now return the tiles */ if( multiB ){ *tileB_addr = multiB ; } else { *tileB_addr = tileB ; } if( multiT ){ *tileT_addr = multiT ; } else { *tileT_addr = tileT ; } return( yerror ) ; } /* end findyerror */ graywolf-0.1.4+20170307gite1bf319/src/mc_compact/movestrat2.c000066400000000000000000000610151305746555600231350ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: movestrat2.c DESCRIPTION:This file contains move strategy for compaction algorithm. CONTENTS: DATE: Apr 11, 1988 REVISIONS: Dec 4, 1988 - added initialization for next compaction cycle. Apr 30, 1989 - rewrote strategy so that it is a center favoring algorithm rather than left or right edge. Sun Nov 4 13:20:53 EST 1990 - rewrote to handle the multiple tiles correctly. We use cell slack instead of tile slack. Sun Nov 11 10:12:22 EST 1990 - grid cell placement if a grid is specified. Thu Apr 18 00:58:28 EDT 1991 - new version featuring constraint compaction. Wed May 1 19:14:46 EDT 1991 - new move strategy for graph constraint compaction. Mon May 6 22:37:01 EDT 1991 - make sure window is correct. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) movestrat2.c version 7.9 5/6/91" ; #endif #include #include #define PICK_INT(l,u) (((l)<(u))?((acm_random() % ((u)-(l)+1))+(l)) : (l)) #define LEFT_EDGE 0 #define RIGHT_EDGE 1 #define CENTERED 2 static INT xlongestS = INT_MAX ; static INT ylongestS = INT_MAX ; static INT area_countS = 0 ; static INT compact_countS = 0 ; static INT lengthS ; static DOUBLE best_areaS = 1.0E30 ; static x_center(); static calc_xslacks(); static update_xslacks(); static y_center(); static calc_yslacks(); static update_yslacks(); static INT sortby_xslack(); #define HEURISTIC1 /* -------------------------------------------------------------- space requirements also include 2 sources and 2 sinks: xSource = 0, xsink = numtilesG + 1, ysource = numtilesG + 2, and ysink = numtilesG + 3 positions in the tileNode array. */ BOOL move_compactx( length ) INT length ; { INT i, newX, oldX, delta_move ; INT node ; INT cell ; INT dist ; INT span ; COMPACTPTR boxptr ; COMPACTPTR tile ; CELLBOXPTR cptr ; INFOPTR stretch_edge ; INFOPTR min_edge ; INFOPTR max_edge ; NODEPTR nptr ; /* initialize moved cell array to false */ for( i=1;i<=numtilesG;i++ ){ tileNodeG[i]->moved = FALSE ; } if( constraintsG ){ for( cell=1;cell<=numcellsG;cell++ ){ cptr = cellarrayG[cell] ; cptr->stretched = FALSE ; } } /* let all routines know the length */ lengthS = length ; /* use the path_deck to enumerate tiles in the critical path */ if( constraintsG ){ for( Ydeck_top(path_deckG); Ydeck_notEnd(path_deckG);Ydeck_down(path_deckG) ) { node = (INT) Ydeck_getData( path_deckG ) ; tile = tileNodeG[node] ; cell = tile->cell ; cptr = cellarrayG[cell] ; if( cptr->stretched ){ /* avoid multiple adjustments */ continue ; } stretch_edge = (INFOPTR) Yrbtree_min( cptr->vedges ) ; stretch_graph( stretch_edge, tile->xvalueMin, 0 ) ; cptr->stretched = TRUE ; } #ifdef LATER /* now make sure all of the graph is large enough */ for( cell=1;cell<=numcellsG;cell++ ){ cptr = cellarrayG[ cell ] ; /* find the new center of the cell which keeps it within */ /* the graph bounding box */ min_edge = (INFOPTR) Yrbtree_min( cptr->vedges ) ; max_edge = (INFOPTR) Yrbtree_max( cptr->vedges ) ; dist = *max_edge->loc - *min_edge->loc ; span = cptr->r_rel - cptr->l_rel + xspaceG ; if( dist < span ){ /* graph needs to be stretched */ stretch_graph( max_edge, *min_edge->loc + span, 0 ) ; } } #endif } /* In order for algorithm to be correct for the multiple tile case */ /* we must first place tiles on the critical path */ for( i=1;i<=numtilesG;i++ ){ boxptr = xGraphG[i] ; if( boxptr->moved ){ /* the cell has already been placed */ continue ; } if( boxptr->criticalX ){ /* save old left edge of tile */ oldX = boxptr->l ; ASSERT( boxptr->xvalueMin == length - boxptr->xvalueMax, "move_compactx", "Critical path where xmax != xmin\n" ) ; /* calculate delta as new xcenter - old xcenter */ newX = boxptr->xvalueMin ; #ifdef LATER if( constraintsG ){ /* find the new left edge of the tile which fits */ /* in graph */ min_edge = (INFOPTR) Yrbtree_min( cellarrayG[boxptr->cell]->vedges ) ; if( newX < *min_edge->loc ){ newX = *min_edge->loc ; } } #endif /* update position of cell tiles */ delta_move = newX - oldX ; update_cell_tiles( boxptr->cell, delta_move, 0 ) ; /* now update tiles windows */ cptr = cellarrayG[boxptr->cell] ; for( nptr = cptr->tiles; nptr ; nptr=nptr->next ){ ASSERTNCONT( nptr->node > 0 && nptr->node <= numtilesG, "move_compactx", "tile out of bounds\n" ) ; tile = tileNodeG[nptr->node] ; tile->xvalueMin = cptr->xcenter + tile->l_rel ; tile->xvalueMax = length - tile->xvalueMin ; } } } /* This point we have placed the tiles in the critical path */ /* ****** now place the cells off the critical path ****** */ x_center() ; /********* end placing tiles off the critical path ***********/ /* save length */ xlongestS = length ; } /* end move_compactx */ static x_center() { INT i, newX, oldX, temp, remainder, xmin, xmax, min, max, sortby_xslack(), delta_move ; INT newpos ; COMPACTPTR boxptr ; NODEPTR nptr ; CELLBOXPTR cptr ; INFOPTR min_edge ; INFOPTR max_edge ; for( i=1;i<=numcellsG;i++ ){ /* sort the slack array by increasing slack */ calc_xslacks( i ) ; Yquicksort( (char *) &(slackG[i]), numcellsG-i, sizeof(CELLBOXPTR), sortby_xslack ) ; cptr = slackG[i] ; nptr = cptr->tiles ; ASSERTNCONT( nptr, "x_center", "nptr is null\n" ) ; boxptr = tileNodeG[nptr->node] ; if( boxptr->moved ){ /* the cell has already been placed */ continue ; } ASSERT( !boxptr->criticalX, "move_compactx", "Critical path tile should already have been placed\n" ); /* first heuristic-move everything to ave. of constraints */ /* find window intersection of all constraints */ xmin = cptr->xmin ; xmax = cptr->xmax ; ASSERT( xmin <= xmax, "x_center", "Constraints cannot be met\n"); /* relative to cell center */ newX = (xmin + xmax) DIVIDED_BY_2 ; oldX = cptr->xcenter ; /********* constrain cell center if graph is specified *********/ if( constraintsG ){ /* find the new center of the cell which keeps it within */ /* the graph bounding box */ min_edge = (INFOPTR) Yrbtree_min( cellarrayG[boxptr->cell]->vedges ) ; max_edge = (INFOPTR) Yrbtree_max( cellarrayG[boxptr->cell]->vedges ) ; min = *min_edge->loc - cptr->l_rel ; max = *max_edge->loc - cptr->r_rel ; if( xmin <= min && max <= xmax ){ /* this means we can use the constraint graph */ if( min <= xmax ){ /* we can use the graph constraint for lower bound */ xmin = min ; } else { /* make sure we meet the window constraints */ xmin = xmax ; } if( min <= max && xmin <= max ){ /* we can use the graph constraint for upper bound */ xmax = max ; } else { /* cell doesn't fit adjust to left */ xmax = xmin ; } /* in these two cases do the best we can */ } else if( xmin <= min && min <= xmax ){ xmin = min ; } else if ( max <= xmax && xmin <= max ){ xmax = max ; } newX = (xmin + xmax) DIVIDED_BY_2 ; } /********* grid cell data if specified *************/ /* set lower left corner to grid */ if( xgridG ){ /* only do if non zero */ temp = newX + cptr->xoffset ; /* do individual tests only one may be zero */ if( remainder = temp % xgridG ){ /* fix x direction */ temp += xgridG - remainder ; } newpos = temp - cptr->xoffset ; if( newpos < xmin ){ /* try next larger grid */ newpos += xgridG ; if( newpos < xmin || newpos > xmax ){ newX = xmin ; } else { newX = newpos ; } } else if( newpos > xmax ){ /* try next grid */ newpos -= xgridG ; if( newpos < xmin || newpos > xmax ){ newX = xmax ; } else { newX = newpos ; } } else { newX = newpos ; } } /* update position of cell tiles */ delta_move = newX - oldX ; update_cell_tiles( boxptr->cell, delta_move, 0 ) ; update_xslacks( boxptr ) ; } /* end looking at cells off the critical path */ } /* end center_x */ static calc_xslacks( cur_cell ) { INT i ; /* counter */ INT xmin ; /* max of all the minimums of a cell */ INT xmax ; /* min of all the maximums of a cell */ INT cent_min ; /* min window of cell center relative */ INT cent_max ; /* max window of cell center relative */ NODEPTR nptr ; /* current tile node of cell */ CELLBOXPTR cptr ; /* current cell */ COMPACTPTR tptr ; /* current tile of cell */ /*********************************************************** * We need to find the intersection of all the tiles of a cell, * that is, we want to find the maximum of all the minimum windows * of the tiles relative to the center of the cell (called xmin). * Likewise, we want to find the minimum of all the maximum windows * relative to the xcenter of the cell. We call that xmax. ***********************************************************/ for( i = cur_cell; i <= numcellsG; i++ ){ cptr = slackG[i] ; if( cptr->multi ){ xmin = INT_MIN ; xmax = INT_MAX ; for( nptr = cptr->tiles; nptr ; nptr=nptr->next ){ ASSERTNCONT( nptr->node > 0 && nptr->node <= numtilesG, "calc_xslacks", "tile out of bounds\n" ) ; tptr = tileNodeG[nptr->node] ; /* first make center relative */ cent_min = tptr->xvalueMin - tptr->l_rel ; cent_max = lengthS - tptr->xvalueMax - tptr->l_rel ; xmin = MAX( xmin, cent_min ) ; xmax = MIN( xmax, cent_max ) ; } /* now save the value of the slack */ cptr->xmin = xmin ; cptr->xmax = xmax ; } else { /* the easy case only one tile */ nptr = cptr->tiles; ASSERTNCONT( nptr->node > 0 && nptr->node <= numtilesG, "calc_xslacks", "tile out of bounds\n" ) ; tptr = tileNodeG[nptr->node] ; cptr->xmin = tptr->xvalueMin - tptr->l_rel ; cptr->xmax = lengthS - tptr->xvalueMax - tptr->l_rel ; } } } /* end calc_xslacks */ static update_xslacks( tptr ) COMPACTPTR tptr ; { INT j ; /* current tile adjacent to node */ INT node ; /* current node popped from the queue */ INT tile ; /* one of the tiles of the adj. cell */ INT length ; /* length of longest path */ INT setValue ; /* the value of the path to this adj node */ INT currentValue ; /* path value of node popped from queue */ INT siblingValue ; /* the value of the path to sibling of adj node */ BOOL first ; /* used to setup the queue */ NODEPTR nptr ; /* used to traverse multi tiles */ CELLBOXPTR cptr ; /* the current cell */ COMPACTPTR sibling ; /* the tile record of the sibling to adj node */ COMPACTPTR nextptr ; /* the tile record of the adj. node */ ECOMPBOXPTR ptr ; /* used to traverse edges of popped node */ QUEUEPTR botqueue, queue ; /* used to implement queue MACRO */ YSETLISTPTR nodeptr ; /* used to set the ancestors correctly */ /* ****************************************************** Algorithm for updating the xslacks. See algorithm for updating yslacks below. * ******************************************************* */ /* now update tiles windows */ cptr = cellarrayG[tptr->cell] ; for( nptr = cptr->tiles; nptr ; nptr=nptr->next ){ ASSERTNCONT( nptr->node > 0 && nptr->node <= numtilesG, "move_compactx", "tile out of bounds\n" ) ; nextptr = tileNodeG[nptr->node] ; nextptr->xvalueMin = cptr->xcenter + nextptr->l_rel ; nextptr->xvalueMax = lengthS - nextptr->xvalueMin ; } longestxPath( FALSE ) ; } /* end update_xslacks */ BOOL move_compacty( length ) int length ; { INT i, newY, oldY, delta_move ; INT node ; INT cell ; INT dist ; INT span ; COMPACTPTR boxptr ; COMPACTPTR tile ; CELLBOXPTR cptr ; INFOPTR stretch_edge ; INFOPTR min_edge ; INFOPTR max_edge ; NODEPTR nptr ; /* initialize moved cell array to false */ for( i=1;i<=numtilesG;i++ ){ tileNodeG[i]->moved = FALSE ; } if( constraintsG ){ for( cell=1;cell<=numcellsG;cell++ ){ cptr = cellarrayG[cell] ; cptr->stretched = FALSE ; } } /* let all routines know the length */ lengthS = length ; /* use the path_deck to enumerate tiles in the critical path */ if( constraintsG ){ for( Ydeck_top(path_deckG); Ydeck_notEnd(path_deckG);Ydeck_down(path_deckG) ) { node = (INT) Ydeck_getData( path_deckG ) ; tile = tileNodeG[node] ; cell = tile->cell ; cptr = cellarrayG[cell] ; if( cptr->stretched ){ /* avoid multiple adjustments */ continue ; } stretch_edge = (INFOPTR) Yrbtree_min( cptr->hedges ) ; stretch_graph( stretch_edge, 0, tile->yvalueMin ) ; cptr->stretched = TRUE ; } #ifdef LATER /* now make sure all of the graph is large enough */ for( cell=1;cell<=numcellsG;cell++ ){ cptr = cellarrayG[ cell ] ; /* find the new center of the cell which keeps it within */ /* the graph bounding box */ min_edge = (INFOPTR) Yrbtree_min( cptr->hedges ) ; max_edge = (INFOPTR) Yrbtree_max( cptr->hedges ) ; dist = *max_edge->loc - *min_edge->loc ; span = cptr->t_rel - cptr->b_rel + yspaceG ; if( dist < span ){ /* graph needs to be stretched */ stretch_graph( max_edge, 0, *min_edge->loc + span ) ; } } #endif } /* In order for algorithm to be correct for the multiple tile case */ /* we must first place tiles on the critical path */ for( i=1;i<=numtilesG;i++ ){ boxptr = yGraphG[i] ; if( boxptr->moved ){ /* the cell has already been placed */ continue ; } if( boxptr->criticalY ){ /* save old left edge of tile */ oldY = boxptr->b ; ASSERT( boxptr->yvalueMin == length - boxptr->yvalueMax, "move_compacty", "Critical path where ymax != ymin" ) ; /* calculate delta as new ycenter - old ycenter */ newY = boxptr->yvalueMin ; #ifdef LATER if( constraintsG ){ /* find the new bottom edge of the tile which fits */ /* in graph */ min_edge = (INFOPTR) Yrbtree_min( cellarrayG[boxptr->cell]->hedges ) ; if( newY < *min_edge->loc ){ newY = *min_edge->loc ; } } #endif delta_move = newY - oldY ; /* update position of cell tiles */ update_cell_tiles( boxptr->cell, 0, delta_move ) ; /* now update tiles windows */ cptr = cellarrayG[boxptr->cell] ; for( nptr = cptr->tiles;nptr; nptr=nptr->next ){ ASSERTNCONT( nptr->node > 0 && nptr->node <= numtilesG, "move_compactx", "tile out of bounds\n" ) ; tile = tileNodeG[nptr->node] ; tile->yvalueMin = cptr->ycenter + tile->b_rel ; tile->yvalueMax = length - tile->yvalueMin ; } } } /* This point we have placed the tiles in the critical path */ /* ****** now place the cells off the critical path ****** */ y_center() ; /********* end placing tiles off the critical path ***********/ /* save length */ ylongestS = length ; } /* end move_compacty */ static y_center() { int i, newY, oldY, temp, remainder, min, max, ymin, ymax, delta_move ; INT sortby_yslack(); INT newpos ; COMPACTPTR boxptr ; NODEPTR nptr ; CELLBOXPTR cptr ; INFOPTR min_edge ; INFOPTR max_edge ; for( i=1;i<=numcellsG;i++ ){ /* sort the slack array by increasing slack */ calc_yslacks( i ) ; Yquicksort( (char *) &(slackG[i]), numcellsG-i, sizeof(CELLBOXPTR), sortby_yslack ) ; cptr = slackG[i] ; nptr = cptr->tiles ; ASSERTNCONT( nptr, "y_center", "nptr is null\n" ) ; boxptr = tileNodeG[nptr->node] ; if( boxptr->moved ){ /* the cell has already been placed */ continue ; } ASSERT( !boxptr->criticalY, "move_compacty", "Critical path tile should already have been placed\n" ); /* first heuristic-move everything to ave. of constraints */ /* find window intersection of all constraints */ ymin = cptr->ymin ; ymax = cptr->ymax ; ASSERT( ymin <= ymax, "y_center", "Constraints cannot be met\n"); /* relative to cell center */ newY = (ymin + ymax) DIVIDED_BY_2 ; oldY = cptr->ycenter ; /********* constrain cell center if graph is specified *********/ if( constraintsG ){ /* find the new center of the cell which keeps it within */ /* the graph bounding box */ min_edge = (INFOPTR) Yrbtree_min( cellarrayG[boxptr->cell]->hedges ) ; max_edge = (INFOPTR) Yrbtree_max( cellarrayG[boxptr->cell]->hedges ) ; min = *min_edge->loc - cptr->b_rel ; max = *max_edge->loc - cptr->t_rel ; if( ymin <= min && max <= ymax ){ /* this means we can use the constraint graph */ if( min <= ymax ){ /* we can use the graph constraint for lower bound */ ymin = min ; } else { /* make sure we meet the window constraints */ ymin = ymax ; } if( min <= max && ymin <= max ){ /* we can use the graph constraint for upper bound */ ymax = max ; } else { /* cell doesn't fit adjust to left */ ymax = ymin ; } /* in these two cases do the best we can */ } else if( ymin <= min && min <= ymax ){ ymin = min ; } else if ( max <= ymax && ymin <= max ){ ymax = max ; } newY = (ymin + ymax) DIVIDED_BY_2 ; } /********* grid cell data if specified *************/ /* set lower left corner to grid */ if( ygridG ){ /* only do if non zero */ temp = newY + cptr->yoffset ; /* do individual tests only one may be zero */ if( remainder = temp % ygridG ){ /* fix y direction */ temp += ygridG - remainder ; } newpos = temp - cptr->yoffset ; if( newpos < ymin ){ /* try next larger grid */ newpos += ygridG ; if( newpos < ymin || newpos > ymax ){ newY = ymin ; } else { newY = newpos ; } } else if( newpos > ymax ){ /* try next grid */ newpos -= ygridG ; if( newpos < ymin || newpos > ymax ){ newY = ymax ; } else { newY = newpos ; } } else { newY = newpos ; } } /* update position of cell tiles */ delta_move = newY - oldY ; update_cell_tiles( boxptr->cell, 0, delta_move ) ; update_yslacks( boxptr ) ; } /* end looking at cells off the critical path */ } /* end y_center */ static calc_yslacks( cur_cell ) { INT i ; /* counter */ INT ymin ; /* max of all the minimums of a cell */ INT ymax ; /* min of all the maximums of a cell */ INT cent_min ; /* min window of cell center relative */ INT cent_max ; /* max window of cell center relative */ NODEPTR nptr ; /* current tile node of cell */ CELLBOXPTR cptr ; /* current cell */ COMPACTPTR tptr ; /* current tile of cell */ /*********************************************************** * We need to find the intersection of all the tiles of a cell, * that is, we want to find the maximum of all the minimum windows * of the tiles relative to the center of the cell (called ymin). * Likewise, we want to find the minimum of all the maximum windows * relative to the ycenter of the cell. We call that ymax. ***********************************************************/ for( i = cur_cell; i <= numcellsG; i++ ){ cptr = slackG[i] ; if( cptr->multi ){ ymin = INT_MIN ; ymax = INT_MAX ; for( nptr = cptr->tiles; nptr ; nptr=nptr->next ){ ASSERTNCONT( nptr->node > 0 && nptr->node <= numtilesG, "calc_yslacks", "tile out of bounds\n" ) ; tptr = tileNodeG[nptr->node] ; /* first make center relative */ cent_min = tptr->yvalueMin - tptr->b_rel ; cent_max = lengthS - tptr->yvalueMax - tptr->b_rel ; ymin = MAX( ymin, cent_min ) ; ymax = MIN( ymax, cent_max ) ; } /* now save the value of the slack */ cptr->ymin = ymin ; cptr->ymax = ymax ; } else { /* the easy case only one tile */ nptr = cptr->tiles; ASSERTNCONT( nptr->node > 0 && nptr->node <= numtilesG, "calc_yslacks", "tile out of bounds\n" ) ; tptr = tileNodeG[nptr->node] ; cptr->ymin = tptr->yvalueMin - tptr->b_rel ; cptr->ymax = lengthS - tptr->yvalueMax - tptr->b_rel ; } } } /* end calc_yslacks */ static update_yslacks( tptr ) COMPACTPTR tptr ; { INT j ; /* current tile adjacent to node */ INT node ; /* current node popped from the queue */ INT tile ; /* one of the tiles of the adj. cell */ INT length ; /* length of longest path */ INT setValue ; /* the value of the path to this adj node */ INT currentValue ; /* path value of node popped from queue */ INT siblingValue ; /* the value of the path to sibling of adj node */ BOOL first ; /* used to setup the queue */ NODEPTR nptr ; /* used to traverse multi tiles */ CELLBOXPTR cptr ; /* the current cell */ COMPACTPTR sibling ; /* the tile record of the sibling to adj node */ COMPACTPTR nextptr ; /* the tile record of the adj. node */ ECOMPBOXPTR ptr ; /* used to traverse edges of popped node */ QUEUEPTR botqueue, queue ; /* used to implement queue MACRO */ YSETLISTPTR nodeptr ; /* used to set the ancestors correctly */ /* ****************************************************** Algorithm for updating the yslacks. We need to actually perform longest path algorithm to update the slacks but we need to do it with fixed objects. * ******************************************************* */ /* now update tiles windows */ cptr = cellarrayG[tptr->cell] ; for( nptr = cptr->tiles; nptr ; nptr=nptr->next ){ ASSERTNCONT( nptr->node > 0 && nptr->node <= numtilesG, "move_compactx", "tile out of bounds\n" ) ; nextptr = tileNodeG[nptr->node] ; nextptr->yvalueMin = cptr->ycenter + nextptr->b_rel ; nextptr->yvalueMax = lengthS - nextptr->yvalueMin ; } longestyPath( FALSE ) ; } /* end update_yslacks */ /* sort by x first then y */ static INT sortby_xslack( cellA , cellB ) CELLBOXPTR *cellA , *cellB ; { INT excess_slacka, excess_slackb ; CELLBOXPTR cptr ; cptr = *cellA ; excess_slacka = cptr->xmax - cptr->xmin ; cptr = *cellB ; excess_slackb = cptr->xmax - cptr->xmin ; return( excess_slacka - excess_slackb ) ; } /* sortby_xslack */ /* sort by x first then y */ INT sortby_yslack( cellA , cellB ) CELLBOXPTR *cellA , *cellB ; { INT excess_slacka, excess_slackb ; CELLBOXPTR cptr ; cptr = *cellA ; excess_slacka = cptr->ymax - cptr->ymin ; cptr = *cellB ; excess_slackb = cptr->ymax - cptr->ymin ; return( excess_slacka - excess_slackb ) ; } /* sortby_yslack */ BOOL test_area() { DOUBLE area ; area = (DOUBLE) xlongestS * (DOUBLE) ylongestS ; ++compact_countS ; if( area < best_areaS ){ /* save best */ best_areaS = area ; area_countS = 0 ; } else { area_countS++ ; if( compact_countS >= 4 && area_countS >= 2 ){ return(FALSE) ; /* satisfied */ } } return(TRUE) ; /* not done yet */ } /* end test_area */ graywolf-0.1.4+20170307gite1bf319/src/mc_compact/multi.c000066400000000000000000000425151305746555600221650ustar00rootroot00000000000000/* * Copyright (C) 1990,1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: multi.c DESCRIPTION:This file contains routines for pre-processing of multi tile cells. CONTENTS: DATE: Jan 21, 1990 REVISIONS: ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) multi.c version 7.3 5/21/92" ; #endif #include #include #include typedef struct vertex_box { INT x ; INT y ; INT class ; struct vertex_box *next ; } *VERTEXPTR, VERTEX_BOX ; #define START 1 #define END 2 #define NOTHING 3 static ERRORPTR multiS = NULL ; /* list of multiple tile adjacencies */ static VERTEXPTR vertex_listS = NIL( VERTEX_BOX *) ; /* head of the list */ static preprocess_multi(); static BOOL fix_tiles(); static add_to_multi_list(); static BOOL find_tile(); static init_vertex_list(); static add_extra_points(); static swap(); static add_pt(); static free_vertex_list(); multi_tiles() { preprocess_multi( TRUE ) ; final_tiles() ; preprocess_multi( FALSE ) ; } /* end multi_tiles */ /* remove overlap between tiles of a multi-tile cell */ /* Since this operation is only done once, a reliable O(n2) algorithm */ /* is reasonable here */ static preprocess_multi( fixNotCheck ) BOOL fixNotCheck ; { int i ; /* counter */ NODEPTR firstptr ; /* the tiles belonging to this cell */ NODEPTR aptr ; /* current tile of cell a */ NODEPTR bptr ; /* current tile of cell b */ COMPACTPTR tilea ; /* info on tile a */ COMPACTPTR tileb ; /* info on tile b */ if( fixNotCheck ){ M( MSG, "preprocess_multi", "Fixing multiple tiles...\n" ) ; } else { M( MSG, "preprocess_multi", "Verifying multiple tiles...\n" ) ; } for( i=1;i<=numcellsG;i++ ){ firstptr = cellarrayG[i]->tiles ; if( !(tileNodeG[firstptr->node]->multi) ){ /* the cell has only one tile */ continue ; } TOP: for( aptr = cellarrayG[i]->tiles;aptr; aptr = aptr->next ){ ASSERTNCONT( aptr->node > 0 && aptr->node <= numtilesG, "preprocess_multi", "tile out of bounds\n" ) ; tilea = tileNodeG[aptr->node] ; for( bptr = aptr->next; bptr ; bptr = bptr->next ){ ASSERTNCONT( bptr->node > 0 && bptr->node <= numtilesG, "preprocess_multi", "tile out of bounds\n" ) ; tileb = tileNodeG[bptr->node] ; if(!(fixNotCheck)){ /* add multi tile structure during */ /* verification */ add_to_multi_list( tilea, tileb ); } /* now check for overlap */ if( projectY( tilea->b, tilea->t, tileb->b, tileb->t) ){ if( projectX( tilea->l,tilea->r,tileb->l,tileb->r )){ if( fix_tiles( tilea, tileb ) ){ /* a goto here makes logic easier to understand */ /* if we modified the tile structure we need to */ /* look at all the tiles again. A very conservative */ /* method but it should not be that bad time wise */ /* since hopefully there are no overlaps */ goto TOP ; } } } } } } /********* end check of tiles ***********/ } /* end preprocess multi */ static BOOL fix_tiles( tilea, tileb ) COMPACTPTR tilea ; /* info on tile a */ COMPACTPTR tileb ; /* info on tile b */ { INT count ; /* count the number of tiles */ INT xerror ; /* error in x direction */ INT xerror_plus ; /* error in plus configuration */ INT yerror ; /* error in y direction */ INT yerror_plus ; /* error in plus configuration */ INT xc, yc ; /* center of the given cell */ INT llx,lly,urx,ury ; /* bounds of the tile */ INT tile ; /* tile added by add_tile */ COMPACTPTR tileL ; /* left tile*/ COMPACTPTR tileR ; /* right tile */ COMPACTPTR tileB ; /* bottom tile */ COMPACTPTR tileT ; /* top tile */ COMPACTPTR tempTile ; /* for sorting tiles */ CELLBOXPTR cptr ; /* current cell */ NODEPTR nptr ; /* current node */ NODEPTR last_node ; /* the last node */ /* now do some calculations */ /* assume tiles are sorted already */ tileL = tilea ; tileR = tileb ; tileB = tilea ; tileT = tileb ; /* sort tiles by bounding box xmin */ if( tileL->l > tileR->l ){ /* assumption wrong - reverse */ tempTile = tileL ; tileL = tileR ; tileR = tempTile ; } /* sort tiles by bounding box ymin */ if( tileB->b > tileT->b ){ /* assumption wrong - reverse */ tempTile = tileB ; tileB = tileT ; tileT = tempTile ; } /* determine where the problem is */ xerror = tileL->r - tileR->l ; /* T overlap error */ if( xerror <= 0 ){ /* the cells are touching which is ok */ return( FALSE ) ; } /**** end of xerror calculation ****/ yerror = tileB->t - tileT->b ; if( yerror <= 0 ){ /* the cells are touching which is ok */ return( FALSE ) ; } /**** end of yerror calculation ****/ sprintf( YmsgG, "Multi-tile true overlap detected: cell %d tiles:%d %d\n", tilea->cell, tilea->node, tileb->node ) ; M( MSG, NULL, YmsgG ) ; free_vertex_list() ; init_vertex_list( tilea->l, tilea->b, tilea->r, tilea->t ) ; init_vertex_list( tileb->l, tileb->b, tileb->r, tileb->t ) ; add_extra_points() ; count = 0 ; cptr = cellarrayG[tilea->cell] ; while( find_tile(&llx , &lly , &urx , &ury ) ) { xc = cptr->xcenter ; yc = cptr->ycenter ; if( ++count == 1 ){ /* assign it to tilea */ tempTile = tilea ; } else if( count == 2 ){ /* assign it to tileb */ tempTile = tileb ; } else { /* need to create a new tile */ init_extra_tile( tilea->cell, tilea->type ) ; addtile( llx - xc, urx - xc, lly - yc, ury - yc ) ; continue ; /* add tile does the below work */ } tempTile->l = llx ; tempTile->r = urx ; tempTile->b = lly ; tempTile->t = ury ; tempTile->l_rel = llx - xc ; tempTile->r_rel = urx - xc ; tempTile->b_rel = lly - yc ; tempTile->t_rel = ury - yc ; tempTile->xspan = urx - llx ; tempTile->yspan = ury - lly ; } if( count == 1 ){ /* we need to delete a tile from the tileNode etc. */ last_node = NIL( NODEBOX * ) ; for( nptr = cptr->tiles; nptr; nptr= nptr->next ){ if( nptr->node == tileb->node ){ /* this is our target tile */ if( last_node ){ /* we are in the middle or end of the list */ last_node->next = nptr->next ; } else { /* we are the first tile in the list */ cptr->tiles = nptr->next ; } Ysafe_free( nptr ) ; Ysafe_free( tileb ) ; break ; } last_node = nptr ; } /* end looking for the tile */ } D( "mc_compact/fix_tiles", fprintf( stderr, "\tWe found %d tiles for this multi-tile\n", count ) ; ) ; return( TRUE ) ; } /* end fix tiles */ /* add to multi list saves a list of the nodes of a multi tile cell */ /* which are adjacent. Since the tiles of a multi tile cell cannot */ /* move relative to one another. We can precompute the edges in the */ /* graphs. Here we need only to save the node numbers */ static add_to_multi_list( tilea, tileb ) COMPACTPTR tilea ; /* info on tile a */ COMPACTPTR tileb ; /* info on tile b */ { ERRORPTR multi_tile ; /* temp pointer */ D( "mc_compact/add_to_multi_list", fprintf( stderr,"multi touch:%d -> %d\n",tilea->node,tileb->node)); /* save multi tile adjacencies - add to multi list */ if( multi_tile = multiS ){ multiS = (ERRORPTR) Ysafe_malloc( sizeof(ERRORBOX) ) ; multiS->next = multi_tile ; } else { multiS = (ERRORPTR) Ysafe_malloc( sizeof(ERRORBOX) ) ; multiS->next = NULL ; } multiS->nodeI = tilea->node ; multiS->nodeJ = tileb->node ; } /* end add_to_multi_list */ /* add the precomputed edges to the xgraph */ add_mtiles_to_xgraph() { ERRORPTR multi_tile ; /* temp pointer */ COMPACTPTR nodeI, nodeJ ; /* two adjacent nodes */ for( multi_tile = multiS; multi_tile; multi_tile = multi_tile->next ){ /* make sure to get ancestors correct */ nodeI = tileNodeG[multi_tile->nodeI] ; nodeJ = tileNodeG[multi_tile->nodeJ] ; if( nodeI->l_rel < nodeJ->l_rel ){ formxEdge( nodeI->node, nodeJ->node ) ; } else if( nodeI->l_rel > nodeJ->l_rel ){ formxEdge( nodeJ->node, nodeI->node ) ; } else { /* in the case that they are equal pick smaller node id */ if( nodeI->node < nodeJ->node ){ formxEdge( nodeI->node, nodeJ->node ) ; } else { formxEdge( nodeJ->node, nodeI->node ) ; } } } } /* end add_mtiles_to_xgraph() */ /* add the precomputed edges to the ygraph */ add_mtiles_to_ygraph() { ERRORPTR multi_tile ; /* temp pointer */ COMPACTPTR nodeI, nodeJ ; /* two adjacent nodes */ for( multi_tile = multiS; multi_tile; multi_tile = multi_tile->next ){ /* make sure to get ancestors correct */ nodeI = tileNodeG[multi_tile->nodeI] ; nodeJ = tileNodeG[multi_tile->nodeJ] ; if( nodeI->b_rel < nodeJ->b_rel ){ formyEdge( nodeI->node, nodeJ->node ) ; } else if( nodeI->b_rel > nodeJ->b_rel ){ formyEdge( nodeJ->node, nodeI->node ) ; } else { /* in the case that they are equal pick smaller node id */ if( nodeI->node < nodeJ->node ){ formyEdge( nodeI->node, nodeJ->node ) ; } else { formyEdge( nodeJ->node, nodeI->node ) ; } } } } /* end add_mtiles_to_ygraph() */ static BOOL find_tile( llx , lly , urx , ury ) INT *llx , *lly , *urx , *ury ; { VERTEX_BOX *vertex , *lvertex , *rvertex , *tvertex ; INT lowest , left_edge , right_edge , top_edge ; INT x, y ; BOOL found ; /* find the leftmost of the lowest START vertices */ /* this is where I start to write slow, but effective algs */ TOP: lowest = INT_MAX ; left_edge = INT_MAX ; lvertex = NULL ; for(vertex = vertex_listS ;vertex ; vertex = vertex->next ){ if( vertex->class == START ) { if( vertex->y < lowest ) { lowest = vertex->y ; lvertex = vertex ; left_edge = vertex->x ; } else if( vertex->y == lowest ) { if( vertex->x < left_edge ) { left_edge = vertex->x ; lvertex = vertex ; } } } } /* end for loop */ if(!(lvertex)) { return(FALSE); /* no more tiles exist */ } /* find the END vertex whose y is lowest */ /* and whose x is the nearest to the right of left_edge */ right_edge = INT_MIN ; rvertex = NULL ; for( vertex = vertex_listS;vertex;vertex = vertex->next ){ if( vertex->class == END ) { if( vertex->y == lowest ) { if( vertex->x >= left_edge ) { if( vertex->x > right_edge ) { right_edge = vertex->x ; rvertex = vertex ; } } } } } /* end for loop */ if(!(rvertex)) { lvertex->class = NOTHING ; goto TOP ; } /* now find ANY vertex whose x is between left_edge and */ /* right_edge and whose y is greater than lowest */ top_edge = INT_MAX ; tvertex = NULL ; for(vertex = vertex_listS ;vertex ; vertex = vertex->next ){ if( vertex->x >= left_edge && vertex->x <= right_edge ) { if( vertex->y > lowest ) { if( vertex->y < top_edge ) { top_edge = vertex->y ; tvertex = vertex ; } } } } /* end for loop */ if( tvertex == NULL || left_edge == right_edge || lowest == top_edge ) { lvertex->class = NOTHING ; if( rvertex ) { rvertex->class = NOTHING ; } goto TOP ; } /* change classes to NOTHING for the selected vertices */ lvertex->class = NOTHING ; rvertex->class = NOTHING ; /* here is the tile */ *llx = left_edge ; *lly = lowest ; *urx = right_edge ; *ury = top_edge ; /* now mark any of the interior points marked start or end to be nothing */ for(vertex = vertex_listS ;vertex ; vertex = vertex->next ){ if( vertex->class == START ) { x = vertex->x ; y = vertex->y ; /* any point inside the tile is nothing */ /* llx <= x < urx && lly <= y < ury */ /* project upwards */ if( *llx <= x && x < *urx && *lly <= y && y < *ury ){ vertex->y = *ury ; } } /* end start test */ if( vertex->class == END ) { x = vertex->x ; y = vertex->y ; if( *llx < x && x <= *urx && *lly <= y && y < *ury ){ vertex->y = *ury ; } } } /* end for loop */ /* the generated tile has four vertices; if any of these vertices */ /* is not currently in the list (only the two top ones could be new) */ /* we need to add them */ found = FALSE ; for(vertex = vertex_listS ;vertex ; vertex = vertex->next ){ if( vertex->x == *llx && vertex->y == *ury ) { found = TRUE ; break ; } } /* end for loop */ if( !found ) { add_pt( *llx, *ury, START ) ; } found = FALSE ; for( vertex = vertex_listS ;vertex ; vertex = vertex->next ){ if( vertex->x == *urx && vertex->y == *ury ) { found = TRUE ; break ; } } /* end for loop */ if( !found ) { add_pt( *urx, *ury, END ) ; } return(TRUE) ; } /* end find_tile */ static init_vertex_list( left, bottom, right, top ) INT left, bottom, right, top ; { /* add in inverse order so list will be in correct order */ add_pt( right, bottom, END ) ; add_pt( right, top, NOTHING ) ; add_pt( left, top, NOTHING ) ; add_pt( left, bottom, START ) ; } /* end init_vertex_list */ static add_extra_points() { INT xpt[9] ; INT ypt[9] ; INT count ; INT i, j ; INT x1, x2, x3, x4 ; INT y1, y2, y3, y4 ; VERTEXPTR vertex ; /* first load arrays */ count = 0 ; for( vertex = vertex_listS ;vertex ; vertex = vertex->next ){ xpt[++count] = vertex->x ; ypt[count] = vertex->y ; } /* end for loop */ ASSERT( count == 8, "add_extra_points", "There should be only 8 points\n" ) ; /* now check places for extra points */ for( i = 1; i <= 4; i++ ){ /* get the line for first tile */ x1 = xpt[i] ; y1 = ypt[i] ; if( i != 4 ){ x2 = xpt[i+1] ; y2 = ypt[i+1] ; } else { x2 = xpt[1] ; y2 = ypt[1] ; } /* always insure that the points are ordered */ if( x2 < x1 ){ swap( &x2, &x1 ) ; } if( y2 < y1 ){ swap( &y2, &y1 ) ; } if( (i % 2) == 1 ){ /* this is the vertical direction look for horz in second tile */ for( j = 6; j <= 8; j += 2 ){ x3 = xpt[j] ; y3 = ypt[j] ; if( j != 8 ){ x4 = xpt[j+1] ; y4 = ypt[j+1] ; } else { x4 = xpt[5] ; y4 = ypt[5] ; } if( x4 < x3 ){ swap( &x4, &x3 ) ; } if( y4 < y3 ){ swap( &x4, &x3 ) ; } if( x3 < x1 && x1 < x4 && y1 < y3 && y3 < y2 ){ /* we have an intersection */ /* x (x2,y2) | | (x3,y3) x --------------------x (x4,y4) | | x (x1,y1) */ add_pt( x1, y3, NOTHING ) ; } } } else { /* this is the horizontal direction look for vert in second tile */ for( j = 5; j <= 8; j += 2 ){ x3 = xpt[j] ; y3 = ypt[j] ; if( j != 8 ){ x4 = xpt[j+1] ; y4 = ypt[j+1] ; } else { x4 = xpt[5] ; y4 = ypt[5] ; } if( x4 < x3 ){ swap( &x4, &x3 ) ; } if( y4 < y3 ){ swap( &x4, &x3 ) ; } if( x1 < x3 && x3 < x2 && y3 < y1 && y1 < y4 ){ /* we have an intersection */ /* x (x4,y4) | | (x1,y1) x --------------------x (x2,y2) | | x (x3,y3) */ add_pt( x3, y2, NOTHING ) ; } } } } } static swap( a, b ) INT *a, *b ; { INT tmp ; tmp = *a ; *a = *b ; *b = tmp ; } /* end swap */ static add_pt( x, y, class ) INT x, y, class ; { VERTEXPTR temp ; /* head of the list */ if( temp = vertex_listS ){ vertex_listS = (VERTEX_BOX *) Ysafe_malloc( sizeof( VERTEX_BOX ) ) ; vertex_listS->next = temp ; } else { vertex_listS = (VERTEX_BOX *) Ysafe_malloc( sizeof( VERTEX_BOX ) ) ; vertex_listS->next = NIL( VERTEX_BOX * ) ; } vertex_listS->x = x ; vertex_listS->y = y ; vertex_listS->class = class ; } /* end add_pt */ static free_vertex_list() { VERTEXPTR next_vertex ; if( vertex_listS ){ for( ;vertex_listS; ){ next_vertex = vertex_listS->next ; Ysafe_free( vertex_listS ) ; vertex_listS = next_vertex ; } } } /* end free_vertex_list */ graywolf-0.1.4+20170307gite1bf319/src/mc_compact/readcgraph.c000066400000000000000000000432551305746555600231350ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley) 01/20/90"; #endif #define YYBYACC 1 /* ----------------------------------------------------------------- FILE: readcgraph.c <- readcgraph.y <- readcgraph.l DESCRIPTION:This file contains the grammar (BNF) for reading the channel graph. The rules for lex are in readcgraph.l. The grammar for yacc is in readcgraph.y. The output of yacc (y.tab.c) is renamed to readcgraph.c CONTENTS: readcgraph( fp ) FILE *fp ; yyerror(s) char *s; yywrap() Note:readcgraph.c will also include the yacc parser. DATE: Apr 7, 1988 REVISIONS: ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) readcgraph.y (Yale) version 1.1 2/23/91" ; #endif #include #include #include /* redefine yacc and lex globals */ #include /* use message routines for errors. */ #include /* use debug utilities. */ #include /* use message routines for errors. */ #undef REJECT /* undefine TWMC macro for lex's version */ #define YYDEBUG 1 /* condition compile for yacc debug */ static INT line_countS ; static char bufferS[LRECL] ; static INT nodeS ; /* current node */ static BOOL abortS = FALSE ; typedef union { INT ival ; char *string ; DOUBLE fval ; } YYSTYPE; #define INTEGER 257 #define STRING 258 #define FLOAT 259 #define NUMNODES 260 #define NUMEDGES 261 #define ADJ 262 #define NODE 263 #define LEN 264 #define CAP 265 #define COLON 266 #define X 267 #define Y 268 #define L 269 #define B 270 #define R 271 #define T 272 #define HNOTV 273 #define LB 274 #define RT 275 #define YYERRCODE 256 short yylhs[] = { -1, 0, 1, 2, 2, 3, 4, 5, 5, 6, }; short yylen[] = { 2, 2, 6, 1, 2, 2, 21, 1, 2, 31, }; short yydefred[] = { 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, }; short yydgoto[] = { 2, 3, 6, 7, 8, 13, 14, }; short yysindex[] = { -260, -264, 0, -259, -254, -261, -259, 0, -256, -253, -250, 0, -252, -256, 0, -257, -255, -251, 0, -247, -249, -244, 0, -243, -248, -246, -245, -242, -239, -238, -240, -241, -237, -236, -234, -231, -235, -233, -230, -229, -226, -225, -232, -228, -223, -222, -224, -217, -221, -227, -220, -219, -216, -209, -218, 0, -215, -207, -214, -213, -205, -212, -211, -201, -210, -208, -200, 0, }; short yyrindex[] = { 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; short yygindex[] = { 0, 0, 0, 21, 0, 0, 22, }; #define YYTABLESIZE 264 short yytable[] = { 1, 5, 4, 9, 5, 10, 12, 16, 15, 19, 22, 17, 20, 24, 25, 21, 26, 23, 30, 31, 1, 28, 27, 36, 29, 32, 37, 11, 33, 34, 35, 42, 43, 48, 38, 18, 40, 41, 39, 44, 49, 54, 45, 46, 47, 51, 52, 53, 55, 50, 58, 57, 61, 60, 56, 63, 64, 67, 66, 59, 0, 0, 62, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, }; short yycheck[] = { 260, 0, 266, 257, 263, 266, 262, 257, 261, 266, 257, 263, 267, 257, 257, 266, 264, 266, 257, 257, 0, 266, 268, 257, 266, 265, 257, 6, 269, 266, 266, 257, 257, 257, 269, 13, 266, 266, 271, 271, 257, 257, 270, 266, 266, 272, 266, 266, 257, 270, 257, 266, 257, 266, 272, 266, 257, 257, 266, 273, -1, -1, 274, -1, -1, 275, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 263, }; #define YYFINAL 2 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 275 #if YYDEBUG char *yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"INTEGER","STRING","FLOAT", "NUMNODES","NUMEDGES","ADJ","NODE","LEN","CAP","COLON","X","Y","L","B","R","T", "HNOTV","LB","RT", }; char *yyrule[] = { "$accept : start_file", "start_file : graph_size node_list", "graph_size : NUMNODES COLON INTEGER NUMEDGES COLON INTEGER", "node_list : node", "node_list : node_list node", "node : node_info adjacency_list", "node_info : NODE COLON INTEGER X COLON INTEGER Y COLON INTEGER L COLON INTEGER R COLON INTEGER B COLON INTEGER T COLON INTEGER", "adjacency_list : adjacent_node", "adjacency_list : adjacency_list adjacent_node", "adjacent_node : ADJ NODE COLON INTEGER LEN COLON INTEGER CAP COLON INTEGER L COLON INTEGER R COLON INTEGER B COLON INTEGER T COLON INTEGER HNOTV COLON INTEGER LB COLON INTEGER RT COLON INTEGER", }; #endif #define yyclearin (yychar=(-1)) #define yyerrok (yyerrflag=0) #ifdef YYSTACKSIZE #ifndef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #endif #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 500 #define YYMAXDEPTH 500 #endif #endif int yydebug; int yynerrs; int yyerrflag; int yychar; short *yyssp; YYSTYPE *yyvsp; YYSTYPE yyval; YYSTYPE yylval; short yyss[YYSTACKSIZE]; YYSTYPE yyvs[YYSTACKSIZE]; #define yystacksize YYSTACKSIZE #include "readcgraph_l.h" /* add readcgraph_l.h for debug purposes */ /* ********************* #include "readcgraph_l.h" *******************/ /* ********************* #include "readcgraph_l.h" *******************/ read_cgraph() { char filename[LRECL] ; #ifdef YYDEBUG extern int yydebug ; yydebug = FALSE ; #endif sprintf( filename, "%s.mrte", cktNameG ) ; yyin = TWOPEN( filename, "r", ABORT ) ; line_countS = 0 ; /* parse input file using yacc */ yyparse(); if( abortS ){ YexitPgm( PGMFAIL ) ; } } /* end read_cgraph */ yyerror(s) char *s; { sprintf(YmsgG,"problem reading %s.mrte:", cktNameG ); M( ERRMSG, "yacc", YmsgG ) ; sprintf(YmsgG, " line %d near '%s' : %s\n" , line_countS+1, yytext, s ); M( MSG,"yacc", YmsgG ) ; abortS = TRUE ; } yywrap() { return(1); } #define YYABORT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int yyparse() { register int yym, yyn, yystate; #if YYDEBUG register char *yys; extern char *getenv(); if (yys = getenv("YYDEBUG")) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = (-1); yyssp = yyss; yyvsp = yyvs; *yyssp = yystate = 0; yyloop: if (yyn = yydefred[yystate]) goto yyreduce; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, shifting to state %d\n", yystate, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; #ifdef lint goto yynewerror; #endif yynewerror: #if YYDEBUG { int test_state, i, expect, two_or_more ; char err_msg[BUFSIZ] ; if( yyname[yychar] ){ sprintf( err_msg, "\nsyntax error - found:%s expected:", yyname[yychar] ) ; two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = YYERRCODE+1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if( expect <= YYTABLESIZE && yycheck[expect] == i ){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = YYERRCODE+1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if( expect <= YYTABLESIZE && yycheck[expect] == i ){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } strcat( err_msg, "\n" ) ; yyerror( err_msg ) ; } else { yyerror("syntax error"); } } #else yyerror("syntax error"); #endif #ifdef lint goto yyerrlab; #endif yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, error recovery shifting\ to state %d\n", *yyssp, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("yydebug: error recovery discarding state %d\n", *yyssp); #endif if (yyssp <= yyss) goto yyabort; --yyssp; --yyvsp; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, error recovery discards token %d (%s)\n", yystate, yychar, yys); } #endif yychar = (-1); goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("yydebug: state %d, reducing by rule %d (%s)\n", yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; yyval = yyvsp[1-yym]; switch (yyn) { case 2: { init_graph( yyvsp[-3].ival, yyvsp[0].ival ) ; } break; case 6: { /* node:1 x:2 y:4 l:0 r:9 b:0 t:8 */ /* node number, center and size */ nodeS = yyvsp[-18].ival ; addNode( yyvsp[-18].ival, yyvsp[-15].ival, yyvsp[-12].ival ) ; } break; case 9: { /* ex. adj node:2 len:32 cap:14 l:-89 r:-63 b:0 t:6 HnotV:1 lb:0 rt:0 */ addEdge( nodeS, yyvsp[-27].ival, /* nodeS, node */ yyvsp[-6].ival, yyvsp[-3].ival, yyvsp[0].ival ) ;/* HnotV, lbcell, rtcelll */ } break; } yyssp -= yym; yystate = *yyssp; yyvsp -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state 0 to\ state %d\n", YYFINAL); #endif yystate = YYFINAL; *++yyssp = YYFINAL; *++yyvsp = yyval; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state %d \ to state %d\n", *yyssp, yystate); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate; *++yyvsp = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: return (1); yyaccept: return (0); } graywolf-0.1.4+20170307gite1bf319/src/mc_compact/readcgraph.h000066400000000000000000000045001305746555600231300ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: readcgraph.h DESCRIPTION:This file redefines global variable of yacc and lex so that we can have more than one parser in TimberWolfMC. CONTENTS: macro redefinitions for graph parser in detail router.. DATE: Aug 7, 1988 REVISIONS: Thu Mar 7 01:41:07 EST 1991 - added more definitions for byacc. ----------------------------------------------------------------- */ /* ***************************************************************** "@(#) readcgraph.h (Yale) version 1.2 3/7/91" ***************************************************************** */ #define yyact DRG_yyact #define yyback DRG_yyback #define yybgin DRG_yybgin #define yychar DRG_yychar #define yychk DRG_yychk #define yycrank DRG_yycrank #define yydebug DRG_yydebug #define yydef DRG_yydef #define yyerrflag DRG_yyerrflag #define yyerror DRG_yyerror #define yyestate DRG_yyestate #define yyexca DRG_yyexca #define yyextra DRG_yyextra #define yyfnd DRG_yyfnd #define yyin DRG_yyin #define yyinput DRG_yyinput #define yyleng DRG_yyleng #define yylex DRG_yylex #define yylineno DRG_yylineno #define yylook DRG_yylook #define yylsp DRG_yylsp #define yylstate DRG_yylstate #define yylval DRG_yylval #define yymatch DRG_yymatch #define yymorfg DRG_yymorfg #define yynerrs DRG_yynerrs #define yyolsp DRG_yyolsp #define yyout DRG_yyout #define yyoutput DRG_yyoutput #define yypact DRG_yypact #define yyparse DRG_yyparse #define yypgo DRG_yypgo #define yyprevious DRG_yyprevious #define yyreds DRG_yyreds #define yyr1 DRG_yyr1 #define yyr2 DRG_yyr2 #define yysbuf DRG_yysbuf #define yysptr DRG_yysptr #define yysvec DRG_yysvec #define yytchar DRG_yytchar #define yytext DRG_yytext #define yytoks DRG_yytoks #define yytop DRG_yytop #define yyunput DRG_yyunput #define yyv DRG_yyv #define yyval DRG_yyval #define yyvstop DRG_yyvstop #define yywrap DRG_yywrap /* for byacc */ #define yyrule DRG_yyrule #define yyname DRG_yyname #define yytable DRG_yytable #define yycheck DRG_yycheck #define yydgoto DRG_yydgoto #define yydefred DRG_yydefred #define yygindex DRG_yygindex #define yyrindex DRG_yyrindex #define yysindex DRG_yysindex #define yylen DRG_yylen #define yylhs DRG_yylhs graywolf-0.1.4+20170307gite1bf319/src/mc_compact/readcgraph_l.h000066400000000000000000000346471305746555600234620ustar00rootroot00000000000000#ifdef linux #include #else # include "stdio.h" #endif #include # define U(x) ((x)&0377) # define NLSTATE yyprevious=YYNEWLINE # define BEGIN yybgin = yysvec + 1 + # define INITIAL 0 # define YYLERR yysvec # define YYSTATE (yyestate-yysvec-1) # define YYOPTIM 1 # define YYLMAX 200 # define output(c) putc(c,yyout) # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} # define yymore() (yymorfg=1) # define ECHO fprintf(yyout, "%s",yytext) # define REJECT { nstr = yyreject(); goto yyfussy;} int yyleng; extern char yytext[]; int yymorfg; extern char *yysptr, yysbuf[]; int yytchar; #ifdef linux FILE *yyin = NULL, *yyout = NULL; #else FILE *yyin ={stdin}, *yyout ={stdout}; #endif extern int yylineno; struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops;}; struct yysvf *yyestate; extern struct yysvf yysvec[], *yybgin; /* ----------------------------------------------------------------- FILE: readcgraph.l DESCRIPTION:rules for lexical analyzer in readcgraph. This lexical analyzer uses a binary search to reduce the size of the f.a. generated by lex. Thanks to Gary Richey who showed me the trick. See chapter 3 of "Introduction to Compiler Construction with UNIX" by Schreiner & Friedman for more details. CONTENTS: lex rules - "@(#) readcgraph.l (Yale) version 1.1 2/23/91" screen() DATE: Aug 07, 1988 - need to add SccsId in comments due to yacc REVISIONS: Oct 6, 1988 - fixed sign mistake in INTEGER & FLOAT Feb 12, 1989 - added <> to alphanum to handle DEC case. Apr 4, 1989 - added comments over multiple lines. ----------------------------------------------------------------- */ #undef YYLMAX #define YYLMAX 2000 /* comments may be at most 2000 characters */ #define token(x) x /* makes it look like regular lex */ #define END(v) (v-1 + sizeof(v) / sizeof( v[0] ) ) /* for table lookup */ #define PADTOKENOFFSET(v) ( &(v[6]) ) /* 6 because 6 pad tokens */ static INT screen() ; static INT check_line_count() ; # define YYNEWLINE 10 yylex(){ int nstr; extern int yyprevious; while((nstr = yylook()) >= 0) yyfussy: switch(nstr){ case 0: if(yywrap()) return(0); break; case 1: { /* C-style comments over multiple lines */ check_line_count(yytext) ; } break; case 2: { /* convert to an integer */ yylval.ival = atoi( yytext ) ; return (INTEGER); } break; case 3: { /* convert to an integer */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 4: { /* convert to an integer */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 5: { return( screen() ) ; } break; case 6: { line_countS++;} break; case 7: { return(COLON) ; } break; case 8: ; break; case 9: { return( token(yytext[0]) ) ;} break; case -1: break; default: fprintf(yyout,"bad switch yylook %d",nstr); } return(0); } /* end of yylex */ /* reserved word screener */ /* ----------------------------------------------------------------- The following is table of the reserved words - Table must be in alphabetical order for binary search to work properly. ----------------------------------------------------------------- */ static struct rw_table { /* reserved word table */ char *rw_name ; /* pattern */ INT rw_yylex ; /* lex token number */ } rwtable[] = { "HnotV", token(HNOTV), "adj", token(ADJ), "b", token(B), "cap", token(CAP), "l", token(L), "lb", token(LB), "len", token(LEN), "node", token(NODE), "numedges", token(NUMEDGES), "numnodes", token(NUMNODES), "r", token(R), "rt", token(RT), "t", token(T), "x", token(X), "y", token(Y) } ; static INT screen() { INT c ; char *Ystrclone() ; struct rw_table *low = rwtable, /* ptr to beginning */ *mid , *high = END(rwtable) ; /* ptr to end */ /* binary search to look thru table to find pattern match */ while( low <= high){ mid = low + (high-low) / 2 ; if( (c = strcmp(mid->rw_name, yytext) ) == STRINGEQ){ return( mid->rw_yylex ) ; /* return token number */ } else if( c < 0 ){ low = mid + 1 ; } else { high = mid - 1 ; } } /* at this point we haven't found a match so we have a string */ /* save the string by making copy */ yylval.string = Ystrclone( yytext ) ; return (STRING); } /* end screen function */ static INT check_line_count( s ) char *s ; { if( s ){ if( strlen(s) >= YYLMAX ){ sprintf(YmsgG, "comment beginning at line %d ",line_countS+1 ); M( ERRMSG, "lex", YmsgG ) ; sprintf(YmsgG,"exceeds maximum allowed length:%d chars.\n", YYLMAX ); M( MSG, NULL, YmsgG ) ; setErrorFlag() ; } for( ;*s;s++ ){ if( *s == '\n'){ line_countS++; } } } } /* end check_line_count */ int yyvstop[] ={ 0, 8, 0, 8, 0, 9, 0, 8, 9, 0, 6, 0, 5, 9, 0, 9, 0, 9, 0, 2, 9, 0, 7, 9, 0, 8, 0, 5, 0, 2, 0, 3, 5, 0, 2, 0, 3, 0, 5, 0, 1, 0, 4, 5, 0, 4, 0, 1, 0, 0}; # define YYTYPE unsigned char struct yywork { YYTYPE verify, advance; } yycrank[] ={ 0,0, 0,0, 1,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,4, 1,5, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 4,11, 1,6, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,3, 1,7, 8,14, 0,0, 1,6, 1,8, 1,9, 13,17, 18,18, 23,29, 24,30, 29,23, 0,0, 0,0, 0,0, 0,0, 1,10, 0,0, 1,3, 6,12, 6,12, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 0,0, 0,0, 6,12, 0,0, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 0,0, 0,0, 6,12, 0,0, 6,12, 0,0, 0,0, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 0,0, 0,0, 0,0, 0,0, 6,12, 0,0, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 0,0, 6,12, 7,13, 7,13, 7,13, 7,13, 7,13, 7,13, 7,13, 7,13, 7,13, 7,13, 9,12, 9,12, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 9,15, 0,0, 9,16, 9,16, 9,16, 9,16, 9,16, 9,16, 9,16, 9,16, 9,16, 9,16, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 0,0, 0,0, 0,0, 0,0, 9,12, 0,0, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 9,12, 14,18, 9,12, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 14,18, 14,18, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 26,28, 26,28, 26,28, 26,28, 26,28, 26,28, 26,28, 26,28, 26,28, 26,28, 0,0, 15,21, 0,0, 0,0, 14,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 14,19, 14,18, 0,0, 0,0, 14,18, 14,20, 14,18, 0,0, 0,0, 0,0, 0,0, 19,23, 0,0, 0,0, 0,0, 0,0, 14,18, 0,0, 14,18, 19,23, 19,23, 0,0, 15,21, 0,0, 0,0, 0,0, 0,0, 14,18, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 19,23, 0,0, 0,0, 0,0, 17,22, 0,0, 0,0, 19,24, 19,23, 0,0, 0,0, 19,23, 19,25, 19,23, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 19,23, 0,0, 19,23, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 21,26, 19,23, 21,26, 17,22, 0,0, 21,27, 21,27, 21,27, 21,27, 21,27, 21,27, 21,27, 21,27, 21,27, 21,27, 22,26, 0,0, 22,26, 0,0, 0,0, 22,28, 22,28, 22,28, 22,28, 22,28, 22,28, 22,28, 22,28, 22,28, 22,28, 27,27, 27,27, 27,27, 27,27, 27,27, 27,27, 27,27, 27,27, 27,27, 27,27, 0,0, 0,0, 0,0, 0,0}; struct yysvf yysvec[] ={ 0, 0, 0, yycrank+-1, 0, yyvstop+1, yycrank+0, yysvec+1, yyvstop+3, yycrank+0, 0, yyvstop+5, yycrank+3, 0, yyvstop+7, yycrank+0, 0, yyvstop+10, yycrank+27, 0, yyvstop+12, yycrank+104, 0, yyvstop+15, yycrank+3, 0, yyvstop+17, yycrank+127, 0, yyvstop+19, yycrank+0, 0, yyvstop+22, yycrank+0, yysvec+4, yyvstop+25, yycrank+0, yysvec+6, yyvstop+27, yycrank+4, yysvec+7, yyvstop+29, yycrank+-249, 0, 0, yycrank+212, yysvec+6, yyvstop+31, yycrank+0, yysvec+9, yyvstop+34, yycrank+271, 0, yyvstop+36, yycrank+-4, yysvec+14, 0, yycrank+-301, 0, 0, yycrank+0, yysvec+14, 0, yycrank+326, yysvec+6, yyvstop+38, yycrank+341, 0, 0, yycrank+-5, yysvec+14, 0, yycrank+-6, yysvec+14, 0, yycrank+0, 0, yyvstop+40, yycrank+222, 0, 0, yycrank+351, yysvec+6, yyvstop+42, yycrank+0, yysvec+26, yyvstop+45, yycrank+7, 0, 0, yycrank+0, yysvec+29, yyvstop+47, 0, 0, 0}; struct yywork *yytop = yycrank+408; struct yysvf *yybgin = yysvec+1; char yymatch[] ={ 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 011 ,01 ,01 ,'#' ,'#' ,01 ,01 ,01 , 01 ,01 ,'*' ,'+' ,01 ,'+' ,'.' ,'/' , '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , '0' ,'0' ,':' ,01 ,'<' ,01 ,'<' ,01 , 01 ,'#' ,'#' ,'#' ,'#' ,'E' ,'#' ,'#' , '#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , '#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , '#' ,'#' ,'#' ,01 ,01 ,01 ,01 ,'#' , 01 ,'#' ,'#' ,'#' ,'#' ,'E' ,'#' ,'#' , '#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , '#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' ,'#' , '#' ,'#' ,'#' ,01 ,'#' ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 0}; char yyextra[] ={ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0}; /* ncform 4.1 83/08/11 */ int yylineno =1; # define YYU(x) x # define NLSTATE yyprevious=YYNEWLINE char yytext[YYLMAX]; struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; char yysbuf[YYLMAX]; char *yysptr = yysbuf; int *yyfnd; extern struct yysvf *yyestate; int yyprevious = YYNEWLINE; yylook(){ register struct yysvf *yystate, **lsp; register struct yywork *yyt; struct yysvf *yyz; int yych; struct yywork *yyr; # ifdef LEXDEBUG int debug; # endif char *yylastch; #ifdef linux if (yyin == NULL) yyin = stdin; if (yyout == NULL) yyout = stdout; #endif /* start off machines */ # ifdef LEXDEBUG debug = 0; # endif if (!yymorfg) yylastch = yytext; else { yymorfg=0; yylastch = yytext+yyleng; } for(;;){ lsp = yylstate; yyestate = yystate = yybgin; if (yyprevious==YYNEWLINE) yystate++; for (;;){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); # endif yyt = yystate->yystoff; if(yyt == yycrank){ /* may not be any transitions */ yyz = yystate->yyother; if(yyz == 0)break; if(yyz->yystoff == yycrank)break; } *yylastch++ = yych = input(); tryagain: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"unsigned char "); allprint(yych); putchar('\n'); } # endif yyr = yyt; if ( (long)yyt > (long)yycrank){ yyt = yyr + yych; if (yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } # ifdef YYOPTIM else if((long)yyt < (long)yycrank) { /* r < yycrank */ yyt = yyr = yycrank+(yycrank-yyt); # ifdef LEXDEBUG if(debug)fprintf(yyout,"compressed state\n"); # endif yyt = yyt + yych; if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } yyt = yyr + YYU(yymatch[yych]); # ifdef LEXDEBUG if(debug){ fprintf(yyout,"try fall back character "); allprint(YYU(yymatch[yych])); putchar('\n'); } # endif if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transition */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); # endif goto tryagain; } # endif else {unput(*--yylastch);break;} contin: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"state %d char ",yystate-yysvec-1); allprint(yych); putchar('\n'); } # endif ; } # ifdef LEXDEBUG if(debug){ fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); allprint(yych); putchar('\n'); } # endif while (lsp-- > yylstate){ *yylastch-- = 0; if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ yyolsp = lsp; if(yyextra[*yyfnd]){ /* must backup */ while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ lsp--; unput(*yylastch--); } } yyprevious = YYU(*yylastch); yylsp = lsp; yyleng = yylastch-yytext+1; yytext[yyleng] = 0; # ifdef LEXDEBUG if(debug){ fprintf(yyout,"\nmatch "); sprint(yytext); fprintf(yyout," action %d\n",*yyfnd); } # endif return(*yyfnd++); } unput(*yylastch); } if (yytext[0] == 0 /* && feof(yyin) */) { yysptr=yysbuf; return(0); } yyprevious = yytext[0] = input(); if (yyprevious>0) output(yyprevious); yylastch=yytext; # ifdef LEXDEBUG if(debug)putchar('\n'); # endif } } yyback(p, m) int *p; { if (p==0) return(0); while (*p) { if (*p++ == m) return(1); } return(0); } /* the following are only used in the lex library */ yyinput(){ #ifdef linux if (yyin == NULL) yyin = stdin; #endif return(input()); } yyoutput(c) int c; { #ifdef linux if (yyout == NULL) yyout = stdout; #endif output(c); } yyunput(c) int c; { unput(c); } graywolf-0.1.4+20170307gite1bf319/src/mc_compact/readtiles.c000066400000000000000000000423321305746555600230040ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley) 01/20/90"; #endif #define YYBYACC 1 /* ----------------------------------------------------------------- FILE: readtiles.c <- readtiles.y <- readtiles.l DESCRIPTION:This file contains the grammar (BNF) for reading the positions of the tiles from placement routine. The rules for lex are in readtiles.l. The grammar for yacc is in readtiles.y. The output of yacc (y.tab.c) is renamed to readtiles.c CONTENTS: readtiles() yyerror(s) char *s; yywrap() Note:readtiles.c will also include the yacc parser. DATE: Apr 7, 1988 REVISIONS: Apr 20, 1989 - original coding. Apr 30, 1989 - added library change and added partition case for compaction. May 3, 1989 - changed to Y prefixes. Mon May 6 22:35:12 EDT 1991 - added offset keyword. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) readtiles.y version 7.2 5/6/91" ; #endif #include #include #include /* use message routines for errors. */ #include /* file opening insert file. */ #include /* use debug utilities. */ #undef REJECT /* undefine TWMC macro for lex's version */ #define YYDEBUG 1 /* condition compile for yacc debug */ static int line_countS ; typedef union { INT ival ; char *string ; double fval ; } YYSTYPE; #define INTEGER 257 #define STRING 258 #define FLOAT 259 #define CELL 260 #define STDCELL 261 #define NUMTILES 262 #define NUMCELLS 263 #define OFFSET 264 #define L 265 #define R 266 #define T 267 #define B 268 #define COLON 269 #define X 270 #define Y 271 #define YYERRCODE 256 short yylhs[] = { -1, 0, 1, 2, 2, 3, 4, 4, 5, 5, 6, }; short yylen[] = { 2, 2, 6, 1, 2, 2, 12, 12, 1, 2, 12, }; short yydefred[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 8, 0, 0, 0, 0, 9, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 10, }; short yydgoto[] = { 2, 3, 7, 8, 9, 15, 16, }; short yysindex[] = { -262, -265, 0, -258, -252, -251, -250, -258, 0, -257, -254, -260, -259, 0, -256, -257, 0, -255, -253, -249, -245, 0, -242, -240, -239, -247, 0, -248, -246, -243, -241, -238, -236, -235, -233, -234, -237, -232, -231, -230, -229, -228, -227, -224, -226, -222, -221, -225, 0, 0, -220, 0, }; short yyrindex[] = { 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; short yygindex[] = { 0, 0, 0, 36, 0, 0, 30, }; #define YYTABLESIZE 262 short yytable[] = { 1, 5, 5, 6, 4, 10, 11, 12, 14, 17, 18, 19, 25, 20, 22, 26, 23, 27, 28, 29, 24, 35, 36, 30, 37, 31, 32, 39, 33, 44, 45, 34, 40, 46, 38, 48, 49, 51, 41, 42, 43, 47, 1, 13, 50, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, }; short yycheck[] = { 262, 0, 260, 261, 269, 257, 257, 257, 265, 263, 270, 270, 257, 269, 269, 257, 269, 257, 257, 266, 269, 257, 257, 271, 257, 271, 269, 264, 269, 257, 257, 269, 264, 257, 268, 257, 257, 257, 269, 269, 269, 267, 0, 7, 269, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 260, 261, }; #define YYFINAL 2 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 271 #if YYDEBUG char *yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"INTEGER","STRING","FLOAT","CELL", "STDCELL","NUMTILES","NUMCELLS","OFFSET","L","R","T","B","COLON","X","Y", }; char *yyrule[] = { "$accept : start_file", "start_file : tile_info cell_list", "tile_info : NUMTILES COLON INTEGER NUMCELLS COLON INTEGER", "cell_list : cell", "cell_list : cell_list cell", "cell : cell_info tile_list", "cell_info : CELL INTEGER X COLON INTEGER Y COLON INTEGER OFFSET COLON INTEGER INTEGER", "cell_info : STDCELL INTEGER X COLON INTEGER Y COLON INTEGER OFFSET COLON INTEGER INTEGER", "tile_list : tile", "tile_list : tile_list tile", "tile : L COLON INTEGER R COLON INTEGER B COLON INTEGER T COLON INTEGER", }; #endif #define yyclearin (yychar=(-1)) #define yyerrok (yyerrflag=0) #ifdef YYSTACKSIZE #ifndef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #endif #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 500 #define YYMAXDEPTH 500 #endif #endif int yydebug; int yynerrs; int yyerrflag; int yychar; short *yyssp; YYSTYPE *yyvsp; YYSTYPE yyval; YYSTYPE yylval; short yyss[YYSTACKSIZE]; YYSTYPE yyvs[YYSTACKSIZE]; #define yystacksize YYSTACKSIZE #include "readtiles_l.h" /* add readtiles_l.h for debug purposes */ /* ********************* #include "readtiles_l.h" *******************/ /* ********************* #include "readtiles_l.h" *******************/ readtiles() { char filename[LRECL] ; #ifdef YYDEBUG extern int yydebug ; yydebug = FALSE ; #endif sprintf( filename, "%s.mvio", cktNameG ) ; yyin = TWOPEN( filename, "r", ABORT ) ; line_countS = 0 ; /* parse input file using yacc */ yyparse(); process_tiles() ; TWCLOSE( yyin ) ; } /* end readtiles */ yyerror(s) char *s; { sprintf(YmsgG,"problem reading %s.mvio:", cktNameG ); M( ERRMSG, "yacc", YmsgG ) ; sprintf(YmsgG, " line %d near '%s' : %s\n" , line_countS+1, yytext, s ); M( MSG,"yacc", YmsgG ) ; setErrorFlag() ; } yywrap() { return(1); } #define YYABORT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int yyparse() { register int yym, yyn, yystate; #if YYDEBUG register char *yys; extern char *getenv(); if (yys = getenv("YYDEBUG")) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = (-1); yyssp = yyss; yyvsp = yyvs; *yyssp = yystate = 0; yyloop: if (yyn = yydefred[yystate]) goto yyreduce; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, shifting to state %d\n", yystate, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; #ifdef lint goto yynewerror; #endif yynewerror: #if YYDEBUG { int test_state, i, expect, two_or_more ; char err_msg[BUFSIZ] ; if( yyname[yychar] ){ sprintf( err_msg, "\nsyntax error - found:%s expected:", yyname[yychar] ) ; two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = YYERRCODE+1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if( expect <= YYTABLESIZE && yycheck[expect] == i ){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = YYERRCODE+1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if( expect <= YYTABLESIZE && yycheck[expect] == i ){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } strcat( err_msg, "\n" ) ; yyerror( err_msg ) ; } else { yyerror("syntax error"); } } #else yyerror("syntax error"); #endif #ifdef lint goto yyerrlab; #endif yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, error recovery shifting\ to state %d\n", *yyssp, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("yydebug: error recovery discarding state %d\n", *yyssp); #endif if (yyssp <= yyss) goto yyabort; --yyssp; --yyvsp; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, error recovery discards token %d (%s)\n", yystate, yychar, yys); } #endif yychar = (-1); goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("yydebug: state %d, reducing by rule %d (%s)\n", yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; yyval = yyvsp[1-yym]; switch (yyn) { case 2: { init( yyvsp[-3].ival, yyvsp[0].ival ) ; } break; case 5: { endCell() ; } break; case 6: { initCell( CELLTYPE, yyvsp[-10].ival, yyvsp[-7].ival, yyvsp[-4].ival, yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 7: { initCell( STDCELLTYPE, yyvsp[-10].ival, yyvsp[-7].ival, yyvsp[-4].ival, yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 10: { /* l:-5 r:5 b:-10 t:10 */ addtile( yyvsp[-9].ival, yyvsp[-6].ival, yyvsp[-3].ival, yyvsp[0].ival ) ; } break; } yyssp -= yym; yystate = *yyssp; yyvsp -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state 0 to\ state %d\n", YYFINAL); #endif yystate = YYFINAL; *++yyssp = YYFINAL; *++yyvsp = yyval; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state %d \ to state %d\n", *yyssp, yystate); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate; *++yyvsp = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: return (1); yyaccept: return (0); } graywolf-0.1.4+20170307gite1bf319/src/mc_compact/readtiles_l.h000066400000000000000000000361511305746555600233260ustar00rootroot00000000000000#ifdef linux #include #else # include "stdio.h" #endif #include # define U(x) ((x)&0377) # define NLSTATE yyprevious=YYNEWLINE # define BEGIN yybgin = yysvec + 1 + # define INITIAL 0 # define YYLERR yysvec # define YYSTATE (yyestate-yysvec-1) # define YYOPTIM 1 # define YYLMAX 200 # define output(c) putc(c,yyout) # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} # define yymore() (yymorfg=1) # define ECHO fprintf(yyout, "%s",yytext) # define REJECT { nstr = yyreject(); goto yyfussy;} int yyleng; extern char yytext[]; int yymorfg; extern char *yysptr, yysbuf[]; int yytchar; #ifdef linux FILE *yyin = NULL, *yyout = NULL; #else FILE *yyin ={stdin}, *yyout ={stdout}; #endif extern int yylineno; struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops;}; struct yysvf *yyestate; extern struct yysvf yysvec[], *yybgin; /* ----------------------------------------------------------------- "@(#) readtiles.l version 7.3 5/6/91" FILE: readtiles.l DESCRIPTION:rules for lexical analyzer in readtiles. This lexical analyzer uses a binary search to reduce the size of the f.a. generated by lex. Thanks to Gary Richey who showed me the trick. See chapter 3 of "Introduction to Compiler Construction with UNIX" by Schreiner & Friedman for more details. CONTENTS: lex rules - screen() DATE: Aug 07, 1988 - need to add SccsId in comments due to yacc REVISIONS: Oct 6, 1988 - fixed sign mistake in INTEGER & FLOAT Feb 12, 1989 - added <> to alphanum to handle DEC case. Apr 4, 1989 - added comments over multiple lines. Apr 18, 1989 - added to compactor. Apr 30, 1989 - modified STDCELL type Thu Apr 18 00:58:28 EDT 1991 - new version featuring constraint compaction. Mon May 6 22:35:12 EDT 1991 - added offset keyword. ----------------------------------------------------------------- */ #undef YYLMAX #define YYLMAX 2000 /* comments may be at most 2000 characters */ #define token(x) x /* makes it look like regular lex */ #define END(v) (v-1 + sizeof(v) / sizeof( v[0] ) ) /* for table lookup */ static int screen() ; static int check_line_count() ; # define YYNEWLINE 10 yylex(){ int nstr; extern int yyprevious; while((nstr = yylook()) >= 0) yyfussy: switch(nstr){ case 0: if(yywrap()) return(0); break; case 1: { /* C-style comments over multiple lines */ check_line_count(yytext) ; } break; case 2: { /* convert to an integer */ yylval.ival = atoi( yytext ) ; return (INTEGER); } break; case 3: { /* convert to an integer */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 4: { /* convert to an integer */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 5: { return(COLON); } break; case 6: { return( screen() ) ; } break; case 7: { line_countS++;} break; case 8: ; break; case 9: { return( token(yytext[0]) ) ;} break; case -1: break; default: fprintf(yyout,"bad switch yylook %d",nstr); } return(0); } /* end of yylex */ /* reserved word screener */ /* ----------------------------------------------------------------- The following is table of the reserved words - Table must be in alphabetical order for binary search to work properly. ----------------------------------------------------------------- */ static struct rw_table { /* reserved word table */ char *rw_name ; /* pattern */ int rw_yylex ; /* lex token number */ } rwtable[] = { "b", token(B), "cell", token(CELL), "l", token(L), "numcells", token(NUMCELLS), "numtiles", token(NUMTILES), "offset", token(OFFSET), "r", token(R), "stdcell", token(STDCELL), "t", token(T), "x", token(X), "y", token(Y) } ; static int screen() { int c ; struct rw_table *low = rwtable, /* ptr to beginning */ *mid , *high = END(rwtable) ; /* ptr to end */ /* binary search to look thru table to find pattern match */ while( low <= high){ mid = low + (high-low) / 2 ; if( (c = strcmp(mid->rw_name, yytext) ) == STRINGEQ){ return( mid->rw_yylex ) ; /* return token number */ } else if( c < 0 ){ low = mid + 1 ; } else { high = mid - 1 ; } } /* at this point we haven't found a match so we have a string */ /* save the string by making copy */ yylval.string = (char *) Ystrclone( yytext ) ; return (STRING); } /* end screen function */ static int check_line_count( s ) char *s ; { if( s ){ if( strlen(s) >= YYLMAX ){ sprintf(YmsgG,"comment beginning at line %d ",line_countS+1 ); M( ERRMSG, "lex", YmsgG ) ; sprintf(YmsgG,"exceeds maximum allowed length:%d chars.\n", YYLMAX ); M( MSG, NULL, YmsgG ) ; setErrorFlag() ; } for( ;*s;s++ ){ if( *s == '\n'){ line_countS++; } } } } /* end check_line_count */ int yyvstop[] ={ 0, 8, 0, 8, 0, 9, 0, 8, 9, 0, 7, 0, 6, 9, 0, 6, 9, 0, 6, 9, 0, 2, 9, 0, 5, 9, 0, 8, 0, 6, 0, 6, 0, 2, 6, 0, 6, 0, 3, 6, 0, 2, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 3, 6, 0, 4, 6, 0, 6, 0, 6, 0, 1, 6, 0, 6, 0, 1, 0, 6, 0, 1, 6, 0, 1, 0, 0}; # define YYTYPE unsigned char struct yywork { YYTYPE verify, advance; } yycrank[] ={ 0,0, 0,0, 1,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,4, 1,5, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 1,7, 8,15, 0,0, 1,6, 1,8, 1,9, 20,20, 28,35, 29,36, 34,27, 35,28, 7,13, 36,28, 7,13, 0,0, 1,10, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 1,6, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 0,0, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 9,16, 0,0, 9,17, 9,17, 9,17, 9,17, 9,17, 9,17, 9,17, 9,17, 9,17, 9,17, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 13,13, 0,0, 13,13, 0,0, 9,18, 13,14, 13,14, 13,14, 13,14, 13,14, 13,14, 13,14, 13,14, 13,14, 13,14, 14,16, 0,0, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 0,0, 0,0, 0,0, 0,0, 15,19, 0,0, 0,0, 0,0, 0,0, 9,18, 0,0, 14,18, 15,19, 15,19, 16,23, 0,0, 16,24, 16,24, 16,24, 16,24, 16,24, 16,24, 16,24, 16,24, 16,24, 16,24, 25,25, 25,25, 25,25, 25,25, 25,25, 25,25, 25,25, 25,25, 25,25, 25,25, 15,20, 16,18, 0,0, 0,0, 0,0, 0,0, 0,0, 14,18, 0,0, 15,21, 15,20, 0,0, 0,0, 15,20, 15,22, 15,20, 0,0, 19,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 15,19, 19,26, 19,19, 0,0, 0,0, 19,19, 19,19, 19,19, 16,18, 0,0, 17,16, 15,20, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 19,19, 18,18, 0,0, 18,18, 0,0, 17,18, 18,25, 18,25, 18,25, 18,25, 18,25, 18,25, 18,25, 18,25, 18,25, 18,25, 21,27, 26,27, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 21,27, 21,27, 26,32, 26,27, 0,0, 0,0, 26,27, 26,33, 26,27, 0,0, 0,0, 0,0, 23,23, 17,18, 23,31, 23,31, 23,31, 23,31, 23,31, 23,31, 23,31, 23,31, 23,31, 23,31, 21,28, 0,0, 0,0, 0,0, 0,0, 26,27, 0,0, 0,0, 27,19, 21,29, 21,28, 23,18, 0,0, 21,28, 21,30, 21,28, 0,0, 27,26, 27,19, 0,0, 0,0, 27,19, 27,34, 27,19, 0,0, 21,27, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 21,28, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 23,18, 27,19, 0,0, 0,0, 24,18, 31,31, 31,31, 31,31, 31,31, 31,31, 31,31, 31,31, 31,31, 31,31, 31,31, 32,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 32,26, 32,19, 31,18, 0,0, 32,19, 32,37, 32,19, 0,0, 0,0, 0,0, 0,0, 0,0, 24,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 32,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 31,18, 0,0, 0,0, 0,0}; struct yysvf yysvec[] ={ 0, 0, 0, yycrank+-1, 0, yyvstop+1, yycrank+0, yysvec+1, yyvstop+3, yycrank+0, 0, yyvstop+5, yycrank+3, 0, yyvstop+7, yycrank+0, 0, yyvstop+10, yycrank+38, 0, yyvstop+12, yycrank+12, yysvec+6, yyvstop+15, yycrank+3, yysvec+6, yyvstop+18, yycrank+119, yysvec+6, yyvstop+21, yycrank+0, 0, yyvstop+24, yycrank+0, yysvec+4, yyvstop+27, yycrank+0, yysvec+6, yyvstop+29, yycrank+141, yysvec+6, yyvstop+31, yycrank+153, yysvec+6, yyvstop+33, yycrank+-214, 0, yyvstop+36, yycrank+179, yysvec+6, yyvstop+38, yycrank+236, yysvec+6, yyvstop+41, yycrank+258, yysvec+6, yyvstop+43, yycrank+-231, yysvec+15, 0, yycrank+-3, yysvec+15, yyvstop+45, yycrank+-315, 0, yyvstop+47, yycrank+0, yysvec+15, yyvstop+49, yycrank+290, yysvec+6, yyvstop+51, yycrank+326, yysvec+6, yyvstop+53, yycrank+189, yysvec+6, yyvstop+56, yycrank+-284, yysvec+21, 0, yycrank+-323, yysvec+15, 0, yycrank+-4, yysvec+15, yyvstop+59, yycrank+-5, yysvec+15, yyvstop+61, yycrank+0, yysvec+6, yyvstop+63, yycrank+348, yysvec+6, yyvstop+66, yycrank+-373, yysvec+15, 0, yycrank+0, 0, yyvstop+68, yycrank+6, 0, 0, yycrank+7, yysvec+6, yyvstop+70, yycrank+9, yysvec+6, yyvstop+72, yycrank+0, yysvec+34, yyvstop+75, 0, 0, 0}; struct yywork *yytop = yycrank+449; struct yysvf *yybgin = yysvec+1; char yymatch[] ={ 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 011 ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'*' ,'+' ,'!' ,'+' ,'.' ,'/' , '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , '0' ,'0' ,':' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 0}; char yyextra[] ={ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0}; /* ncform 4.1 83/08/11 */ int yylineno =1; # define YYU(x) x # define NLSTATE yyprevious=YYNEWLINE char yytext[YYLMAX]; struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; char yysbuf[YYLMAX]; char *yysptr = yysbuf; int *yyfnd; extern struct yysvf *yyestate; int yyprevious = YYNEWLINE; yylook(){ register struct yysvf *yystate, **lsp; register struct yywork *yyt; struct yysvf *yyz; int yych; struct yywork *yyr; # ifdef LEXDEBUG int debug; # endif char *yylastch; #ifdef linux if (yyin == NULL) yyin = stdin; if (yyout == NULL) yyout = stdout; #endif /* start off machines */ # ifdef LEXDEBUG debug = 0; # endif if (!yymorfg) yylastch = yytext; else { yymorfg=0; yylastch = yytext+yyleng; } for(;;){ lsp = yylstate; yyestate = yystate = yybgin; if (yyprevious==YYNEWLINE) yystate++; for (;;){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); # endif yyt = yystate->yystoff; if(yyt == yycrank){ /* may not be any transitions */ yyz = yystate->yyother; if(yyz == 0)break; if(yyz->yystoff == yycrank)break; } *yylastch++ = yych = input(); tryagain: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"unsigned char "); allprint(yych); putchar('\n'); } # endif yyr = yyt; if ( (long)yyt > (long)yycrank){ yyt = yyr + yych; if (yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } # ifdef YYOPTIM else if((long)yyt < (long)yycrank) { /* r < yycrank */ yyt = yyr = yycrank+(yycrank-yyt); # ifdef LEXDEBUG if(debug)fprintf(yyout,"compressed state\n"); # endif yyt = yyt + yych; if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } yyt = yyr + YYU(yymatch[yych]); # ifdef LEXDEBUG if(debug){ fprintf(yyout,"try fall back character "); allprint(YYU(yymatch[yych])); putchar('\n'); } # endif if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transition */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); # endif goto tryagain; } # endif else {unput(*--yylastch);break;} contin: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"state %d char ",yystate-yysvec-1); allprint(yych); putchar('\n'); } # endif ; } # ifdef LEXDEBUG if(debug){ fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); allprint(yych); putchar('\n'); } # endif while (lsp-- > yylstate){ *yylastch-- = 0; if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ yyolsp = lsp; if(yyextra[*yyfnd]){ /* must backup */ while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ lsp--; unput(*yylastch--); } } yyprevious = YYU(*yylastch); yylsp = lsp; yyleng = yylastch-yytext+1; yytext[yyleng] = 0; # ifdef LEXDEBUG if(debug){ fprintf(yyout,"\nmatch "); sprint(yytext); fprintf(yyout," action %d\n",*yyfnd); } # endif return(*yyfnd++); } unput(*yylastch); } if (yytext[0] == 0 /* && feof(yyin) */) { yysptr=yysbuf; return(0); } yyprevious = yytext[0] = input(); if (yyprevious>0) output(yyprevious); yylastch=yytext; # ifdef LEXDEBUG if(debug)putchar('\n'); # endif } } yyback(p, m) int *p; { if (p==0) return(0); while (*p) { if (*p++ == m) return(1); } return(0); } /* the following are only used in the lex library */ yyinput(){ #ifdef linux if (yyin == NULL) yyin = stdin; #endif return(input()); } yyoutput(c) int c; { #ifdef linux if (yyout == NULL) yyout = stdout; #endif output(c); } yyunput(c) int c; { unput(c); } graywolf-0.1.4+20170307gite1bf319/src/mc_compact/stdmacro.c000066400000000000000000000421571305746555600226510ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: stdmacro.c DESCRIPTION:This file contains algorithm for removing violations of stdcell macro placement. CONTENTS: DATE: Apr 20, 1989 - original coding. REVISIONS: May 3, 1989 - changed to Y prefixes. May 18, 1989 - added extended source test to insure tests are complete. Jun 21, 1989 - changed swap to exchange only x positions. May 4, 1990 - updated the functionality of Yset_init. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) stdmacro.c version 7.3 2/15/91" ; #endif #include #include #include /* --------------------------------------------------------------- state input valid next state H1 H yes H1 H1 S yes S1 S1 H yes H2 S1 S yes S1 H2 H yes H2 H2 S no -- --------------------------------------------------------------- */ #define E 0 #define H1 1 #define S1 2 #define H2 3 typedef struct { int node ; /* node number */ int from_left ; /* distance from left edge of bar */ int from_right ; /* distance from right edge of bar */ int left_neighbor ; /* left swapping neighbor */ int right_neighbor ; /* right swapping neighbor */ BOOL type ; /* tile type */ BOOL candidate ; /* whether it is an exchange candidate */ COMPACTPTR ptr ; /* pointer to tile record */ } SELECTBOX, *SELECTPTR ; static int nextStateS[4][2] = { { E, E }, /* error state */ { H1, S1 }, /* state H1 */ { H2, S1 }, /* state S1 */ { H2, E }, /* state H2 */ } ; static YSETPTR nodeSetS ; /* these two implement set of tile nodes */ static SELECTPTR *stackArrayS ; /* members of an invalid path */ static int sortbydist(); partition_compact() { ERRORPTR violations, buildXGraph() ; int i ; /* --------------------------------------------------------------- Algorithm: While partition violations remain do First remove overlap violations - use compact. Next build xgraph to show adjacencies in x direction. Find longest path in x direction. At this point each node will be labeled with a allowed window. We use this for determining cell moves if violation is detected. Next perform a depth-first search to check violations. In a single path between source and sink we must only have H* S* H* patterns where H respresents hardcell, S represents softcells and * represents zero or more occurences. Note: we traverse the critical path first since it may change topology the most. If a violation is detected, swap with partner in violation if possible, noting which direction cell will travel. Mark cell as moved. else no violations break loop. od. We now will be able to compact in a normal fashion since topology is now fixed. --------------------------------------------------------------- */ /* initialization */ nodeSetS = Yset_init( 0, last_tileG ) ; /* allocate stackArray for fixing problems */ stackArrayS = (SELECTPTR *) Ysafe_malloc( (numtilesG+2) * sizeof(SELECTBOX) ) ; for( i = 0; i <= last_tileG ; i++ ){ stackArrayS[i] = (SELECTPTR) Ysafe_malloc( sizeof(SELECTBOX) ) ; } /* end initialization */ /* perform constraint satisfaction */ while( TRUE ){ /* first remove overlap violations only */ remove_violations() ; buildXGraph() ; /* G( ) is NOGRAPHICS conditional compile */ G( if( graphicsG && TWinterupt() ) ){ G( process_graphics() ) ; } G( draw_the_data() ) ; /* build the critical path in x direction */ longestxPath() ; /* do depth first search removing violations */ /* returns true when no violations remain */ if( depth_first_search() ){ break ; } /* free graph so we can start over again */ freeGraph(XFORWARD ) ; freeGraph(XBACKWARD ) ; } /* end loop */ /* free graph so we can start over again */ freeGraph(XFORWARD ) ; freeGraph(XBACKWARD ) ; M(MSG,NULL,"Constraints satisfied before compaction...\n") ; /* compact to make things fit better */ compact() ; /* verify constraints second time to guarantee correctness */ while( TRUE ){ /* first remove overlap violations only */ remove_violations() ; buildXGraph() ; /* G( ) is NOGRAPHICS conditional compile */ G( if( graphicsG && TWinterupt() ) ){ G( process_graphics() ) ; } G( draw_the_data() ) ; /* build the critical path in x direction */ longestxPath() ; /* do depth first search removing violations */ /* returns true when no violations remain */ if( depth_first_search() ){ break ; } /* free graph so we can start over again */ freeGraph(XFORWARD ) ; freeGraph(XBACKWARD ) ; } /* end loop */ M(MSG,NULL,"Constraints satisfied after compaction...\n") ; /* show the results */ G( draw_the_data() ) ; } /* end partition_compact */ BOOL depth_first_search() { /* ------------------------------------------------------------ Algorithm: initialize all nodes active. initialize all edges unvisited. while an active node exist do node = source node. while node != sink node do pick min node that is active. mark edge as visited. mark from field so we can backtrack. if all edges of from node are marked, node becomes inactive. od. now at sink node verify H* S* H* constraints by backtracking. if error swap cells noting direction and return FALSE. od. when we reach this point, no errors remain we are done and so return TRUE. -------------------------------------------------------------*/ int i ; /* counter */ int source ; /* effective source node */ int sink ; /* sink tile */ int activeNodes ; /* number of active nodes */ int node ; /* current node */ int nextNode ; /* next candidate tile in path */ int currentValue ; /* find longest path first */ int state ; /* current state for error check */ BOOL inactive ; BOOL curType ; /* current type of macro */ COMPACTPTR tptr ; /* tile pointer */ COMPACTPTR tile ; /* tile pointer */ ECOMPBOXPTR ptr ; /* edge pointer */ YSETLISTPTR setptr ; /* stack of nodes in sorted order */ activeNodes = numtilesG + 1 ; sink = numtilesG + 1 ; Yset_empty( nodeSetS ) ; /* mark all the nodes active */ /* initialize all the edges of the graph to FALSE */ for( i=numtilesG; i >= 0; i-- ){ tptr = tileNodeG[i] ; tptr->moved = FALSE ; /* use moved field as marker */ for( ptr = tptr->xadjF; ptr ; ptr = ptr->next ){ ptr->marked = FALSE ; } /* since Yset_add keeps a stack add in reverse order */ Yset_add( nodeSetS, i ) ; } /* end initialization */ while( activeNodes > 0 ){ /* find effective source node - nodes are in sorted order */ /* from left to right. Pop one from the stack. */ do { setptr = Yset_enumerate( nodeSetS ) ; source = setptr->node ; tptr = tileNodeG[source] ; if( tptr->moved ){ Yset_delete( nodeSetS, source ) ; /* avoid this node it is marked already */ } else { break ; /* we found an unmarked node */ } } while( setptr ) ; node = source ; for( ; node != sink; node = nextNode ){ tptr = tileNodeG[node] ; /* pick min node that is active */ nextNode = 0 ; /* initialize */ currentValue = INT_MAX ; for( ptr = tptr->xadjF; ptr ; ptr = ptr->next ){ if( ptr->marked ){ continue ; } tile = tileNodeG[ptr->node] ; if( tile->xvalueMin < currentValue ){ currentValue = tile->xvalueMin ; nextNode = ptr->node ; } } if( nextNode == 0 ){ break ; /* at end of the line exit loop */ } /* mark edge as visited */ /* check to see if all edges are marked */ inactive = TRUE ; for( ptr = tptr->xadjF; ptr ; ptr = ptr->next ){ if( ptr->node == nextNode ){ ptr->marked = TRUE ; } if( !(ptr->marked) ){ inactive = FALSE ; } } if( inactive ){ activeNodes-- ; Yset_delete( nodeSetS, node ) ; tptr->moved = TRUE ; } /* make tracks */ tileNodeG[nextNode]->pathx = node ; } /* end for loop */ sink = node ; source = SOURCE ; /* now we need to follow the source all the way back to proper */ /* source to verify complete path */ while( node != source ){ tptr = tileNodeG[node] ; curType = tptr->type ; ptr = tptr->xadjB; nextNode = ptr->node ; for( ; ptr ; ptr = ptr->next ){ if( tileNodeG[ptr->node]->type != curType ){ nextNode = ptr->node ; break ; } } /* if we don't find any different one take first one */ /* make tracks */ tileNodeG[node]->pathx = nextNode ; node = nextNode ; /* update node */ } /* end find beginning */ /* now at sink node verify H* S* H* constraints */ /* name states as H2* S1* H1* */ state = H1 ; node = sink ; D( "mc_compact/depth_first_search",M( MSG, NULL, "\nPath:\n" ) ) ; while( node != source ){ tptr = tileNodeG[node] ; /* use finite automata to check validity of constraints */ state = nextStateS[state][tptr->type] ; /* ************** HOW TO FIX THINGS UP ***************** */ if( state == E ){ /* error */ D( "mc_compact/depth_first_search", sprintf( YmsgG,"Topology error with tile:%d\n", node ) ) ; D( "mc_compact/depth_first_search", M( MSG, NULL, YmsgG ) ) ; remove_problem( source, sink ) ; return( FALSE ) ; /* we aren't done yet */ } /* ************** END HOW TO FIX THINGS UP ************** */ D( "mc_compact/depth_first_search", sprintf( YmsgG," %d\n", node ) ; M( MSG, NULL, YmsgG ) ; ) ; node = tptr->pathx ; } } return( TRUE ) ; /* we are finished */ } /* end depth_first_search */ /* perform the swap of two nodes */ swap_nodes( node1, node2 ) int node1, node2 ; { COMPACTPTR tptr1 ; /* tile pointer */ COMPACTPTR tptr2 ; /* tile pointer */ CELLBOXPTR cptr ; /* cell pointer */ int new_xc1 ; /* new position of node 1 center */ int new_xc2 ; /* new position of node 2 center */ int deltax ; /* change needed to accomplish swap */ int cell ; /* current cell in question */ ASSERT( node1 > 0 && node1 <= numtilesG,"swap_nodes", "node1 out of bounds\n" ) ; ASSERT( node2 > 0 && node2 <= numtilesG,"swap_nodes", "node2 out of bounds\n" ) ; D( "mc_compact/swap_nodes", sprintf( YmsgG, "swapping nodes:%d =><= %d\n", node1, node2 ) ) ; D( "mc_compact/swap_nodes", M( MSG,"swap_node", YmsgG ) ) ; /* swap relative to left side of tiles */ tptr1 = tileNodeG[node1] ; tptr2 = tileNodeG[node2] ; new_xc1 = tptr2->l - tptr1->l_rel ; new_xc2 = tptr1->l - tptr2->l_rel ; /* now swap updating all tiles of cell one */ cell = tptr1->cell ; cptr = cellarrayG[cell] ; deltax = new_xc1 - cptr->xcenter ; update_cell_tiles( cell, deltax, 0 ) ; /* now swap updating all tiles of cell two */ cell = tptr2->cell ; cptr = cellarrayG[cell] ; deltax = new_xc2 - cptr->xcenter ; update_cell_tiles( cell, deltax, 0 ) ; } /* end swap_nodes */ remove_problem( source, sink ) int source, sink ; { int i ; /* temp counter */ int node ; int count ; /* keeps track of size of tile path */ int state ; /* current state */ int sinkX ; /* position of sink */ int sourceX ; /* position of source */ SELECTPTR sptr ; COMPACTPTR tptr ; /* static int sortbydist() ; */ /* how to sort the tiles in path */ /* start over putting state in stackArray */ node = sink ; count = 0 ; while( node != source ){ sptr = stackArrayS[++count] ; tptr = tileNodeG[node] ; sptr->type = tptr->type ; sptr->ptr = tptr ; sptr->node = node ; sptr->from_left = INT_MAX ; sptr->from_right = INT_MAX ; sptr->candidate = TRUE ; node = tptr->pathx ; } /* we have now put error path in array with bounds 1 and count */ /* now invalidate candidancy for H1 nodes at edge of bar*/ /* also calculate the distance from the left edge of bar for */ /* tiles traveling right or those who haven't made up their mind */ state = H1 ; sinkX = tileNodeG[sink]->l ; sourceX = tileNodeG[source]->r ; /* from the right */ for( i = 1; i <= count ; i++ ){ sptr = stackArrayS[i] ; state = nextStateS[state][sptr->ptr->type] ; if( state == H1 ){ sptr->candidate = FALSE ; } else if( sptr->type == CELLTYPE && ( sptr->ptr->direction == NODIRECTION || sptr->ptr->direction == GOINGRIGHT ) ){ sptr->from_right = sinkX - sptr->ptr->l ; } else if( sptr->type == STDCELLTYPE ){ /* these cells are never candidates */ sptr->candidate = FALSE ; } /* update neighbor field */ if( i > 1 ){ /* avoid sink */ sptr->right_neighbor = stackArrayS[i-1]->ptr->node ; } } /* end loop from the right */ /* from the left */ /* do the same as above only from other side */ state = H1 ; for( i = count; i > 0; i-- ){ sptr = stackArrayS[i] ; state = nextStateS[state][sptr->ptr->type] ; if( state == H1 ){ sptr->candidate = FALSE ; } else if( sptr->type == CELLTYPE && ( sptr->ptr->direction == NODIRECTION || sptr->ptr->direction == GOINGLEFT ) ){ sptr->from_left = sptr->ptr->r - sourceX ; } else if( sptr->type == STDCELLTYPE ){ sptr->candidate = FALSE ; } /* update neighbor field */ if( i < count ){ /* avoid sink */ sptr->left_neighbor = stackArrayS[i+1]->ptr->node ; } } /* end loop from the left */ /* now sort tiles in array according to from distance */ Yquicksort( (char *) &(stackArrayS[1]), count, sizeof(SELECTPTR), sortbydist ) ; /* pick the node with the closest distance traveling */ /* the right way already */ for( i = 1; i <= count; i++ ){ sptr = stackArrayS[i] ; if( !sptr->candidate ){ continue ; } if( sptr->from_left < sptr->from_right ){ /* coming from the left */ /* swap with left neighbor */ ASSERT( tileNodeG[sptr->left_neighbor]->type == STDCELLTYPE, NULL,"Logical error\n" ) ; sptr->ptr->direction = GOINGLEFT ; swap_nodes( sptr->node, sptr->left_neighbor ); return( FALSE ) ; /* we aren't done yet */ } else { /* coming from the right */ /* swap with right neighbor */ ASSERT( tileNodeG[sptr->right_neighbor]->type == STDCELLTYPE, NULL,"Logical error\n" ) ; sptr->ptr->direction = GOINGRIGHT ; swap_nodes( sptr->node, sptr->right_neighbor ); return( FALSE ) ; /* we aren't done yet */ } } /* should never reach here - check is for memory problem*/ ASSERT( TRUE, "depth_first_search", "Logic problem" ) ; } /* end remove_problem */ /* sort by valid candidate first then distance left or right */ static int sortbydist( tileA, tileB ) SELECTPTR *tileA , *tileB ; { SELECTPTR t1, t2 ; /* temps to make our life easier */ int min1, min2 ; /* the minimum of the distance for the two tiles */ t1 = *tileA ; t2 = *tileB ; if( t1->candidate != t2->candidate ){ if( t1->candidate == TRUE ){ return( -1 ) ; } else { /* t2 is a candidate */ return( 1 ) ; } } else { /* sort by minimum distance to either side */ min1 = MIN( t1->from_right, t1->from_left ) ; min2 = MIN( t2->from_right, t2->from_left ) ; return( min1 - min2 ) ; } } /* end sortbydist */ graywolf-0.1.4+20170307gite1bf319/src/mc_compact/xcompact.c000066400000000000000000000671011305746555600226470ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: xcompact.c DESCRIPTION:This file contains type declarations for the compaction in the xdirection. CONTENTS: DATE: Apr 8, 1988 REVISIONS: Sep 20, 1988 - removed excess edges from source and sink Oct 29, 1988 - fixed problem with cells being exactly same size as picket and changed picket to doubly-linked list. Nov 7, 1988 - implemented the doubly-linked list correctly. Jan 29, 1989 - changed msg to YmsgG and added \n's. Mar 11, 1989 - fixed argument type bug in project functions. Apr 22, 1989 - modified to make multiple cell tiles work. Apr 25, 1989 - give quicksort two tries to order tiles expanding core if necessary. May 3, 1989 - changed to Y prefixes. May 6, 1989 - added no graphics compile switch ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) xcompact.c version 7.2 11/10/90" ; #endif #include #include #include static PICKETPTR botPickS ; buildXGraph() { int i ; /* counter */ int overlapx ; /* overlap conditions in x direction */ int overlapy ; /* overlap conditions in y direction */ int sortbyXY() ; /* sort the tiles X then Y */ int left, right ; /* coordinates of tiles */ int bottom, top ; /* coordinates of tiles */ BOOL firstPick ; /* TRUE if first picket which matches */ BOOL possibleEdgetoSource; /* TRUE if this could be edge to source */ BOOL *xancestorB ; /* TRUE for a cell if cell has B ancestors */ BOOL *xancestorF ; /* TRUE for a cell if cell has F ancestors */ COMPACTPTR candidate ; /* this is the tile in question */ COMPACTPTR t ; /* this is the current picket */ PICKETPTR freepick ; /* used to free the pickets at the end */ PICKETPTR curPick ; /* traverse the pickets */ PICKETPTR lowerLimit ; /* first picket tile overlaps/touches */ PICKETPTR upperLimit ; /* last picket tile overlaps or touches */ initxPicket() ; /* xGraphG is now initialized */ xancestorB = (BOOL *) Ysafe_calloc( last_cellG+1,sizeof(BOOL) ) ; xancestorF = (BOOL *) Ysafe_calloc( last_cellG+1,sizeof(BOOL) ) ; /* sort by xmin ymin of the bounding box */ /* we give it two chances - second time we expand core if necessary */ for( i=0; i <= 1 ; i++ ){ Yquicksort((char *)xGraphG,numtilesG+2,sizeof(COMPACTPTR),sortbyXY); if( xGraphG[SOURCE]->cell == XSOURCEC && xGraphG[SINK]->cell == XSINKC ){ break ; } else { find_core( &left, &right, &bottom, &top ) ; /* expand core region */ t = tileNodeG[XSOURCE] ; t->l = left ; t->r = t->l ; t = tileNodeG[XSINK] ; t->l = right ; t->r = t->l ; } } if( xGraphG[SOURCE]->cell != XSOURCEC || xGraphG[SINK]->cell != XSINKC ){ M( ERRMSG, "xcompact", "Fatal error in configuration\n" ) ; if( graphicsG ){ G( TWcloseGraphics() ) ; } YexitPgm( PGMFAIL ) ; } for( i=1 ; i<= numtilesG ; i++ ){ firstPick = TRUE ; lowerLimit = NULL ; upperLimit = NULL ; possibleEdgetoSource = FALSE ; candidate = xGraphG[i] ; /* search thru picket list for adjacencies */ for( curPick=botPickS;curPick;curPick=curPick->next){ ASSERT( dcheckPicks(), "buildXGraph", "pickets are bad" ) ; overlapy = projectY( curPick->pt2.bot, curPick->pt1.top, candidate->b, candidate->t) ; if( overlapy > 0 ){ /* overlap positive means real overlap */ /* save span of overlap */ if( firstPick ){ lowerLimit = curPick ; firstPick = FALSE ; } upperLimit = curPick ; t = tileNodeG[curPick->node] ; /* check for multiple tiles - no errors possible */ if( candidate->cell == t->cell ){ continue ; } /* now check for errors */ overlapx = projectX(t->l,t->r,candidate->l,candidate->r); if( overlapy > 0 && overlapx > 0 ){ D( "mc_compact/buildXGraph", sprintf( YmsgG, "Overlap detected: cell %d (tile:%d) and cell %d (tile:%d)\n", candidate->cell, candidate->node, t->cell, t->node ) ) ; D( "mc_compact/buildXGraph", M( MSG, NULL, YmsgG ) ) ; } ASSERT( t->node == curPick->node, "buildCGraph", "tileNodeG != curPick. Problem \n" ) ; /* form edge on only first occurance of cell */ if( t->node == 0 ){ /* source node */ /* delay adding this edge */ possibleEdgetoSource = TRUE ; } else { formxEdge( t->node, candidate->node ) ; } } else if( upperLimit ){ /* we are past the upper limit so break & save time */ break ; } } ASSERT( lowerLimit, "compact", "lowerLimit is NULL" ) ; ASSERT( upperLimit, "compact", "upperLimit is NULL" ) ; if( possibleEdgetoSource && xancestorF[candidate->cell] == FALSE ){ /* no need to make an edge to source if we already */ /* have an ancestor. Always make sure it is one of the lowest */ /* nodes of the multi-tiled cell */ formxEdge( 0, cellarrayG[candidate->cell]->xlo ) ; xancestorF[candidate->cell] = TRUE ; } update_xpicket( i, lowerLimit, upperLimit ) ; } /* end for loop */ /* process sink last */ /* search thru picket list for adjacencies */ for( curPick=botPickS;curPick;curPick=curPick->next){ /* remaining pickets must necessarily overlap sink */ t = tileNodeG[curPick->node] ; ASSERT( t->node == curPick->node, "buildXGraph", "tileNodeG != curPick. Problem \n" ) ; if( curPick->node != 0 && /* avoid source */ /* make sure sink is one of the highest nodes of the cell */ xancestorB[t->cell] == FALSE ){ /* no parents */ formxEdge( cellarrayG[t->cell]->xhi, xGraphG[last_tileG]->node ) ; xancestorB[t->cell] = TRUE ; } } D( "mc_compact/buildXGraph", M( MSG, NULL, "\n" ) ) ; /* now add multiple tile edges to graph. Precomputed in multi.c */ add_mtiles_to_xgraph() ; ASSERT( dxancestors( last_tileG, xGraphG ),"xcompact", "Number of ancestors does not match edges." ) ; cleanupGraph( XFORWARD ) ; cleanupGraph( XBACKWARD ) ; Ysafe_free( xancestorB ) ; Ysafe_free( xancestorF ) ; ASSERT( dxancestors( last_tileG, xGraphG ),"xcompact", "Number of ancestors does not match edges." ) ; /* delete all pickets */ for( curPick = botPickS; curPick ; ) { freepick = curPick ; curPick = curPick->next ; Ysafe_free( freepick ) ; } } /* end buildXGraph */ formxEdge( fromNode, toNode ) int fromNode ; int toNode ; { COMPACTPTR e1, e2 ; ECOMPBOXPTR temp, newE ; int constraint ; /* contraint between tiles */ e1 = tileNodeG[fromNode] ; D( "mc_compact/formxEdge", sprintf( YmsgG, "e1 is NULL; fromNode: %d\n", fromNode ) ) ; ASSERT( e1, "formxEdge", YmsgG ) ; e2 = tileNodeG[toNode] ; D( "mc_compact/formxEdge", sprintf( YmsgG, "e2 is NULL; toNode: %d\n", toNode ) ) ; ASSERT( e2, "formxEdge", YmsgG ) ; for( temp = e1->xadjF; temp; temp = temp->next ){ if( temp->node == toNode ){ return ; } } /* create forward edge */ if( temp = e1->xadjF ){ newE = e1->xadjF = (ECOMPBOXPTR) Ysafe_malloc(sizeof(ECOMPBOX)) ; /* hook to rest of list */ newE->next = temp ; } else { /* start adjacency list */ newE = e1->xadjF = (ECOMPBOXPTR) Ysafe_malloc(sizeof(ECOMPBOX)) ; newE->next = NULL ; } newE->node = toNode ; newE->marked = FALSE ; /* calculate the forward constraint */ /* This is a left edge algorithm so constraint is span of from tile */ /* one xspaceG spacing unless same cell */ if( e1->cell != e2->cell ){ constraint = e1->r_rel - e1->l_rel + xspaceG ; /* span of tile */ } else { /* this removes problem of overlapping tiles on multitiles */ constraint = ABS( e2->l_rel - e1->l_rel ) ; } newE->constraint = constraint ; ASSERT( newE->constraint >= 0, "formxEdge", YmsgG ) ; e1->xancestrB++ ; /* update ancestor count for longest path */ /* create backward edge */ if( temp = e2->xadjB ){ newE = e2->xadjB = (ECOMPBOXPTR) Ysafe_malloc(sizeof(ECOMPBOX)) ; /* hook to rest of list */ newE->next = temp ; } else { /* start adjacency list */ newE = e2->xadjB = (ECOMPBOXPTR) Ysafe_malloc(sizeof(ECOMPBOX)) ; newE->next = NULL ; } newE->node = fromNode ; newE->marked = FALSE ; newE->constraint = constraint ; e2->xancestrF++ ; /* update ancestor count for longest path */ D( "mc_compact/formxEdge", sprintf( YmsgG, "Edge %d - %d has a negative edge weight\n", fromNode, toNode ) ) ; ASSERT( newE->constraint >= 0, "formxEdge", YmsgG ) ; } initxPicket() { COMPACTPTR sink, source, node ; int i ; /* initialize all paths and values for all tiles */ for( i=0; i<= last_tileG ; i++ ) { node = xGraphG[i] ; node->pathx = 0 ; node->pathy = 0 ; node->xvalueMin = INT_MIN ; node->xvalueMax = INT_MIN ; node->xancestrF = 0 ; node->xancestrB = 0 ; node->criticalX = FALSE ; node->moved = FALSE ; } source = xGraphG[0] ; source->xvalueMin = 0 ; source->xvalueMax = 0 ; sink = xGraphG[last_tileG] ; sink->xvalueMax = 0 ; /* initialize picket to source */ botPickS = (PICKETPTR) Ysafe_malloc( sizeof(PICKETBOX) ) ; botPickS->pt1.top = xGraphG[0]->t ; botPickS->pt2.bot = xGraphG[0]->b ; botPickS->node = xGraphG[0]->node ; botPickS->next = NULL ; botPickS->prev = NULL ; } /* end initxPicket */ update_xpicket( i, lowerLimit, upperLimit ) int i ; PICKETPTR lowerLimit, upperLimit ; { PICKETPTR t, temp, curPick ; COMPACTPTR newtile ; /* new tile to be added to picket */ /* for speed */ newtile = xGraphG[i] ; if( newtile->b == lowerLimit->pt1.top ){ /* increment the lower limit */ lowerLimit = lowerLimit->next ; } /* update picket */ if( lowerLimit != upperLimit ){ /* first reset limits if cell i coincides with limits */ if( newtile->b == lowerLimit->pt2.bot ){ /* this tile will dissappear */ lowerLimit = lowerLimit->prev ; } if( newtile->t == upperLimit->pt1.top ){ /* this tile will dissappear */ upperLimit = upperLimit->next ; } /* insert node */ t = lowerLimit->next ; /* save old pointer to free it later */ temp = lowerLimit->next = (PICKETPTR) Ysafe_malloc( sizeof(PICKETBOX) ) ; /* fix back link */ temp->prev = lowerLimit ; /* delete picket- delete all pickets up to upperLimit */ for( curPick = t; curPick ; ) { if( curPick == upperLimit ){ break ; } t = curPick ; curPick = curPick->next ; Ysafe_free( t ) ; } /* Bottom link is now done. Now update picket information */ /* form overlapping pickets */ /* set lower limit */ lowerLimit->pt1.top = newtile->b ; /* set upper limit */ upperLimit->pt2.bot = newtile->t ; /* fill current picket */ temp->pt2.bot = newtile->b ; temp->pt1.top = newtile->t ; temp->node = newtile->node ; /* fix up the upper link */ temp->next = upperLimit ; upperLimit->prev = temp ; /* remove patheological cases - zero width nodes */ if( upperLimit->pt1.top == upperLimit->pt2.bot ){ /* upper node not needed remove */ temp->next = upperLimit->next ; temp->next->prev = temp ; Ysafe_free( upperLimit ) ; } /* bottom case - easier now due to doubly linked list */ if( lowerLimit->pt2.bot == lowerLimit->pt1.top ){ /* hook to precessor of lowerLimit */ temp->prev = lowerLimit->prev ; temp->prev->next = temp ; Ysafe_free( lowerLimit ) ; } } else { /* split a node */ /* first check case of exactly the same size tiles */ if( newtile->b == lowerLimit->pt2.bot && newtile->t == lowerLimit->pt1.top ){ /* this picket will be taken over by new ownership */ lowerLimit->node = newtile->node ; } else if( newtile->b == lowerLimit->pt2.bot || newtile->t == lowerLimit->pt1.top ){ /* insert one extra node above the lowerLimit */ t = lowerLimit->next ; /* save old pointer */ temp = lowerLimit->next = (PICKETPTR) Ysafe_malloc( sizeof(PICKETBOX) ) ; temp->next = t ; if( t ){ /* first time it is a special case */ t->prev = temp ; } temp->prev = lowerLimit ; /* the two nodes are done at this point */ if( newtile->b == lowerLimit->pt2.bot ){ /* lower limit is going to be replaced with newtile */ /* need to copy data to upper tile */ temp->node = lowerLimit->node ; temp->pt1.top = lowerLimit->pt1.top ; temp->pt2.bot = newtile->t ; lowerLimit->node = newtile->node ; lowerLimit->pt1.top = newtile->t ; lowerLimit->pt2.bot = newtile->b ; } else { /* newtile->t == lowerLimit->pt1.top */ /* no need to copy data to upper tile */ temp->node = newtile->node ; temp->pt1.top = newtile->t ; temp->pt2.bot = newtile->b ; lowerLimit->pt1.top = newtile->b ; } } else { /* three node case */ /* insert upper node - the same node */ t = lowerLimit->next ; /* save old pointer */ temp = lowerLimit->next = (PICKETPTR) Ysafe_malloc( sizeof(PICKETBOX) ) ; temp->next = t ; if( t ){ /* first time it is a special case */ t->prev = temp ; } temp->prev = lowerLimit ; temp->pt1.top = lowerLimit->pt1.top ; temp->pt2.bot = newtile->t ; temp->node = lowerLimit->node ; /* insert middle node - the new node */ t = lowerLimit->next ; /* save old pointer */ temp = lowerLimit->next = (PICKETPTR) Ysafe_malloc( sizeof(PICKETBOX) ) ; temp->next = t ; t->prev = temp ; temp->prev = lowerLimit ; temp->pt1.top = newtile->t ; temp->pt2.bot = newtile->b ; temp->node = newtile->node ; lowerLimit->pt1.top = newtile->b ; } } }/* end picket update */ /* function returns whether one cell projects onto another */ int projectX( tile1_left, tile1_right, tile2_left, tile2_right ) int tile1_left, tile1_right, tile2_left, tile2_right ; { /* ----------------------------------------------------- First check case 2nd tile larger than first complete overlap */ if( tile2_left <= tile1_left && tile1_right <= tile2_right ){ return( OVERLAP1 ) ; /* ----------------------------------------------------- Check if an edge of tile two is encompassed by tile 1 Second check left edge of tile2 : tile1_left <= tile2_left < tile1_right + xspaceG */ } else if( tile1_left<=tile2_left&&tile2_leftl != (*tileB)->l ){ return( (*tileA)->l - (*tileB)->l ) ; } else { /* if xmins are equal sort by ymins */ return( (*tileA)->b - (*tileB)->b ) ; } } load_ancestors( direction ) INT direction ; { INT i ; /* counter */ INT last ; /* last tile in tileNode array */ last = YSINK ; switch( direction ){ case XFORWARD: for( i = 0; i <= last; i++ ){ ancestorG[i] = tileNodeG[i]->xancestrF ; } break ; case XBACKWARD: for( i = 0; i <= last; i++ ){ ancestorG[i] = tileNodeG[i]->xancestrB ; } break ; case YFORWARD: for( i = 0; i <= last; i++ ){ ancestorG[i] = tileNodeG[i]->yancestrF ; } break ; case YBACKWARD: for( i = 0; i <= last; i++ ){ ancestorG[i] = tileNodeG[i]->yancestrB ; } break ; } } static xforwardPath() { INT j ; /* current tile adjacent to node */ INT node ; /* current node popped from the queue */ INT setValue ; /* the value of the path to this adj node */ INT currentValue ; /* path value of node popped from queue */ COMPACTPTR nextptr ; /* the tile record of the adj. node */ ECOMPBOXPTR ptr ; /* used to traverse edges of popped node */ QUEUEPTR botqueue, queue ; /* used to implement queue MACRO */ /* --------------------------------------------------------------- longestxPath uses breadth first search to find path. All QUEUE functions are combined into macros for speed and easier reading of the algorithm. See compact.h for details. */ /* FORWARD DIRECTION - SOURCE TO SINK */ load_ancestors( XFORWARD ) ; INITQUEUE( queue, XSOURCE ) ; while( queue ){ node = TOPQUEUE( queue ) ; currentValue = tileNodeG[node]->xvalueMin ; for( ptr = tileNodeG[node]->xadjF; ptr ; ptr = ptr->next ){ j = ptr->node ; nextptr = tileNodeG[j] ; /* calculate maximum of test condition */ setValue = currentValue + ptr->constraint ; if( !(nextptr->moved) && nextptr->xvalueMin < setValue ) { nextptr->xvalueMin = setValue ; nextptr->pathx = node ; } if( --ancestorG[j] == 0 ){ /* ready to add to queue when number ancestors = 0 */ ADD2QUEUE( queue, j ) ; } } /* end adjacency loop */ } /* end loop on queue */ } /* end xforwardPath */ static xbackwardPath() { INT j ; /* current tile adjacent to node */ INT node ; /* current node popped from the queue */ INT setValue ; /* the value of the path to this adj node */ INT currentValue ; /* path value of node popped from queue */ COMPACTPTR nextptr ; /* the tile record of the adj. node */ ECOMPBOXPTR ptr ; /* used to traverse edges of popped node */ QUEUEPTR botqueue, queue ; /* used to implement queue MACRO */ /* --------------------------------------------------------------- longestxPath uses breadth first search to find path. All QUEUE functions are combined into macros for speed and easier reading of the algorithm. See compact.h for details. */ /* FORWARD DIRECTION - SOURCE TO SINK */ load_ancestors( XBACKWARD ) ; /* REVERSE DIRECTION - SINK TO SOURCE */ INITQUEUE( queue, XSINK ) ; while( queue ){ node = TOPQUEUE( queue ) ; currentValue = tileNodeG[node]->xvalueMax ; for( ptr = tileNodeG[node]->xadjB; ptr ; ptr = ptr->next ){ j = ptr->node ; nextptr = tileNodeG[j] ; /* calculate maximum of test condition */ setValue = currentValue + ptr->constraint ; if( !(nextptr->moved) && nextptr->xvalueMax < setValue ) { nextptr->xvalueMax = setValue ; nextptr->pathx = node ; } if( --ancestorG[j] == 0 ){ /* ready to add to queue when number ancestors = 0 */ ADD2QUEUE( queue, j ) ; } } } } /* end xbackwardPath */ INT longestxPath( find_path ) BOOL find_path ; { INT cell ; /* current cell in question */ INT tile ; /* one of the tiles of the adj. cell */ INT count ; /* number of iterations */ INT center ; /* where center of cell is relative to path */ INT length ; /* length of longest path */ INT setValue ; /* the value of the path to this adj node */ INT siblingCenter ; /* the value of the path to sibling of adj node */ BOOL need_to_iterate_path ; /* if TRUE perform another round of longest path*/ BOOL need_to_update_tiles; /* whether tile x values need to be updated */ NODEPTR nptr ; /* used to traverse multi tiles */ CELLBOXPTR cptr ; /* the current cell */ COMPACTPTR sibling ; /* the tile record of the sibling to adj node */ COMPACTPTR nextptr ; /* the tile record of the adj. node */ ECOMPBOXPTR ptr ; /* used to traverse edges of popped node */ /* --------------------------------------------------------------- longestxPath uses breadth first search to find path. All QUEUE functions are combined into macros for speed and easier reading of the algorithm. See compact.h for details. */ /* FORWARD DIRECTION - SOURCE TO SINK */ /* First check to make sure all the ancestors are correct */ D( "mc_compact/xanc", check_xancestors() ; ) ; /*********************************************************** * The longest path algorithm in the FORWARD direction. ***********************************************************/ count = 0 ; need_to_iterate_path = TRUE ; while( need_to_iterate_path ){ xforwardPath() ; /*********************************************************** * The code below looks to see if we need to iterate because * of multiple cells. ***********************************************************/ need_to_iterate_path = FALSE ; for( cell = 1; cell <= numcellsG ; cell++ ){ cptr = cellarrayG[cell] ; if( cptr->multi ){ nptr = cptr->tiles; tile = nptr->node ; nextptr = tileNodeG[tile] ; center = nextptr->xvalueMin - nextptr->l_rel ; need_to_update_tiles = FALSE ; /* look for the maximimum of all the siblings */ /* if all the centers are the same there is no */ /* need to update the forward path for this cell */ for( nptr = nptr->next;nptr;nptr=nptr->next ){ tile = nptr->node ; /* see if we need to update reverse edges */ sibling = tileNodeG[tile] ; siblingCenter = sibling->xvalueMin - sibling->l_rel ; if( center != siblingCenter ){ need_to_update_tiles = TRUE ; need_to_iterate_path = TRUE ; if( center < siblingCenter ){ center = siblingCenter ; } } } if( need_to_update_tiles ){ for( nptr = cptr->tiles;nptr;nptr=nptr->next ){ tile = nptr->node ; sibling = tileNodeG[tile] ; sibling->xvalueMin = center + sibling->l_rel ; } } } } D( "mc_compact/iterate", count++ ; ) ; } /* end loop on longest path for forward loop including fixed cells. */ D( "mc_compact/iterate", fprintf( stderr, "It took %d time[s] to converge in x forward graph\n\n", count ) ; ) ; /*********************************************************** * At this point we have iterated to get the longest path * Now measure it. ***********************************************************/ if( find_path ){ length = path(XFORWARD) ; } /*********************************************************** * The longest path algorithm in the REVERSE direction. ***********************************************************/ need_to_iterate_path = TRUE ; count = 0 ; while( need_to_iterate_path ){ /* find the longest path backward */ xbackwardPath() ; /*********************************************************** * The code below looks to see if we need to iterate because * of multiple cells. ***********************************************************/ need_to_iterate_path = FALSE ; for( cell = 1; cell <= numcellsG ; cell++ ){ cptr = cellarrayG[cell] ; if( cptr->multi ){ nptr = cptr->tiles; tile = nptr->node ; nextptr = tileNodeG[tile] ; center = nextptr->xvalueMax + nextptr->l_rel ; need_to_update_tiles = FALSE ; /* look for the maximimum of all the siblings */ /* if all the centers are the same there is no */ /* need to update the forward path for this cell */ for( nptr = nptr->next;nptr;nptr=nptr->next ){ tile = nptr->node ; /* see if we need to update reverse edges */ sibling = tileNodeG[tile] ; siblingCenter = sibling->xvalueMax + sibling->l_rel ; if( center != siblingCenter ){ need_to_update_tiles = TRUE ; need_to_iterate_path = TRUE ; if( center < siblingCenter ){ center = siblingCenter ; } } } if( need_to_update_tiles ){ for( nptr = cptr->tiles;nptr;nptr=nptr->next ){ tile = nptr->node ; sibling = tileNodeG[tile] ; sibling->xvalueMax = center - sibling->l_rel ; } } } } D( "mc_compact/iterate", count++ ; ) ; } /* end loop on longest path for reverse loop including fixed cells. */ D( "mc_compact/iterate", fprintf( stderr, "It took %d time[s] to converge in x backward graph\n\n", count ) ; ) ; /*********************************************************** * At this point we have iterated to get the longest path * in the reverse direction. Now measure it. ***********************************************************/ if( find_path ){ ASSERT( length == path(XBACKWARD), "longestxPath", "Longest path doesn't agree forward & back") ; } return( length ) ; } /* end longestxPath */ dxpick() { PICKETPTR curPick ; printf("Bottom to top pickets:\n" ) ; for( curPick=botPickS;curPick;curPick=curPick->next){ printf("Node:%2d cell:%2d bot:%4d top:%4d\n", curPick->node, tileNodeG[curPick->node]->cell, curPick->pt2.bot, curPick->pt1.top ) ; } } /* verify that the picket list is correct */ BOOL dcheckPicks() { PICKETPTR lastpick, pick_it ; int forwardCount, backCount ; if( YgetListSize(botPickS,&(botPickS->next)) != -1 ){ forwardCount = 0 ; backCount = 0 ; for( pick_it = botPickS;pick_it;pick_it=pick_it->next ){ forwardCount++ ; lastpick = pick_it ; } for( pick_it = lastpick;pick_it;pick_it=pick_it->prev ){ backCount++ ; } if( forwardCount == backCount ){ return( TRUE ) ; } } return( FALSE ) ; } graywolf-0.1.4+20170307gite1bf319/src/mc_compact/ycompact.c000066400000000000000000000616141305746555600226530ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: ycompact.c DESCRIPTION:This file contains type declarations for the compaction in the ydirection. CONTENTS: DATE: Apr 8, 1988 REVISIONS: Sep 20, 1988 - removed excess edges from source and sink Oct 29, 1988 - fixed problem when cell is exactly same size as picket or multiples of pickets. Also changed picket to doubly-linked list. Nov 7, 1988 - implemented doubly-linked list correctly. Jan 29, 1989 - changed to YmsgG and added \n's. Apr 22, 1989 - modified to make multiple cell tiles work. Fixed bug in update_ypicket(). Apr 25, 1989 - give quicksort two chances to order tiles expanding core if necessary. May 3, 1989 - changed to Y prefixes. May 6, 1989 - added no graphics compile switch ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) ycompact.c version 7.1 11/10/90" ; #endif #include #include static PICKETPTR leftPickS ; ERRORPTR buildYGraph() { int i ; /* counter */ int overlapx ; /* overlap conditions in x direction */ int overlapy ; /* overlap conditions in y direction */ int sortbyYX() ; /* sort the tiles Y then X */ int left, right ; /* coordinates of tiles */ int bottom, top ; /* coordinates of tiles */ BOOL firstPick ; /* TRUE if first picket which matches */ BOOL possibleEdgetoSource; /* TRUE if this could be edge to source */ BOOL *yancestorB ; /* TRUE for a cell if cell has B ancestors */ BOOL *yancestorF ; /* TRUE for a cell if cell has F ancestors */ COMPACTPTR candidate ; /* this is the tile in question */ COMPACTPTR t ; /* this is the current picket */ PICKETPTR freepick ; /* used to free the pickets at the end */ PICKETPTR curPick ; /* traverse the pickets */ PICKETPTR lowerLimit ; /* first picket tile overlaps/touches */ PICKETPTR upperLimit ; /* last picket tile overlaps or touches */ ERRORPTR errorPtr ; /* form a list of errors to be processed*/ ERRORPTR lasterror ; /* last error in list */ ERRORPTR violations ; /* head of the error list */ /* initialize error list */ lasterror = NULL ; violations = NULL ; yancestorB = (BOOL *) Ysafe_calloc( last_cellG+1,sizeof(BOOL) ) ; yancestorF = (BOOL *) Ysafe_calloc( last_cellG+1,sizeof(BOOL) ) ; inityPicket() ; /* yGraphG is now initialized */ /* sort by ymin xmin of the bounding box */ /* we give it two chances - second time we expand core if necessary */ for( i=0; i <= 1 ; i++ ){ Yquicksort((char *)yGraphG,numtilesG+2,sizeof(COMPACTPTR),sortbyYX); if( yGraphG[SOURCE]->cell == YSOURCEC && yGraphG[SINK]->cell == YSINKC ){ break ; } else { find_core( &left, &right, &bottom, &top ) ; /* expand core region */ t = tileNodeG[YSOURCE] ; t->b = bottom ; t->t = t->b ; t = tileNodeG[YSINK] ; t->b = top ; t->t = t->b ; } } if( yGraphG[SOURCE]->cell != YSOURCEC || yGraphG[SINK]->cell != YSINKC ){ M( ERRMSG, "ycompact", "Fatal error in configuration\n" ) ; if( graphicsG ){ G( TWcloseGraphics() ) ; } YexitPgm( PGMFAIL ) ; } for( i=1 ; i<= numtilesG ; i++ ){ firstPick = TRUE ; lowerLimit = NULL ; upperLimit = NULL ; possibleEdgetoSource = FALSE ; candidate = yGraphG[i] ; /* search thru picket list for adjacencies */ for( curPick=leftPickS;curPick;curPick=curPick->next){ overlapx = projectX( curPick->pt2.lft, curPick->pt1.rght, candidate->l, candidate->r) ; if( overlapx > 0 ){ /* allow touching */ /* save span of overlap */ if( firstPick ){ lowerLimit = curPick ; firstPick = FALSE ; } upperLimit = curPick ; t = tileNodeG[curPick->node] ; /* multiple tile case - no error possible */ if( candidate->cell == t->cell ){ continue ; } /* check for errors */ overlapy = projectY( t->b, t->t, candidate->b, candidate->t ) ; if( overlapx > 0 && overlapy > 0 ){ /* save violations - add to violation list */ if( lasterror ){ errorPtr = (ERRORPTR) Ysafe_malloc( sizeof(ERRORBOX) ) ; lasterror->next = errorPtr ; lasterror = errorPtr ; } else { violations = errorPtr = lasterror = (ERRORPTR) Ysafe_malloc( sizeof(ERRORBOX) ) ; } errorPtr->next = NULL ; errorPtr->nodeI = candidate->node ; errorPtr->nodeJ = t->node ; /* for debug only : sprintf( YmsgG, Overlap detected: cell %d and cell %d\n", candidate->cell, t->cell ) ; M( MSG, NULL, YmsgG ) ; */ } ASSERT( t->node == curPick->node, "buildCGraph", "tileNodeG != curPick. Problem \n" ) ; /* form edge on only first occurance of cell */ if( t->node == numtilesG+2 ){ /* source node */ /* delay adding this edge */ possibleEdgetoSource = TRUE ; } else { formyEdge( t->node, candidate->node ) ; } } else if( upperLimit ){ /* we are past the upper limit so break & save time */ break ; } } ASSERT( lowerLimit, "compact", "lowerLimit is NULL" ) ; ASSERT( upperLimit, "compact", "lowerLimit is NULL" ) ; if( possibleEdgetoSource && yancestorF[candidate->cell] == FALSE ){ /* no need to make an edge to source if we already */ /* have an ancestor. Always make sure it is one of the lowest */ /* nodes of the multi-tiled cell */ formyEdge( numtilesG+2, cellarrayG[candidate->cell]->ylo ) ; yancestorF[candidate->cell] = TRUE ; } update_ypicket( i, lowerLimit, upperLimit ) ; } /* end for loop */ /* process sink last */ /* search thru picket list for adjacencies */ for( curPick=leftPickS;curPick;curPick=curPick->next){ /* remaining pickets must necessarily overlap sink */ t = tileNodeG[curPick->node] ; ASSERT( t->node == curPick->node, "buildCGraph", "tileNodeG != curPick. Problem \n" ) ; if( curPick->node != numtilesG+2 && /* avoid the source */ yancestorB[t->cell] == FALSE ){ /* no parents */ formyEdge( cellarrayG[t->cell]->yhi, yGraphG[last_tileG]->node ) ; yancestorB[t->cell] = TRUE ; } } /* now add multiple tile edges to graph. Precomputed in multi.c */ add_mtiles_to_ygraph() ; cleanupGraph( YFORWARD ) ; cleanupGraph( YBACKWARD ) ; Ysafe_free( yancestorB ) ; Ysafe_free( yancestorF ) ; /* delete all pickets */ for( curPick = leftPickS; curPick ; ) { freepick = curPick ; curPick = curPick->next ; Ysafe_free( freepick ) ; } return( violations ) ; } /* end buildYGraph */ formyEdge( fromNode, toNode ) int fromNode ; int toNode ; { COMPACTPTR e1, e2 ; ECOMPBOXPTR temp, newE ; int constraint ; /* constaint between tiles */ e1 = tileNodeG[fromNode] ; D( "mc_compact/formyEdge", sprintf( YmsgG, "e1 is NULL; fromNode: %d\n", fromNode ) ) ; ASSERT( e1, "formyEdge", YmsgG ) ; e2 = tileNodeG[toNode] ; D( "mc_compact/formyEdge", sprintf( YmsgG, "e2 is NULL; toNode: %d\n", toNode ) ) ; ASSERT( e2, "formyEdge", YmsgG ) ; for( temp = e1->yadjF; temp; temp = temp->next ){ if( temp->node == toNode ){ return ; } } /* calculate the forward constraint */ /* This is a left edge algorithm so constraint is span of from tile */ /* one yspaceG spacing unless same cell */ if( e1->cell != e2->cell ){ constraint = e1->t_rel - e1->b_rel + yspaceG ; /* span of tile */ } else { /* this removes problem of overlapping tiles on multitiles */ constraint = ABS( e2->b_rel - e1->b_rel ) ; } D( "mc_compact/formyEdge", sprintf( YmsgG, "Edge %d - %d has a negative edge weight\n", fromNode, toNode ) ) ; ASSERT( constraint >= 0, "formyEdge", YmsgG ) ; if( constraint < 0 ){ return ; } /* create forward edge */ if( temp = e1->yadjF ){ newE = e1->yadjF = (ECOMPBOXPTR) Ysafe_malloc(sizeof(ECOMPBOX)) ; /* hook to rest of list */ newE->next = temp ; } else { /* start adjacency list */ newE = e1->yadjF = (ECOMPBOXPTR) Ysafe_malloc(sizeof(ECOMPBOX)) ; newE->next = NULL ; } newE->node = toNode ; newE->marked = FALSE ; newE->constraint = constraint ; e1->yancestrB++ ; /* update ancestor count for longest path */ /* create backward edge */ if( temp = e2->yadjB ){ newE = e2->yadjB = (ECOMPBOXPTR) Ysafe_malloc(sizeof(ECOMPBOX)) ; /* hook to rest of list */ newE->next = temp ; } else { /* start adjacency list */ newE = e2->yadjB = (ECOMPBOXPTR) Ysafe_malloc(sizeof(ECOMPBOX)) ; newE->next = NULL ; } newE->node = fromNode ; newE->marked = FALSE ; newE->constraint = constraint ; e2->yancestrF++ ; /* update ancestor count for longest path */ } inityPicket( ) { COMPACTPTR source, sink, node ; int i ; /* initialize all paths and values for all tiles */ for( i=0; i<= last_tileG ; i++ ) { node = yGraphG[i] ; node->pathx = 0 ; node->pathy = 0 ; node->yvalueMin = INT_MIN ; node->yvalueMax = INT_MIN ; node->yancestrF = 0 ; node->yancestrB = 0 ; node->criticalY = FALSE ; node->moved = FALSE ; } source = yGraphG[0] ; source->yvalueMin = 0 ; source->yvalueMax = 0 ; sink = yGraphG[last_tileG] ; sink->yvalueMin = INT_MIN ; sink->yvalueMax = 0 ; /* initialize picket to source */ leftPickS = (PICKETPTR) Ysafe_malloc( sizeof(PICKETBOX) ) ; leftPickS->pt1.rght = yGraphG[0]->r ; leftPickS->pt2.lft = yGraphG[0]->l ; leftPickS->node = yGraphG[0]->node ; leftPickS->next = NULL ; leftPickS->prev = NULL ; } update_ypicket( i, lowerLimit, upperLimit ) int i ; PICKETPTR lowerLimit, upperLimit ; { PICKETPTR t, temp, curPick ; COMPACTPTR newtile ; /* new tile to be added to picket */ /* for speed */ newtile = yGraphG[i] ; if( newtile->l == lowerLimit->pt1.rght ){ /* increment lower limit */ lowerLimit = lowerLimit->next ; } if( lowerLimit != upperLimit ){ /* first reset limits if cell i coincides with limits */ if( newtile->l == lowerLimit->pt2.lft ){ lowerLimit = lowerLimit->prev ; } if( newtile->r == upperLimit->pt1.rght ){ upperLimit = upperLimit->next ; } /* insert node */ t = lowerLimit->next ; /* save old pointer */ temp = lowerLimit->next = (PICKETPTR) Ysafe_malloc( sizeof(PICKETBOX) ) ; /* fix back link */ temp->prev = lowerLimit ; /* delete picket- delete all pickets up to upperLimit */ for( curPick = t; curPick ; ) { if( curPick == upperLimit ){ break ; } t = curPick ; curPick = curPick->next ; Ysafe_free( t ) ; } /* left link is now done. Now update picket information */ /* form overlapping pickets */ /* set lower limit */ lowerLimit->pt1.rght = newtile->l ; /* set upper limit */ upperLimit->pt2.lft = newtile->r ; /* fill current picket */ temp->pt2.lft = newtile->l ; temp->pt1.rght = newtile->r ; temp->node = newtile->node ; /* fix the right link */ temp->next = upperLimit ; upperLimit->prev = temp ; ASSERT( tileNodeG[lowerLimit->node]->l <= lowerLimit->pt1.rght && lowerLimit->pt1.rght <= tileNodeG[lowerLimit->node]->r, "update_ypicket", "a cell does not exist between limits" ) ; ASSERT( tileNodeG[upperLimit->node]->l <= upperLimit->pt2.lft && upperLimit->pt2.lft <= tileNodeG[upperLimit->node]->r, "update_ypicket", "a cell does not exist between limits" ) ; /* remove patheological cases - zero width nodes */ if( upperLimit->pt1.rght == upperLimit->pt2.lft ){ /* upper node not needed remove */ temp->next = upperLimit->next ; temp->next->prev = temp ; Ysafe_free( upperLimit ) ; } /* bottom case - easier now due to doubly linked list */ if( lowerLimit->pt2.lft == lowerLimit->pt1.rght ){ /* hook precessor of lowerLimit */ temp->prev = lowerLimit->prev ; temp->prev->next = temp ; Ysafe_free( lowerLimit ) ; } } else { /* split a node */ /* first check case of exactly the same size tiles */ if( newtile->l == lowerLimit->pt2.lft && newtile->r == upperLimit->pt1.rght ){ /* this picket will be taken over by new ownership */ lowerLimit->node = newtile->node ; } else if( newtile->l == lowerLimit->pt2.lft || newtile->r == upperLimit->pt1.rght ){ /* two picket case */ /* insert one extra node above the lowerLimit */ t = lowerLimit->next ; /* save old pointer */ temp = lowerLimit->next = (PICKETPTR) Ysafe_malloc( sizeof(PICKETBOX) ) ; temp->next = t ; if( t ){ /* first time it is a special case */ t->prev = temp ; } temp->prev = lowerLimit ; /* the two nodes are done at this point */ if( newtile->l == lowerLimit->pt2.lft ){ /* lower limit is going to be replaced with newtile */ /* need to copy data to upper tile */ temp->node = lowerLimit->node ; temp->pt1.rght = lowerLimit->pt1.rght ; temp->pt2.lft = newtile->r ; lowerLimit->node = newtile->node ; lowerLimit->pt1.rght = newtile->r ; lowerLimit->pt2.lft = newtile->l ; } else { /* newtile->r == lowerLimit->pt1.rght */ /* no need to copy data to upper tile */ temp->node = newtile->node ; temp->pt1.rght = newtile->r ; temp->pt2.lft = newtile->l ; lowerLimit->pt1.rght = newtile->l ; } } else { /* three picket case */ /* insert an upper node */ t = lowerLimit->next ; /* save old pointer */ temp = lowerLimit->next = (PICKETPTR) Ysafe_malloc( sizeof(PICKETBOX) ) ; temp->next = t ; if( t ){ /* first time it is a special case */ t->prev = temp ; } temp->prev = lowerLimit ; temp->pt1.rght = lowerLimit->pt1.rght ; temp->pt2.lft = newtile->r ; temp->node = lowerLimit->node ; /* insert middle node */ t = lowerLimit->next ; /* save old pointer */ temp = lowerLimit->next = (PICKETPTR) Ysafe_malloc( sizeof(PICKETBOX) ) ; temp->next = t ; t->prev = temp ; temp->prev = lowerLimit ; temp->pt1.rght = newtile->r ; temp->pt2.lft = newtile->l ; temp->node = newtile->node ; lowerLimit->pt1.rght = newtile->l ; ASSERT( tileNodeG[temp->node]->l <= temp->pt2.lft && temp->pt2.lft <= tileNodeG[temp->node]->r, "update_ypicket", "a cell does not exist between limits" ) ; ASSERT( tileNodeG[lowerLimit->node]->l <= lowerLimit->pt1.rght && lowerLimit->pt1.rght <= tileNodeG[lowerLimit->node]->r, "update_ypicket", "a cell does not exist between limits" ) ; } /* end else for three picket case */ } }/* end picket update */ /* sort by y first then x */ sortbyYX( tileA , tileB ) COMPACTPTR *tileA , *tileB ; { if( (*tileA)->b != (*tileB)->b ){ return( (*tileA)->b - (*tileB)->b ) ; } else { /* if ymins are equal sort by xmins */ return( (*tileA)->l - (*tileB)->l ) ; } } static yforwardPath() { INT j ; /* current tile adjacent to node */ INT node ; /* current node popped from the queue */ INT setValue ; /* the value of the path to this adj node */ INT currentValue ; /* path value of node popped from queue */ COMPACTPTR nextptr ; /* the tile record of the adj. node */ ECOMPBOXPTR ptr ; /* used to traverse edges of popped node */ QUEUEPTR botqueue, queue ; /* used to implement queue MACRO */ /* --------------------------------------------------------------- longestyPath uses breadth first search to find path. All QUEUE functions are combined into macros for speed and easier reading of the algorithm. See compact.h for details. */ /* FORWARD DIRECTION - SOURCE TO SINK */ load_ancestors( YFORWARD ) ; INITQUEUE( queue, YSOURCE ) ; while( queue ){ node = TOPQUEUE( queue ) ; currentValue = tileNodeG[node]->yvalueMin ; for( ptr = tileNodeG[node]->yadjF; ptr ; ptr = ptr->next ){ j = ptr->node ; nextptr = tileNodeG[j] ; /* calculate maximum of test condition */ setValue = currentValue + ptr->constraint ; if( !(nextptr->moved) && nextptr->yvalueMin < setValue ) { nextptr->yvalueMin = setValue ; nextptr->pathy = node ; } if( --ancestorG[j] == 0 ){ /* ready to add to queue when number ancestors = 0 */ ADD2QUEUE( queue, j ) ; } } /* end adjacency loop */ } /* end loop on queue */ } /* end yforwardPath */ static ybackwardPath() { INT j ; /* current tile adjacent to node */ INT node ; /* current node popped from the queue */ INT setValue ; /* the value of the path to this adj node */ INT currentValue ; /* path value of node popped from queue */ COMPACTPTR nextptr ; /* the tile record of the adj. node */ ECOMPBOXPTR ptr ; /* used to traverse edges of popped node */ QUEUEPTR botqueue, queue ; /* used to implement queue MACRO */ /* --------------------------------------------------------------- longestyPath uses breadth first search to find path. All QUEUE functions are combined into macros for speed and easier reading of the algorithm. See compact.h for details. */ /* FORWARD DIRECTION - SOURCE TO SINK */ load_ancestors( YBACKWARD ) ; /* REVERSE DIRECTION - SINK TO SOURCE */ INITQUEUE( queue, YSINK ) ; while( queue ){ node = TOPQUEUE( queue ) ; currentValue = tileNodeG[node]->yvalueMax ; for( ptr = tileNodeG[node]->yadjB; ptr ; ptr = ptr->next ){ j = ptr->node ; nextptr = tileNodeG[j] ; /* calculate maximum of test condition */ setValue = currentValue + ptr->constraint ; if( !(nextptr->moved) && nextptr->yvalueMax < setValue ) { nextptr->yvalueMax = setValue ; nextptr->pathy = node ; } if( --ancestorG[j] == 0 ){ /* ready to add to queue when number ancestors = 0 */ ADD2QUEUE( queue, j ) ; } } } } /* end ybackwardPath */ INT longestyPath( find_path ) BOOL find_path ; { INT cell ; /* current cell in question */ INT tile ; /* one of the tiles of the adj. cell */ INT count ; /* number of iterations */ INT center ; /* where center of cell is relative to path */ INT length ; /* length of longest path */ INT setValue ; /* the value of the path to this adj node */ INT siblingCenter ; /* the value of the path to sibling of adj node */ BOOL need_to_iterate_path ; /* if TRUE perform another round of longest path*/ BOOL need_to_update_tiles; /* whether tile y values need to be updated */ NODEPTR nptr ; /* used to traverse multi tiles */ CELLBOXPTR cptr ; /* the current cell */ COMPACTPTR sibling ; /* the tile record of the sibling to adj node */ COMPACTPTR nextptr ; /* the tile record of the adj. node */ ECOMPBOXPTR ptr ; /* used to traverse edges of popped node */ /* --------------------------------------------------------------- longestyPath uses breadth first search to find path. All QUEUE functions are combined into macros for speed and easier reading of the algorithm. See compact.h for details. */ /* FORWARD DIRECTION - SOURCE TO SINK */ /* First check to make sure all the ancestors are correct */ D( "mc_compact/yanc", check_yancestors() ; ) ; /*********************************************************** * The longest path algorithm in the FORWARD direction. ***********************************************************/ need_to_iterate_path = TRUE ; count = 0 ; while( need_to_iterate_path ){ yforwardPath() ; /*********************************************************** * The code below looks to see if we need to iterate because * of multiple cells. ***********************************************************/ need_to_iterate_path = FALSE ; for( cell = 1; cell <= numcellsG ; cell++ ){ cptr = cellarrayG[cell] ; if( cptr->multi ){ nptr = cptr->tiles; tile = nptr->node ; nextptr = tileNodeG[tile] ; center = nextptr->yvalueMin - nextptr->b_rel ; need_to_update_tiles = FALSE ; /* look for the maximimum of all the siblings */ /* if all the centers are the same there is no */ /* need to update the forward path for this cell */ for( nptr = nptr->next;nptr;nptr=nptr->next ){ tile = nptr->node ; /* see if we need to update reverse edges */ sibling = tileNodeG[tile] ; siblingCenter = sibling->yvalueMin - sibling->b_rel ; if( center != siblingCenter ){ need_to_update_tiles = TRUE ; need_to_iterate_path = TRUE ; if( center < siblingCenter ){ center = siblingCenter ; } } } if( need_to_update_tiles ){ for( nptr = cptr->tiles;nptr;nptr=nptr->next ){ tile = nptr->node ; sibling = tileNodeG[tile] ; sibling->yvalueMin = center + sibling->b_rel ; } } } } D( "mc_compact/iterate", count++ ; ) ; } /* end loop on longest path for forward loop including fixed cells. */ D( "mc_compact/iterate", fprintf( stderr, "It took %d time[s] to converge in y forward graph\n\n", count ) ; ) ; /*********************************************************** * At this point we have iterated to get the longest path * Now measure it. ***********************************************************/ if( find_path ){ length = path(YFORWARD) ; } /*********************************************************** * The longest path algorithm in the REVERSE direction. ***********************************************************/ need_to_iterate_path = TRUE ; count = 0 ; while( need_to_iterate_path ){ /* find the longest path backward */ ybackwardPath() ; /*********************************************************** * The code below looks to see if we need to iterate because * of multiple cells. ***********************************************************/ need_to_iterate_path = FALSE ; for( cell = 1; cell <= numcellsG ; cell++ ){ cptr = cellarrayG[cell] ; if( cptr->multi ){ nptr = cptr->tiles; tile = nptr->node ; nextptr = tileNodeG[tile] ; center = nextptr->yvalueMax + nextptr->b_rel ; need_to_update_tiles = FALSE ; /* look for the maximimum of all the siblings */ /* if all the centers are the same there is no */ /* need to update the forward path for this cell */ for( nptr = nptr->next;nptr;nptr=nptr->next ){ tile = nptr->node ; /* see if we need to update reverse edges */ sibling = tileNodeG[tile] ; siblingCenter = sibling->yvalueMax + sibling->b_rel ; if( center != siblingCenter ){ need_to_update_tiles = TRUE ; need_to_iterate_path = TRUE ; if( center < siblingCenter ){ center = siblingCenter ; } } } if( need_to_update_tiles ){ for( nptr = cptr->tiles;nptr;nptr=nptr->next ){ tile = nptr->node ; sibling = tileNodeG[tile] ; sibling->yvalueMax = center - sibling->b_rel ; } } } } D( "mc_compact/iterate", count++ ; ) ; } /* end loop on longest path for reverse loop including fixed cells. */ D( "mc_compact/iterate", fprintf( stderr, "It took %d time[s] to converge in y backward graph\n\n", count ) ; ) ; /*********************************************************** * At this point we have iterated to get the longest path * in the reverse direction. Now measure it. ***********************************************************/ if( find_path ){ ASSERT( length == path(YBACKWARD), "longestyPath", "Longest path doesn't agree forward & back") ; } return( length ) ; } /* end longestyPath */ dypick() { PICKETPTR curPick ; printf("Bottom to top pickets:\n" ) ; for( curPick=leftPickS;curPick;curPick=curPick->next){ printf("Node:%2d cell:%2d left:%4d right:%4d\n", curPick->node, tileNodeG[curPick->node]->cell, curPick->pt2.lft, curPick->pt1.rght ) ; } } graywolf-0.1.4+20170307gite1bf319/src/mincut/000077500000000000000000000000001305746555600200525ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/src/mincut/CMakeLists.txt000066400000000000000000000005601305746555600226130ustar00rootroot00000000000000 add_executable(Mincut main.c output.c readcells.c ${CMAKE_SOURCE_DIR}/src/date/date.c) target_link_libraries(Mincut ${CMAKE_BINARY_DIR}/src/Ylib/libycadgraywolf.so) target_link_libraries(Mincut X11) target_link_libraries(Mincut m) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include .) install(TARGETS Mincut DESTINATION lib/graywolf/bin) graywolf-0.1.4+20170307gite1bf319/src/mincut/date.h000066400000000000000000000001071305746555600211360ustar00rootroot00000000000000#define DATE "@(#) Yale compilation date:Mon May 25 21:09:40 EDT 1992" graywolf-0.1.4+20170307gite1bf319/src/mincut/globals.h000066400000000000000000000045451305746555600216560ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- "@(#) globals.h version 1.1 7/30/91" FILE: globals.h CONTENTS: definitions for globals structures and variables DATE: Apr 24, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef GLOBALS_H #define GLOBALS_H #include #ifndef MATH_H #define MATH_H #include #endif /* MATH_H */ /* if not using makefile and debug is wanted add it here */ /* #define DEBUG */ /* ***********LEAVE THE BELOW UNCHANGED *************************** */ #define NOCUT "nocut - replacement for Mincut" #define HARDCELLTYPE 1 #define SOFTCELLTYPE 2 #define STDCELLTYPE 3 #define PADCELLTYPE 4 /* compile switch for globals */ #ifndef MAIN_VARS #define EXTERN extern #else #define EXTERN #endif EXTERN char *cktNameG ; #endif /* GLOBALS_H */ graywolf-0.1.4+20170307gite1bf319/src/mincut/main.c000066400000000000000000000122451305746555600211460ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * Copyright (C) 2014 Ruben Undheim * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: main.c DESCRIPTION:This file contains main control routine for the syntax program. CONTENTS: DATE: Apr 24, 1989 REVISIONS: Dec 8, 1989 - now write temp file to be moved later so that programs that follow won't run until passing syntax. Fri Jan 25 17:57:06 PST 1991 - added debug flag to syntax. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) main.c version 1.1 7/30/91" ; #endif #define MAIN_VARS #include #include #include #include #include #include #include #include "globals.h" #include "config-build.h" #define EXPECTEDMEMORY (1024 * 1024) /* 1M should be enough */ #define VERSION "v1.0" main( argc , argv ) int argc ; char *argv[] ; { char *YinitProgram(), *Ystrclone() ; char filename[LRECL] ; char command[LRECL] ; char *ptr ; int arg_count ; int yaleIntro() ; int debug ; FILE *fp ; char *twdir, *Ygetenv() ; /* start up cleanup handler */ YINITCLEANUP( argv[0], NULL, MAYBEDUMP ) ; Yinit_memsize( EXPECTEDMEMORY ) ; if( argc < 2 || argc > 3 ){ syntax() ; } else { debug = FALSE ; arg_count = 1 ; if( *argv[1] == '-' ){ for( ptr = ++argv[1]; *ptr; ptr++ ){ switch( *ptr ){ case 'd': debug = TRUE ; break ; default: sprintf( YmsgG,"Unknown option:%c\n", *ptr ) ; M(ERRMSG,"main",YmsgG); syntax() ; } } YdebugMemory( debug ) ; cktNameG = Ystrclone( argv[++arg_count] ); /* now tell the user what he picked */ M(MSG,NULL,"\n\nSyntax switches:\n" ) ; if( debug ){ YsetDebug( TRUE ) ; M(MSG,NULL,"\tdebug on\n" ) ; } M(MSG,NULL,"\n" ) ; } else if( argc == 2 ){ /* order is important here */ YdebugMemory( FALSE ) ; cktNameG = Ystrclone( argv[1] ); } else { syntax() ; } } /* we can change this value in the debugger */ YinitProgram(NOCUT, VERSION, yaleIntro) ; if( twdir = TWFLOWDIR ){ sprintf(command, "awk -f %s/bin/splt_file.a %s.cel", twdir , cktNameG ) ; } else { fprintf(stderr,"ERROR:TWDIR environment variable not set.\n"); fprintf(stderr,"Please set it to TimberWolf root directory\n"); YexitPgm( PGMFAIL ) ; } read_par() ; sprintf( filename, "%s.cel", cktNameG ) ; fp = TWOPEN( filename, "r", ABORT ) ; readcells( fp ) ; TWCLOSE( fp ) ; sprintf( filename, "%s.mcel", cktNameG ) ; fp = TWOPEN( filename, "w", ABORT ) ; output( fp ) ; TWCLOSE( fp ) ; sprintf( filename, "%s.stat", cktNameG ) ; fp = TWOPEN( filename, "a", ABORT ) ; update_stats( fp ) ; TWCLOSE( fp ) ; fprintf(stdout, "Splitting %s.cel into " , cktNameG ) ; fprintf(stdout, "%s.scel and %s.mcel...\n" , cktNameG , cktNameG ) ; fflush( stdout ) ; Ysystem( "Mincut", ABORT, command, NULL ) ; fprintf(stdout, "\tdone!\n\n" ) ; fflush( stdout ) ; YexitPgm( PGMOK ) ; } /* end main */ /* give user correct syntax */ syntax() { M(ERRMSG,NULL,"\n" ) ; M(MSG,NULL,"Incorrect syntax. Correct syntax:\n"); sprintf( YmsgG, "\n%s circuitName\n\n", NOCUT ); M(MSG,NULL,YmsgG ) ; YexitPgm(PGMFAIL); } /* end syntax */ yaleIntro() { int i ; M( MSG, NULL, "\n") ; M( MSG, NULL, YmsgG) ; M( MSG, NULL, "\nTimberWolf System Floorplan Setup Program\n"); M( MSG, NULL, "Authors: Carl Sechen, Bill Swartz,\n"); M( MSG, NULL, " Yale University\n"); M( MSG, NULL, "\n"); } /* end yaleIntro */ graywolf-0.1.4+20170307gite1bf319/src/mincut/output.c000066400000000000000000000222631305746555600215630ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: output.c DESCRIPTION:This file accumulates data for TimberWolf system. CONTENTS: DATE: Apr 24, 1989 REVISIONS: May 24, 1989 - updated argument to YcurTime. May 15, 1990 - now add up cell area so that standard cell macros size will be the average macro size. Aug 3, 1990 - added port counting to output. Thu Apr 18 01:12:20 EDT 1991 - added more error checking. Wed Jun 12 13:40:11 CDT 1991 - added check for pins outside cell boundary. Wed Jul 24 21:06:02 CDT 1991 - added a more meaningful output error message. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) output.c version 1.1 7/30/91" ; #endif #include #include "globals.h" #include #include #include #include #define EXPECTEDNUMNETS 10009 typedef struct { BOOL io_signal ; char *net ; } NETBOX, *NETPTR ; static int objectS = 0 ; /* number of objects read */ static int celltypeS ; /* current cell type */ static DOUBLE total_cell_lenS = 0.0 ; static DOUBLE total_cell_heightS = 0.0; static DOUBLE total_areaS = 0.0 ; static DOUBLE core_areaS = 0.0 ; static DOUBLE average_cell_heightS ; static DOUBLE row_sepS ; static DOUBLE row_sep_absS ; static int total_std_cellS = 0 ; static char current_cellS[LRECL] ; /* the current cell name */ static char cur_pinnameS[LRECL] ; /* current pinname */ static YHASHPTR netTableS ; /* hash table for cross referencing nets */ /* *************************************************************** */ init() { /* get ready for parsing */ /* make hash table for nets */ netTableS = Yhash_table_create( EXPECTEDNUMNETS ) ; } /* end init */ addCell( celltype, cellname ) int celltype ; char *cellname ; { strcpy( current_cellS, cellname ) ; Ysafe_free( cellname ) ; /* passify the user */ if( (++objectS % 50) == 0 ){ sprintf( YmsgG, "Read %4d objects so far...\n", objectS ) ; M( MSG, NULL, YmsgG ) ; } celltypeS = celltype ; /* save for determining instances etc. */ } /* end addCell */ addNet( signal ) char *signal ; { NETPTR data ; if( strcmp( signal, "TW_PASS_THRU" ) == STRINGEQ ){ return ; /* not a net so return */ } if( data = (NETPTR) Yhash_search( netTableS, signal, NULL, FIND )){ /* this net now makes an io connection mark it as such */ switch( celltypeS ){ case HARDCELLTYPE: case SOFTCELLTYPE: case PADCELLTYPE: data->io_signal = TRUE ; break ; case STDCELLTYPE: break ; } } else { /* else a new net - load data holder */ data = (NETPTR) Ysafe_malloc( sizeof(NETBOX) ) ; data->net = signal ; switch( celltypeS ){ case HARDCELLTYPE: case SOFTCELLTYPE: case PADCELLTYPE: data->io_signal = TRUE ; break ; case STDCELLTYPE: data->io_signal = FALSE ; break ; } if( Yhash_search( netTableS, signal, (char *)data, ENTER )){ sprintf( YmsgG, "Trouble adding signal:%s to hash table\n", signal ) ; M(ERRMSG,"addNet",YmsgG ) ; } } } /* end addNet */ set_bbox( left, right, bottom, top ) INT left, right, bottom, top ; { DOUBLE width, height ; width = (DOUBLE) (right - left) ; total_cell_lenS += width ; height = (DOUBLE) (top - bottom) ; total_cell_heightS += height ; total_areaS += width * height ; core_areaS += width * (height + row_sep_absS) ; total_std_cellS++ ; } /* end set_bbox */ output( fp ) FILE *fp ; { INT g ; if( total_std_cellS > 0 ){ average_cell_heightS = total_cell_heightS / (DOUBLE) total_std_cellS ; } else { average_cell_heightS = 0.0 ; } core_areaS *= (row_sepS + 1.0) ; fprintf( stderr, "\n----------------------------\n" ) ; fprintf( stderr, "Total stdcells :%d\n", total_std_cellS ) ; fprintf( stderr, "Total cell width :%4.2le\n", total_cell_lenS ) ; fprintf( stderr, "Total cell height :%4.2le\n", total_cell_heightS ) ; fprintf( stderr, "Total cell area :%4.2le\n", total_areaS ) ; fprintf( stderr, "Total core area :%4.2le\n", core_areaS ) ; fprintf( stderr, "Average cell height:%4.2le\n\n", average_cell_heightS ) ; /* the first instance take as a rectangle - initially a square */ g = (INT) sqrt( core_areaS ) ; fprintf( fp, "cluster 1 name core\n" ) ; fprintf( fp, "corners 4 0 0 0 %d %d %d %d 0\n", g, g, g, g ) ; write_softpins( fp ) ; /* for the second instance use an L shape */ g = (INT) sqrt( core_areaS / 3.0 ) ; if( g > 2 ){ fprintf( fp, "instance core_L\n" ) ; fprintf( fp, "corners 6 " ) ; fprintf( fp, "0 0 " ) ; fprintf( fp, "0 %d ", 2*g ) ; fprintf( fp, "%d %d ", g, 2*g ) ; fprintf( fp, "%d %d ", g, g ) ; fprintf( fp, "%d %d ", 2*g, g ) ; fprintf( fp, "%d 0\n", 2*g ) ; write_softpins( fp ) ; } /* for the third instance use a T shape */ g = (INT) sqrt( core_areaS / 4.0 ) ; if( g > 2 ){ fprintf( fp, "instance core_T\n" ) ; fprintf( fp, "corners 8 " ) ; fprintf( fp, "%d 0 ", g ) ; fprintf( fp, "%d %d ", g, g ) ; fprintf( fp, "0 %d ", g ) ; fprintf( fp, "0 %d ", 2*g ) ; fprintf( fp, "%d %d ", 3*g, 2*g ) ; fprintf( fp, "%d %d ", 3*g, g ) ; fprintf( fp, "%d %d ", 2*g, g ) ; fprintf( fp, "%d 0\n", 2*g ) ; write_softpins( fp ) ; } #ifdef USHAPE /* for the third instance use a U shape */ g = (INT) sqrt( core_areaS / 5.0 ) ; if( g > 2 ){ fprintf( fp, "instance core_U\n" ) ; fprintf( fp, "corners 8 " ) ; fprintf( fp, "0 0 " ) ; fprintf( fp, "0 %d ", 2*g ) ; fprintf( fp, "%d %d ", g, 2*g ) ; fprintf( fp, "%d %d ", g, g ) ; fprintf( fp, "%d %d ", 2*g, g ) ; fprintf( fp, "%d %d ", 2*g, 2*g ) ; fprintf( fp, "%d %d ", 3*g, 2*g ) ; fprintf( fp, "%d 0\n", 3*g ) ; write_softpins( fp ) ; } #endif /* for the fourth instance use a modified L shape */ g = (INT) sqrt( core_areaS / 5.0 ) ; if( g > 2 ){ fprintf( fp, "instance core_L2\n" ) ; fprintf( fp, "corners 6 " ) ; fprintf( fp, "0 0 " ) ; fprintf( fp, "0 %d ", 2*g ) ; fprintf( fp, "%d %d ", 2*g, 2*g ) ; fprintf( fp, "%d %d ", 2*g, g ) ; fprintf( fp, "%d %d ", 3*g, g ) ; fprintf( fp, "%d 0\n", 3*g ) ; write_softpins( fp ) ; } } /* end output */ write_softpins( fp ) FILE *fp ; { YTABLEPTR thread ; NETPTR net ; int pin_count ; fprintf( fp, "asplb 0.5 aspub 2.0\n" ) ; fprintf( fp, "class 0 orientations 0 1 2 3 4 5 6 7\n") ; pin_count = 0 ; for( thread=netTableS->thread;thread;thread=thread->threadNext){ net = (NETPTR) thread->data ; if( net->io_signal ){ fprintf( fp, "softpin name pin%d signal %s\n", ++pin_count, net->net ) ; } } fprintf( fp, "\n" ) ; } /* end write_softpins */ read_par() { char input[LRECL] ; char *bufferptr ; char **tokens ; INT numtokens ; INT line ; BOOL onNotOff ; BOOL wildcard ; BOOL found ; found = FALSE ; Yreadpar_init( cktNameG, USER, TWSC, TRUE ) ; while( tokens = Yreadpar_next( &bufferptr, &line, &numtokens, &onNotOff, &wildcard )){ if( numtokens == 0 ){ /* skip over empty lines */ continue ; } if ((numtokens != 2) && (numtokens != 3)) { continue ; } if( strcmp( tokens[0], "rowSep" ) == STRINGEQ ){ row_sepS = atof( tokens[1] ) ; if (numtokens == 3) row_sep_absS = atof( tokens[2] ) ; found = TRUE ; } } if(!(found)){ M(WARNMSG, "read_par", "Couldn't find rowsep in parameter file\n" ) ; M(WARNMSG, NULL,"Using default of 1.0\n" ) ; row_sepS = 1.0 ; row_sep_absS = 0.0 ; } } /* end readpar */ update_stats( fp ) FILE *fp ; { fprintf( fp, "tot_length:%d\n", (INT)total_cell_lenS); fprintf( fp, "num_soft:1\n" ) ; fprintf( fp, "cell_height:%d\n", (INT) average_cell_heightS); } /* end update_stats */ graywolf-0.1.4+20170307gite1bf319/src/mincut/readcells.c000066400000000000000000001344001305746555600221560ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley) 01/20/90"; #endif #define YYBYACC 1 /* ----------------------------------------------------------------- FILE: readcells.c <- readcells.y <- readcells.l DESCRIPTION:This file contains the grammar (BNF) for the TimberWolfMC input file parser. The rules for lex are in readcells.l. The grammar for yacc is in readcells.y. The output of yacc (y.tab.c) is renamed to readcells.c CONTENTS: readcells( fp ) FILE *fp ; yyerror(s) char *s; yywrap() Note:readcells.c will also include the yacc parser. DATE: Aug 7, 1988 REVISIONS: Oct 27, 1988 - modified fixed and group cell code. Now accept designs without pads. Jan 29, 1989 - changed to msgG and added \n. Mar 6, 1989 - removed redundant string from padgroupname Mar 7, 1989 - now able to parse instance lists but don't process them. Mar 12, 1989 - changed group cell and supercell reference from integer to string to be easier for user. Mar 13, 1989 - added string to instance to tell them apart. Apr 24, 1989 - added standard cells to yacc. May 7, 1989 - corrected padgroup. May 11, 1989 - must have layer info for this flow. Jun 19, 1989 - added pin groups to syntax checker. Mar 39, 1990 - added new MC softpin syntax. Fri Jan 25 17:59:55 PST 1991 - added missing SC options. Thu Apr 18 01:14:09 EDT 1991 - added initial orient feature and reversed corners field. Also added more error checking and now context free language. Wed Jun 12 13:41:41 CDT 1991 - added check for pins outside boundary and fixed sidespace syntax. Wed Jul 3 13:19:19 CDT 1991 - now TimberWolf handles more than one unequiv pair. Wed Jul 24 21:07:46 CDT 1991 - added analog input to syntax. Tue Aug 13 12:57:00 CDT 1991 - now allow stdcells to have no pins and fixed mirror keyword prob. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) readcells.y version 1.4 5/22/92" ; #endif #include #include #include #include #include #include "globals.h" #undef REJECT #ifdef DEBUG #define YYDEBUG 1 /* condition compile for yacc debug */ /* #define LEXDEBUG 1 */ /* conditional compile for lex debug */ #ifdef LEXDEBUG /* two bugs in Yale version of lex */ #define allprint(x) fprintf( stdout, "%c\n", x ) #define sprint(x) fprintf( stdout, "%s\n", x ) #endif #endif /* DEBUG */ static int line_countS ; static char bufferS[LRECL] ; typedef union { INT ival ; char *string ; double fval ; } YYSTYPE; #define INTEGER 257 #define STRING 258 #define FLOAT 259 #define ADDEQUIV 260 #define APPROXFIXED 261 #define ASPLB 262 #define ASPUB 263 #define AT 264 #define BLOCK 265 #define BOTTOM 266 #define CELL 267 #define CELLGROUP 268 #define CLASS 269 #define CONNECT 270 #define CORNERS 271 #define EQUIV 272 #define FIXED 273 #define FROM 274 #define HARDCELL 275 #define INITIALLY 276 #define INSTANCE 277 #define LAYER 278 #define LEFT 279 #define NAME 280 #define NEIGHBORHOOD 281 #define NOMIRROR 282 #define NONFIXED 283 #define NOPERMUTE 284 #define OF 285 #define ORIENT 286 #define ORIENTATIONS 287 #define PAD 288 #define PADGROUP 289 #define PERMUTE 290 #define PIN 291 #define RESTRICT 292 #define RIGHT 293 #define RIGIDFIXED 294 #define SIDE 295 #define SIDESPACE 296 #define SIGNAL 297 #define SOFTCELL 298 #define SOFTPIN 299 #define STDCELL 300 #define SUPERGROUP 301 #define TOP 302 #define PINGROUP 303 #define ENDPINGROUP 304 #define SWAPGROUP 305 #define UNEQUIV 306 #define CELLOFFSET 307 #define ECO_ADDED_CELL 308 #define LEGALBLKCLASS 309 #define CURRENT 310 #define POWER 311 #define NO_LAYER_CHANGE 312 #define KEEPOUT 313 #define YYERRCODE 256 short yylhs[] = { -1, 0, 0, 4, 4, 6, 6, 8, 8, 8, 5, 5, 12, 12, 13, 13, 7, 7, 11, 11, 21, 21, 22, 22, 22, 22, 22, 22, 9, 9, 30, 30, 32, 32, 10, 10, 40, 40, 41, 41, 41, 33, 14, 14, 15, 16, 16, 29, 39, 17, 54, 54, 31, 31, 56, 18, 18, 25, 23, 60, 60, 24, 26, 61, 62, 62, 63, 28, 57, 57, 58, 58, 58, 58, 59, 59, 27, 19, 2, 3, 45, 49, 49, 51, 53, 34, 64, 64, 36, 37, 37, 65, 65, 46, 46, 42, 43, 43, 66, 66, 38, 38, 20, 20, 69, 69, 71, 71, 70, 70, 70, 70, 72, 72, 72, 67, 67, 76, 68, 68, 77, 73, 81, 82, 82, 87, 88, 88, 83, 83, 84, 84, 85, 85, 74, 74, 89, 75, 75, 90, 79, 79, 79, 91, 93, 92, 92, 94, 95, 96, 96, 44, 44, 97, 97, 98, 98, 99, 99, 78, 78, 100, 100, 48, 48, 48, 86, 80, 80, 101, 47, 47, 50, 50, 102, 102, 52, 52, 55, 55, 35, 35, 103, 103, 104, 105, 105, 1, 1, 1, }; short yylen[] = { 2, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 4, 5, 1, 2, 1, 1, 1, 1, 1, 1, 2, 3, 1, 3, 5, 4, 2, 3, 1, 3, 6, 5, 4, 2, 6, 5, 4, 4, 3, 4, 4, 3, 13, 14, 8, 14, 1, 0, 8, 2, 2, 1, 2, 1, 3, 1, 1, 2, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 4, 3, 3, 4, 4, 3, 2, 3, 2, 4, 3, 1, 2, 0, 2, 4, 1, 2, 1, 1, 1, 2, 0, 1, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2, 2, 1, 2, 3, 2, 3, 6, 5, 6, 2, 2, 2, 2, 3, 0, 2, 0, 2, 0, 1, 1, 2, 5, 1, 2, 5, 1, 2, 1, 2, 1, 1, 2, 3, 4, 0, 1, 3, 4, 3, 3, 1, 2, 2, 2, 0, 3, 1, 2, 0, 2, 3, 2, 0, 2, 1, 0, 3, 1, 2, 2, 2, 1, 2, 1, 2, 0, 1, 1, 2, 5, 2, 3, 1, 1, 1, }; short yydefred[] = { 0, 0, 0, 0, 0, 0, 0, 5, 7, 8, 9, 0, 0, 0, 188, 187, 189, 0, 0, 0, 0, 1, 0, 12, 0, 0, 0, 0, 6, 16, 0, 0, 69, 76, 0, 0, 0, 61, 0, 0, 0, 20, 22, 23, 24, 25, 26, 27, 0, 0, 54, 0, 0, 30, 0, 0, 0, 0, 0, 36, 49, 0, 0, 0, 0, 0, 13, 14, 0, 0, 0, 0, 17, 176, 0, 0, 0, 67, 57, 59, 0, 63, 0, 0, 0, 0, 21, 73, 70, 71, 72, 0, 0, 0, 0, 0, 0, 0, 0, 182, 0, 0, 0, 0, 0, 0, 47, 48, 0, 0, 15, 0, 0, 172, 0, 0, 0, 0, 0, 177, 0, 0, 0, 178, 0, 60, 66, 0, 64, 0, 0, 0, 18, 0, 104, 0, 111, 0, 0, 0, 0, 0, 41, 31, 0, 0, 183, 0, 0, 0, 0, 37, 80, 82, 81, 174, 175, 0, 0, 173, 94, 0, 84, 83, 88, 0, 0, 45, 0, 0, 179, 65, 0, 0, 0, 106, 0, 105, 0, 0, 0, 0, 134, 137, 0, 0, 0, 0, 19, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 91, 0, 78, 0, 0, 0, 0, 117, 107, 0, 0, 0, 0, 135, 138, 123, 125, 0, 0, 0, 0, 74, 75, 0, 87, 0, 0, 100, 0, 0, 0, 95, 0, 0, 96, 98, 99, 0, 169, 171, 0, 0, 0, 92, 90, 0, 0, 0, 0, 0, 0, 129, 0, 0, 126, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 165, 89, 0, 0, 0, 0, 0, 0, 0, 131, 133, 121, 127, 0, 185, 0, 0, 0, 0, 0, 0, 0, 0, 155, 0, 144, 0, 119, 0, 0, 0, 145, 0, 79, 0, 0, 0, 122, 166, 136, 139, 56, 186, 52, 0, 0, 154, 153, 0, 157, 158, 151, 156, 161, 0, 0, 0, 146, 143, 0, 0, 0, 77, 0, 0, 152, 162, 0, 150, 147, 0, 0, 0, 0, 120, 148, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 50, 0, 53, 51, }; short yydgoto[] = { 4, 294, 206, 307, 5, 21, 6, 27, 7, 8, 9, 10, 22, 65, 23, 67, 29, 11, 39, 84, 132, 40, 41, 42, 43, 44, 45, 46, 47, 12, 51, 52, 53, 94, 54, 97, 120, 167, 229, 13, 58, 59, 104, 236, 268, 24, 115, 158, 200, 68, 112, 30, 74, 31, 76, 124, 55, 48, 91, 226, 80, 82, 127, 128, 141, 204, 237, 230, 239, 133, 134, 174, 175, 231, 180, 181, 136, 240, 272, 300, 347, 137, 186, 221, 256, 284, 280, 187, 223, 182, 183, 301, 302, 303, 304, 305, 342, 270, 295, 296, 327, 242, 113, 98, 99, 261, }; short yysindex[] = { -221, -57, -57, -57, 0, -184, -188, 0, 0, 0, 0, -158, -125, -125, 0, 0, 0, -57, -179, -144, -57, 0, -93, 0, -108, -57, -57, -236, 0, 0, -57, -154, 0, 0, -51, -57, -47, 0, -45, -64, -158, 0, 0, 0, 0, 0, 0, 0, -139, -41, 0, -97, -108, 0, -96, -190, -108, -44, -97, 0, 0, -57, -57, -61, -57, -69, 0, 0, -57, -65, -58, -56, 0, 0, -70, -173, -57, 0, 0, 0, -34, 0, -32, -31, -201, -64, 0, 0, 0, 0, 0, -30, -29, -57, -108, -97, -49, -37, -96, 0, -26, -24, -97, -25, -37, -108, 0, 0, -57, -251, 0, -235, -216, 0, -22, -55, -57, -57, -19, 0, -205, -35, -17, 0, -57, 0, 0, -32, 0, -52, -36, -48, 0, -201, 0, -228, 0, -168, -201, -28, -15, -12, 0, 0, -10, -205, 0, -23, -21, -14, -205, 0, 0, 0, 0, 0, 0, -43, -42, 0, 0, -42, 0, 0, 0, -39, 1, 0, -2, -13, 0, 0, 2, -57, -174, 0, -228, 0, -20, -18, -9, -27, 0, 0, 7, 11, -53, 13, 0, -153, 0, 18, 16, -48, -2, -2, 10, -101, 19, 24, 0, -48, 1, 0, -227, 0, 27, -2, 20, -7, 0, 0, -9, -27, -57, -57, 0, 0, 0, 0, 26, -40, 50, 57, 0, 0, 3, 0, 59, -48, 0, -9, 64, 79, 0, -8, -122, 0, 0, 0, -16, 0, 0, 87, -48, -227, 0, 0, 4, 83, 95, -57, 60, 60, 0, 102, 51, 0, 108, 101, 114, 118, 0, -9, 103, 112, -57, -57, 73, 0, -57, 93, -135, 0, 0, 132, 122, 90, 60, 143, -168, -168, 0, 0, 0, 0, 145, 0, 157, 132, 132, 116, -99, -57, -164, -187, 0, 158, 0, 146, 0, 155, 155, -16, 0, -16, 0, 180, 132, 181, 0, 0, 0, 0, 0, 0, 0, 182, -57, 0, 0, -187, 0, 0, 0, 0, 0, 186, -57, 155, 0, 0, 165, 171, 189, 0, 176, 175, 0, 0, 175, 0, 0, -2, 190, -2, 195, 0, 0, 216, -2, 219, 0, 206, 225, 221, 132, 226, 132, 0, 132, 0, 0, }; short yyrindex[] = { 0, 0, 0, 0, 0, 490, 17, 0, 0, 0, 0, -140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 501, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 247, 0, 0, 0, 566, 0, 0, 0, 0, 0, 0, 517, 0, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -141, 0, 0, 0, 584, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 588, 0, 0, 251, 0, 0, 0, 602, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 178, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, -100, 0, 0, 0, 0, 0, 620, 0, 411, 0, 0, 584, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -134, 0, 0, 0, 436, 440, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 487, 0, 0, 0, 493, 0, 0, 0, 37, 0, 0, 458, 0, 0, 0, 0, 0, 0, 0, -129, -120, 0, 0, 0, 0, 0, 0, 0, 81, 0, 31, 0, 0, 0, 0, 0, 515, 0, 230, 0, 0, 0, 0, 542, 0, 0, 0, 211, 0, 0, 489, 62, 458, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, 0, 0, 0, -256, 0, 255, 0, 0, 0, 0, 547, 0, 0, 0, 292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 339, 364, 273, 0, 236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 131, 0, 389, 0, 0, 310, 0, 0, 0, 0, 156, 0, 0, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; short yygindex[] = { 0, -1, -185, -263, 0, 0, 0, 0, 519, 0, 0, 0, 0, 0, 504, 471, 511, 0, 509, 466, 414, 0, 522, 0, 0, 0, 0, 0, 0, 0, 503, 544, 469, -38, -6, 0, 55, 47, 367, 0, 514, 460, 0, 0, 0, 0, -176, 464, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 448, 0, 379, 350, -189, 0, 0, 459, 0, 415, -80, -165, 418, 0, 0, -207, 0, 256, 0, -77, 0, 0, 0, -170, 0, 0, -177, -145, 0, 296, 0, -217, 0, 0, 331, 307, -272, 0, 0, 491, 0, 506, 0, }; #define YYTABLESIZE 921 short yytable[] = { 17, 18, 19, 216, 135, 85, 163, 57, 238, 232, 233, 212, 46, 184, 28, 170, 60, 3, 69, 63, 105, 4, 249, 325, 70, 71, 316, 317, 247, 73, 246, 124, 25, 153, 78, 216, 217, 43, 155, 154, 262, 14, 15, 16, 178, 334, 1, 238, 156, 325, 57, 176, 165, 135, 2, 262, 128, 184, 135, 114, 106, 107, 42, 109, 105, 26, 263, 111, 217, 274, 14, 15, 16, 119, 100, 123, 157, 3, 179, 1, 25, 130, 166, 281, 121, 330, 216, 2, 324, 184, 130, 101, 142, 359, 176, 361, 331, 362, 332, 57, 122, 61, 131, 185, 20, 271, 132, 152, 310, 322, 3, 111, 330, 26, 338, 162, 163, 130, 32, 323, 58, 68, 87, 170, 33, 298, 224, 75, 34, 93, 210, 160, 58, 68, 88, 58, 62, 299, 58, 55, 225, 58, 58, 68, 89, 58, 49, 35, 50, 36, 37, 38, 145, 58, 68, 90, 167, 112, 349, 150, 351, 62, 113, 49, 58, 354, 58, 58, 58, 130, 112, 114, 209, 62, 159, 113, 62, 235, 170, 62, 93, 267, 62, 62, 114, 319, 62, 14, 15, 16, 130, 320, 193, 167, 62, 20, 64, 197, 235, 118, 14, 15, 16, 312, 313, 62, 77, 62, 62, 62, 79, 159, 81, 252, 253, 83, 92, 96, 103, 108, 64, 114, 116, 125, 117, 126, 129, 139, 140, 144, 115, 147, 118, 148, 149, 160, 159, 157, 164, 168, 169, 172, 190, 130, 173, 191, 189, 192, 202, 196, 278, 194, 198, 195, 199, 116, 205, 220, 203, 208, 214, 207, 215, 178, 218, 291, 292, 85, 219, 234, 222, 255, 266, 159, 85, 227, 271, 241, 275, 179, 46, 28, 28, 243, 248, 254, 250, 228, 259, 28, 251, 85, 118, 85, 85, 163, 85, 85, 124, 124, 46, 85, 28, 124, 170, 3, 124, 257, 124, 4, 149, 170, 28, 46, 258, 28, 260, 337, 85, 124, 124, 264, 124, 128, 128, 43, 43, 340, 128, 124, 124, 128, 124, 128, 124, 124, 265, 124, 279, 140, 276, 124, 124, 124, 128, 128, 273, 128, 130, 130, 42, 42, 277, 130, 128, 128, 130, 128, 130, 128, 128, 282, 128, 283, 142, 285, 286, 128, 128, 130, 130, 287, 130, 132, 132, 288, 267, 289, 132, 130, 130, 132, 130, 132, 130, 130, 290, 130, 297, 141, 306, 160, 309, 130, 132, 132, 308, 132, 160, 160, 311, 160, 314, 160, 132, 132, 160, 132, 160, 132, 132, 108, 132, 318, 315, 326, 167, 93, 93, 160, 93, 93, 160, 167, 167, 93, 328, 299, 167, 160, 160, 167, 160, 167, 160, 341, 109, 333, 335, 336, 110, 159, 159, 339, 167, 343, 344, 167, 167, 159, 345, 159, 352, 346, 167, 167, 163, 167, 93, 167, 167, 167, 159, 167, 350, 167, 170, 170, 167, 170, 167, 159, 159, 353, 170, 159, 355, 159, 159, 159, 356, 167, 357, 159, 167, 167, 159, 33, 159, 164, 2, 167, 167, 40, 167, 358, 167, 115, 115, 159, 360, 10, 159, 159, 159, 115, 159, 115, 159, 159, 159, 159, 159, 159, 159, 32, 180, 11, 115, 115, 181, 115, 116, 116, 159, 28, 66, 159, 115, 115, 116, 115, 116, 115, 159, 159, 110, 159, 72, 159, 159, 159, 39, 116, 116, 159, 116, 38, 159, 85, 159, 138, 188, 116, 116, 95, 116, 56, 116, 118, 118, 159, 86, 143, 159, 151, 34, 118, 244, 118, 102, 159, 159, 201, 159, 171, 159, 149, 149, 161, 118, 245, 149, 118, 102, 149, 269, 149, 29, 211, 118, 118, 177, 118, 213, 118, 348, 329, 149, 293, 321, 149, 35, 159, 146, 0, 140, 140, 149, 149, 0, 149, 0, 149, 140, 0, 140, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 140, 0, 0, 140, 142, 142, 0, 0, 0, 0, 140, 140, 142, 140, 142, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 0, 0, 142, 141, 141, 0, 0, 0, 0, 142, 142, 141, 142, 141, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 108, 108, 141, 0, 0, 0, 0, 0, 108, 141, 141, 0, 141, 0, 141, 0, 0, 0, 0, 0, 0, 108, 0, 0, 108, 109, 109, 0, 0, 110, 110, 108, 0, 109, 108, 0, 108, 110, 0, 0, 0, 0, 0, 0, 0, 0, 109, 93, 93, 109, 110, 0, 0, 110, 0, 93, 109, 93, 0, 109, 110, 109, 0, 110, 0, 110, 163, 163, 93, 163, 0, 93, 0, 0, 0, 0, 33, 33, 93, 93, 0, 93, 40, 40, 33, 0, 33, 0, 0, 0, 40, 0, 40, 0, 0, 0, 0, 33, 0, 164, 164, 0, 164, 40, 32, 32, 0, 33, 0, 0, 33, 0, 32, 40, 32, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 39, 39, 0, 0, 32, 38, 38, 32, 39, 0, 39, 0, 0, 38, 0, 38, 0, 0, 0, 0, 0, 39, 0, 0, 34, 34, 38, 0, 0, 0, 0, 39, 34, 0, 39, 0, 38, 0, 0, 38, 0, 0, 102, 102, 0, 34, 29, 29, 0, 0, 102, 0, 0, 0, 29, 34, 0, 0, 34, 0, 35, 35, 0, 102, 0, 0, 0, 29, 35, 0, 0, 0, 0, 102, 0, 0, 102, 29, 103, 103, 29, 35, 0, 0, 0, 0, 103, 0, 0, 0, 0, 35, 0, 0, 35, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 103, }; short yycheck[] = { 1, 2, 3, 180, 84, 0, 0, 13, 197, 194, 195, 176, 0, 269, 0, 0, 17, 0, 24, 20, 58, 0, 207, 295, 25, 26, 289, 290, 204, 30, 257, 0, 268, 284, 35, 212, 181, 0, 273, 290, 229, 257, 258, 259, 272, 308, 267, 236, 283, 321, 56, 131, 257, 133, 275, 244, 0, 313, 138, 286, 61, 62, 0, 64, 102, 301, 231, 68, 213, 245, 257, 258, 259, 74, 264, 76, 292, 298, 306, 267, 268, 0, 287, 253, 257, 302, 263, 275, 295, 257, 291, 281, 93, 356, 174, 358, 303, 360, 305, 105, 273, 280, 303, 271, 288, 292, 0, 108, 278, 273, 298, 112, 329, 301, 321, 116, 117, 291, 276, 283, 261, 261, 261, 124, 282, 260, 279, 281, 286, 0, 304, 0, 273, 273, 273, 276, 280, 272, 279, 279, 293, 282, 283, 283, 283, 286, 271, 305, 273, 307, 308, 309, 97, 294, 294, 294, 0, 291, 343, 104, 345, 261, 291, 271, 305, 350, 307, 308, 309, 291, 304, 291, 173, 273, 0, 304, 276, 299, 0, 279, 277, 303, 282, 283, 304, 284, 286, 257, 258, 259, 291, 290, 145, 0, 294, 288, 289, 150, 299, 269, 257, 258, 259, 280, 281, 305, 257, 307, 308, 309, 257, 0, 257, 214, 215, 279, 257, 313, 262, 280, 289, 286, 280, 257, 280, 257, 257, 257, 257, 278, 0, 257, 269, 257, 259, 257, 0, 292, 257, 274, 257, 293, 257, 291, 280, 257, 274, 257, 287, 263, 251, 274, 295, 274, 296, 0, 258, 310, 257, 257, 280, 274, 280, 272, 257, 266, 267, 262, 257, 259, 257, 311, 280, 0, 269, 257, 292, 258, 274, 306, 268, 267, 268, 259, 257, 259, 266, 271, 285, 275, 297, 286, 0, 288, 289, 289, 291, 292, 267, 268, 288, 296, 288, 272, 289, 288, 275, 257, 277, 288, 0, 296, 298, 301, 257, 301, 257, 318, 313, 288, 289, 257, 291, 267, 268, 288, 289, 328, 272, 298, 299, 275, 301, 277, 303, 304, 257, 306, 278, 0, 257, 310, 311, 312, 288, 289, 259, 291, 267, 268, 288, 289, 257, 272, 298, 299, 275, 301, 277, 303, 304, 259, 306, 312, 0, 257, 265, 311, 312, 288, 289, 257, 291, 267, 268, 257, 303, 274, 272, 298, 299, 275, 301, 277, 303, 304, 274, 306, 295, 0, 258, 260, 302, 312, 288, 289, 274, 291, 267, 268, 257, 270, 257, 272, 298, 299, 275, 301, 277, 303, 304, 0, 306, 297, 257, 257, 260, 288, 289, 288, 291, 292, 291, 267, 268, 296, 280, 272, 272, 298, 299, 275, 301, 277, 303, 270, 0, 257, 257, 257, 0, 267, 268, 257, 288, 274, 257, 291, 292, 275, 274, 277, 257, 278, 298, 299, 0, 301, 0, 303, 267, 268, 288, 270, 274, 272, 288, 289, 275, 291, 277, 260, 298, 257, 296, 301, 257, 303, 267, 268, 274, 288, 257, 272, 291, 292, 275, 0, 277, 0, 0, 298, 299, 0, 301, 274, 303, 267, 268, 288, 274, 0, 291, 267, 268, 275, 270, 277, 272, 298, 299, 275, 301, 277, 303, 0, 269, 0, 288, 289, 269, 291, 267, 268, 288, 6, 22, 291, 298, 299, 275, 301, 277, 303, 298, 299, 65, 301, 27, 303, 267, 268, 0, 288, 289, 272, 291, 0, 275, 40, 277, 85, 138, 298, 299, 52, 301, 13, 303, 267, 268, 288, 40, 94, 291, 105, 0, 275, 201, 277, 56, 298, 299, 161, 301, 127, 303, 267, 268, 115, 288, 202, 272, 291, 0, 275, 236, 277, 0, 174, 298, 299, 133, 301, 176, 303, 340, 301, 288, 268, 293, 291, 0, 112, 98, -1, 267, 268, 298, 299, -1, 301, -1, 303, 275, -1, 277, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 288, -1, -1, 291, 267, 268, -1, -1, -1, -1, 298, 299, 275, 301, 277, 303, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, -1, -1, 291, 267, 268, -1, -1, -1, -1, 298, 299, 275, 301, 277, 303, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, 267, 268, 291, -1, -1, -1, -1, -1, 275, 298, 299, -1, 301, -1, 303, -1, -1, -1, -1, -1, -1, 288, -1, -1, 291, 267, 268, -1, -1, 267, 268, 298, -1, 275, 301, -1, 303, 275, -1, -1, -1, -1, -1, -1, -1, -1, 288, 267, 268, 291, 288, -1, -1, 291, -1, 275, 298, 277, -1, 301, 298, 303, -1, 301, -1, 303, 288, 289, 288, 291, -1, 291, -1, -1, -1, -1, 267, 268, 298, 299, -1, 301, 267, 268, 275, -1, 277, -1, -1, -1, 275, -1, 277, -1, -1, -1, -1, 288, -1, 288, 289, -1, 291, 288, 267, 268, -1, 298, -1, -1, 301, -1, 275, 298, 277, -1, 301, -1, -1, -1, -1, -1, -1, -1, -1, 288, -1, -1, -1, -1, -1, 267, 268, -1, -1, 298, 267, 268, 301, 275, -1, 277, -1, -1, 275, -1, 277, -1, -1, -1, -1, -1, 288, -1, -1, 267, 268, 288, -1, -1, -1, -1, 298, 275, -1, 301, -1, 298, -1, -1, 301, -1, -1, 267, 268, -1, 288, 267, 268, -1, -1, 275, -1, -1, -1, 275, 298, -1, -1, 301, -1, 267, 268, -1, 288, -1, -1, -1, 288, 275, -1, -1, -1, -1, 298, -1, -1, 301, 298, 267, 268, 301, 288, -1, -1, -1, -1, 275, -1, -1, -1, -1, 298, -1, -1, 301, -1, -1, -1, -1, 288, -1, -1, -1, -1, -1, -1, -1, -1, -1, 298, -1, -1, 301, }; #define YYFINAL 4 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 313 #if YYDEBUG char *yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"INTEGER","STRING","FLOAT", "ADDEQUIV","APPROXFIXED","ASPLB","ASPUB","AT","BLOCK","BOTTOM","CELL", "CELLGROUP","CLASS","CONNECT","CORNERS","EQUIV","FIXED","FROM","HARDCELL", "INITIALLY","INSTANCE","LAYER","LEFT","NAME","NEIGHBORHOOD","NOMIRROR", "NONFIXED","NOPERMUTE","OF","ORIENT","ORIENTATIONS","PAD","PADGROUP","PERMUTE", "PIN","RESTRICT","RIGHT","RIGIDFIXED","SIDE","SIDESPACE","SIGNAL","SOFTCELL", "SOFTPIN","STDCELL","SUPERGROUP","TOP","PINGROUP","ENDPINGROUP","SWAPGROUP", "UNEQUIV","CELLOFFSET","ECO_ADDED_CELL","LEGALBLKCLASS","CURRENT","POWER", "NO_LAYER_CHANGE","KEEPOUT", }; char *yyrule[] = { "$accept : start_file", "start_file : core pads", "start_file : core", "core : corecells", "core : corecells cellgroups", "corecells : coretype", "corecells : corecells coretype", "coretype : hardcell", "coretype : softcell", "coretype : stdcell", "pads : padcells", "pads : padcells padgroups", "padcells : padcell", "padcells : padcells padcell", "padgroups : padgroup", "padgroups : padgroups padgroup", "cellgroups : cellgroup", "cellgroups : cellgroups cellgroup", "stdcell : cellname std_fixed bbox pinlist", "stdcell : cellname optional_list std_fixed bbox pinlist", "optional_list : option", "optional_list : optional_list option", "option : celloffset", "option : eco", "option : swap_group", "option : legal_block_classes", "option : mirror", "option : initial_orient", "hardcell : hardcellname custom_instance_list", "hardcell : hardcellname fixed custom_instance_list", "custom_instance_list : custom_instance", "custom_instance_list : custom_instance_list instance custom_instance", "custom_instance : corners keep_outs class orient hardpins", "custom_instance : corners keep_outs class orient", "softcell : softname soft_instance_list", "softcell : softname fixed soft_instance_list", "soft_instance_list : soft_instance", "soft_instance_list : soft_instance_list instance soft_instance", "soft_instance : corners aspect class orient softpins mc_pingroup", "soft_instance : corners aspect class orient softpins", "soft_instance : corners aspect class orient", "instance : INSTANCE string", "padcell : padname corners cur_orient restriction sidespace hardpins", "padcell : padname corners cur_orient restriction sidespace", "padgroup : padgroupname padgrouplist restriction sidespace", "cellgroup : supergroupname supergrouplist class orient", "cellgroup : cellgroupname neighborhood cellgrouplist", "hardcellname : HARDCELL string NAME string", "softname : SOFTCELL string NAME string", "cellname : CELL string string", "neighborhood : NEIGHBORHOOD INTEGER FROM xloc INTEGER FROM yloc INTEGER FROM xloc INTEGER FROM yloc", "neighborhood : NEIGHBORHOOD FIXED INTEGER FROM xloc INTEGER FROM yloc INTEGER FROM xloc INTEGER FROM yloc", "fixed : fixedcontext AT INTEGER FROM xloc INTEGER FROM yloc", "fixed : fixedcontext NEIGHBORHOOD INTEGER FROM xloc INTEGER FROM yloc INTEGER FROM xloc INTEGER FROM yloc", "fixedcontext : FIXED", "std_fixed :", "std_fixed : initially fixed_type INTEGER FROM fixed_loc OF BLOCK INTEGER", "swap_group : SWAPGROUP string", "celloffset : CELLOFFSET offset_list", "offset_list : INTEGER", "offset_list : offset_list INTEGER", "eco : ECO_ADDED_CELL", "legal_block_classes : LEGALBLKCLASS num_block_classes block_classes", "num_block_classes : INTEGER", "block_classes : block_class", "block_classes : block_classes block_class", "block_class : INTEGER", "initial_orient : ORIENT INTEGER", "initially :", "initially : INITIALLY", "fixed_type : FIXED", "fixed_type : NONFIXED", "fixed_type : RIGIDFIXED", "fixed_type : APPROXFIXED", "fixed_loc : LEFT", "fixed_loc : RIGHT", "mirror : NOMIRROR", "bbox : LEFT INTEGER RIGHT INTEGER BOTTOM INTEGER TOP INTEGER", "xloc : STRING", "yloc : STRING", "padname : PAD string NAME string", "padgroupname : PADGROUP string PERMUTE", "padgroupname : PADGROUP string NOPERMUTE", "supergroupname : SUPERGROUP string NAME string", "cellgroupname : CELLGROUP string NAME string", "corners : CORNERS INTEGER cornerpts", "cornerpts : INTEGER INTEGER", "cornerpts : cornerpts INTEGER INTEGER", "class : CLASS INTEGER", "orient : INTEGER ORIENTATIONS orientlist cur_orient", "orient : ORIENTATIONS orientlist cur_orient", "orientlist : INTEGER", "orientlist : orientlist INTEGER", "cur_orient :", "cur_orient : ORIENT INTEGER", "aspect : ASPLB FLOAT ASPUB FLOAT", "softpins : softtype", "softpins : softpins softtype", "softtype : pintype", "softtype : softpin", "hardpins : pintype", "hardpins : hardpins pintype", "pinlist :", "pinlist : stdgrppins", "stdgrppins : std_grppintype", "stdgrppins : stdgrppins std_grppintype", "stdpins : std_pintype", "stdpins : stdpins std_pintype", "std_grppintype : pinrecord", "std_grppintype : pinrecord equiv_list", "std_grppintype : pinrecord unequiv_list", "std_grppintype : pingroup", "std_pintype : pinrecord", "std_pintype : pinrecord equiv_list", "std_pintype : pinrecord unequiv_list", "pintype : pinrecord", "pintype : pinrecord equiv_list", "pingroup : PINGROUP stdpins ENDPINGROUP", "softpin : softpin_info siderestriction", "softpin : softpin_info siderestriction softequivs", "softpin_info : SOFTPIN NAME string SIGNAL string opt_layer", "pinrecord : required_pinfo contour current power no_layer_change", "required_pinfo : PIN NAME string SIGNAL string layer", "contour : INTEGER INTEGER", "contour : num_corners pin_pts", "num_corners : CORNERS INTEGER", "pin_pts : INTEGER INTEGER", "pin_pts : pin_pts INTEGER INTEGER", "current :", "current : CURRENT FLOAT", "power :", "power : POWER FLOAT", "no_layer_change :", "no_layer_change : NO_LAYER_CHANGE", "equiv_list : equiv", "equiv_list : equiv_list equiv", "equiv : EQUIV NAME string layer contour", "unequiv_list : unequiv", "unequiv_list : unequiv_list unequiv", "unequiv : UNEQUIV NAME string layer contour", "softequivs : mc_equiv", "softequivs : mc_equiv user_equiv_list", "softequivs : user_equiv_list", "mc_equiv : addequiv siderestriction", "addequiv : ADDEQUIV", "user_equiv_list : user_equiv", "user_equiv_list : user_equiv_list user_equiv", "user_equiv : equiv_name siderestriction connect", "equiv_name : EQUIV NAME string opt_layer", "connect :", "connect : CONNECT", "mc_pingroup : pingroupname pingrouplist siderestriction", "mc_pingroup : mc_pingroup pingroupname pingrouplist siderestriction", "pingroupname : PINGROUP string PERMUTE", "pingroupname : PINGROUP string NOPERMUTE", "pingrouplist : pinset", "pingrouplist : pingrouplist pinset", "pinset : string FIXED", "pinset : string NONFIXED", "siderestriction :", "siderestriction : RESTRICT SIDE side_list", "side_list : INTEGER", "side_list : side_list INTEGER", "sidespace :", "sidespace : SIDESPACE FLOAT", "sidespace : SIDESPACE FLOAT FLOAT", "layer : LAYER INTEGER", "opt_layer :", "opt_layer : LAYER INTEGER", "sideplace : STRING", "restriction :", "restriction : RESTRICT SIDE sideplace", "padgrouplist : padset", "padgrouplist : padgrouplist padset", "padset : string FIXED", "padset : string NONFIXED", "supergrouplist : string", "supergrouplist : supergrouplist string", "cellgrouplist : string", "cellgrouplist : cellgrouplist string", "keep_outs :", "keep_outs : keep_out_list", "keep_out_list : keep_out", "keep_out_list : keep_out_list keep_out", "keep_out : KEEPOUT LAYER INTEGER CORNERS keep_pts", "keep_pts : INTEGER INTEGER", "keep_pts : keep_pts INTEGER INTEGER", "string : STRING", "string : INTEGER", "string : FLOAT", }; #endif #define yyclearin (yychar=(-1)) #define yyerrok (yyerrflag=0) #ifdef YYSTACKSIZE #ifndef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #endif #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 500 #define YYMAXDEPTH 500 #endif #endif int yycnprs = 0; int yydebug; int yynerrs; int yyerrflag; int yychar; short *yyssp; YYSTYPE *yyvsp; YYSTYPE yyval; YYSTYPE yylval; short yyss[YYSTACKSIZE]; YYSTYPE yyvs[YYSTACKSIZE]; #define yystacksize YYSTACKSIZE #include "readcells_l.h" /* add readcells_l.h for debug purposes */ /* ********************* #include "readcells_l.h" *******************/ /* ********************* #include "readcells_l.h" *******************/ readcells( fp ) FILE *fp ; { #ifdef YYDEBUG extern int yydebug ; yydebug = FALSE ; D( "syntax/readcells", yydebug = TRUE ; ) ; #endif yyin = fp ; line_countS = 0 ; init() ; /* parse input file using yacc */ yyparse(); } /* end readcells */ yyerror(s) char *s; { sprintf(YmsgG,"problem reading %s.cel:", cktNameG ); M( ERRMSG, "yacc", YmsgG ) ; sprintf(YmsgG, " line %d near '%s' : %s\n" , line_countS+1, yytext, s ); M( MSG,"yacc", YmsgG ) ; } /* end yyerror */ yywrap() { return(1); } #define YYABORT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int yyparse() { register int yym, yyn, yystate; #if YYDEBUG register char *yys; extern char *getenv(); if (yys = getenv("YYDEBUG")) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = (-1); yyssp = yyss; yyvsp = yyvs; *yyssp = yystate = 0; yyloop: if (yyn = yydefred[yystate]) goto yyreduce; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, shifting to state %d\n", yystate, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; #ifdef lint goto yynewerror; #endif yynewerror: #if YYDEBUG { int test_state, i, expect, two_or_more ; char err_msg[BUFSIZ] ; if( yyname[yychar] ){ sprintf( err_msg, "Found %s.\nExpected ", yyname[yychar] ) ; two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } yyerror( err_msg ) ; if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } } else { sprintf( err_msg, "Found unknown token.\nExpected "); two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } yyerror( err_msg ) ; if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } } } #else yyerror("syntax error"); if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } #endif #ifdef lint goto yyerrlab; #endif yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, error recovery shifting\ to state %d\n", *yyssp, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("yydebug: error recovery discarding state %d\n", *yyssp); #endif if (yyssp <= yyss) goto yyabort; --yyssp; --yyvsp; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, error recovery discards token %d (%s)\n", yystate, yychar, yys); } #endif yychar = (-1); goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("yydebug: state %d, reducing by rule %d (%s)\n", yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; yyval = yyvsp[1-yym]; switch (yyn) { case 33: { sprintf( YmsgG, "hardcell at line %d does not have any pins\n", line_countS+1 ) ; M(WARNMSG,"readcells",YmsgG ) ; } break; case 40: { sprintf( YmsgG, "softcell at line %d does not have any pins\n", line_countS+1 ) ; M(WARNMSG,"readcells",YmsgG ) ; } break; case 41: { Ysafe_free( yyvsp[0].string ) ; } break; case 43: { sprintf( YmsgG, "pad cell at line %d does not have any pins\n", line_countS+1 ) ; M(WARNMSG,"readcells",YmsgG ) ; } break; case 47: { addCell(HARDCELLTYPE, yyvsp[0].string ) ; Ysafe_free( yyvsp[-2].string ) ; } break; case 48: { addCell(SOFTCELLTYPE, yyvsp[0].string ) ; Ysafe_free( yyvsp[-2].string ) ; } break; case 49: { addCell(STDCELLTYPE, yyvsp[0].string ) ; Ysafe_free( yyvsp[-1].string ) ; } break; case 77: { set_bbox( yyvsp[-6].ival, yyvsp[-4].ival, yyvsp[-2].ival, yyvsp[0].ival ) ; } break; case 80: { addCell(PADCELLTYPE, yyvsp[0].string ) ; Ysafe_free( yyvsp[-2].string ) ; } break; case 81: { addCell(PADCELLTYPE, yyvsp[-1].string ) ; } break; case 82: { addCell(PADCELLTYPE, yyvsp[-1].string ) ; } break; case 83: { Ysafe_free( yyvsp[-2].string ) ; Ysafe_free( yyvsp[0].string ) ; } break; case 84: { /* fixed locations same as pad context */ Ysafe_free( yyvsp[-2].string ) ; Ysafe_free( yyvsp[0].string ) ; } break; case 120: { Ysafe_free( yyvsp[-3].string ) ; addNet( yyvsp[-1].string ) ; } break; case 122: { addNet( yyvsp[-1].string ) ; } break; case 174: { Ysafe_free( yyvsp[-1].string ) ; } break; case 175: { Ysafe_free( yyvsp[-1].string ) ; } break; case 176: { Ysafe_free( yyvsp[0].string ) ; } break; case 177: { Ysafe_free( yyvsp[0].string ) ; } break; case 178: { Ysafe_free( yyvsp[0].string ) ; } break; case 179: { Ysafe_free( yyvsp[0].string ) ; } break; case 187: { yyval.string = yyvsp[0].string ; } break; case 188: { /* convert integer to string */ /* this allows integers to be used as strings */ /* a kluge but timberwolf's old parser supported it */ sprintf( bufferS,"%d", yyvsp[0].ival ) ; /* now clone string */ yyval.string = Ystrclone( bufferS ) ; } break; case 189: { /* convert float to string */ /* this allows floats to be used as strings */ /* a kluge but timberwolf's old parser supported it */ sprintf( bufferS,"%f", yyvsp[0].fval ) ; /* now clone string */ yyval.string = Ystrclone( bufferS ) ; } break; } yyssp -= yym; yystate = *yyssp; yyvsp -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state 0 to\ state %d\n", YYFINAL); #endif yystate = YYFINAL; *++yyssp = YYFINAL; *++yyvsp = yyval; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state %d \ to state %d\n", *yyssp, yystate); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate; *++yyvsp = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: return (1); yyaccept: return (0); } graywolf-0.1.4+20170307gite1bf319/src/mincut/readcells_l.h000066400000000000000000000414631305746555600225040ustar00rootroot00000000000000#ifdef linux #include #else # include "stdio.h" #endif # define U(x) ((x)&0377) # define NLSTATE yyprevious=YYNEWLINE # define BEGIN yybgin = yysvec + 1 + # define INITIAL 0 # define YYLERR yysvec # define YYSTATE (yyestate-yysvec-1) # define YYOPTIM 1 # define YYLMAX 200 # define output(c) putc(c,yyout) # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} # define yymore() (yymorfg=1) # define ECHO fprintf(yyout, "%s",yytext) # define REJECT { nstr = yyreject(); goto yyfussy;} int yyleng; extern char yytext[]; int yymorfg; extern char *yysptr, yysbuf[]; int yytchar; #ifdef linux FILE *yyin =(FILE *)NULL, *yyout =(FILE *)NULL; #else FILE *yyin ={stdin}, *yyout ={stdout}; #endif extern int yylineno; struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops;}; struct yysvf *yyestate; extern struct yysvf yysvec[], *yybgin; /* ----------------------------------------------------------------- FILE: readcells.l DESCRIPTION:rules for lexical analyzer for syntax checker. This lexical analyzer uses a binary search to reduce the size of the f.a. generated by lex. Thanks to Gary Richey who showed me the trick. See chapter 3 of "Introduction to Compiler Construction with UNIX" by Schreiner & Friedman for more details. CONTENTS: lex rules - screen() DATE: Aug 07, 1988 - need to add SccsId in comments due to yacc static char SccsId[] = "@(#) readcells.l version 1.2 5/22/92" ; REVISIONS: Oct 6, 1988 - fixed sign mistake in INTEGER & FLOAT Feb 12, 1989 - added <> to alphanum to handle DEC case. Apr 4, 1989 - added comments over multiple lines. May 7, 1989 - corrected pad groups. Jun 19, 1989 - added pin groups to syntax. Nov 5, 1989 - Fixed problem with sign - now ? (0 or 1 occurences) instead of * (0 or more). Mar 29, 1990 - added new MC softpin syntax. Fri Jan 25 17:58:05 PST 1991 - added missing SC keywords and added new alphanum. Fri Mar 22 20:18:19 CST 1991 - made letter more general. Thu Apr 18 01:13:03 EDT 1991 - removed unneeded tokens. Wed Jul 24 21:07:46 CDT 1991 - added analog input to syntax. ----------------------------------------------------------------- */ #undef YYLMAX #define YYLMAX 2000 /* comments may be at most 2000 characters */ #define token(x) x /* makes it look like regular lex */ #define END(v) (v-1 + sizeof(v) / sizeof( v[0] ) ) /* for table lookup */ static int screen() ; static int check_line_count() ; # define YYNEWLINE 10 yylex(){ int nstr; extern int yyprevious; while((nstr = yylook()) >= 0) yyfussy: switch(nstr){ case 0: if(yywrap()) return(0); break; case 1: { /* C-style comments over multiple lines */ check_line_count(yytext) ; } break; case 2: { /* convert to an integer */ yylval.ival = atoi( yytext ) ; return (INTEGER); } break; case 3: { /* convert to an float */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 4: { /* convert to an float */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 5: { return( screen() ) ; } break; case 6: { line_countS++;} break; case 7: ; break; case 8: { return( token(yytext[0]) ) ;} break; case -1: break; default: fprintf(yyout,"bad switch yylook %d",nstr); } return(0); } /* end of yylex */ /* reserved word screener */ /* ----------------------------------------------------------------- The following is table of the reserved words - Table must be in alphabetical order for binary search to work properly. ----------------------------------------------------------------- */ static struct rw_table { /* reserved word table */ char *rw_name ; /* pattern */ int rw_yylex ; /* lex token number */ } rwtable[] = { "ECO_added_cell", token(ECO_ADDED_CELL), "addequiv", token(ADDEQUIV), "approximately_fixed", token(APPROXFIXED), "asplb", token(ASPLB), "aspub", token(ASPUB), "at", token(AT), "block", token(BLOCK), "bottom", token(BOTTOM), "cell", token(CELL), "cell_offset", token(CELLOFFSET), "cellgroup", token(CELLGROUP), "class", token(CLASS), "connect", token(CONNECT), "corners", token(CORNERS), "current", token(CURRENT), "end_pin_group", token(ENDPINGROUP), "equiv", token(EQUIV), "fixed", token(FIXED), "from", token(FROM), "hardcell", token(HARDCELL), "initially", token(INITIALLY), "instance", token(INSTANCE), "keepout", token(KEEPOUT), "layer", token(LAYER), "left", token(LEFT), "legal_block_classes", token(LEGALBLKCLASS), "name", token(NAME), "neighborhood", token(NEIGHBORHOOD), "no_layer_change", token(NO_LAYER_CHANGE), "nomirror", token(NOMIRROR), "nonfixed", token(NONFIXED), "nopermute", token(NOPERMUTE), "of", token(OF), "orient", token(ORIENT), "orientations", token(ORIENTATIONS), "pad", token(PAD), "padgroup", token(PADGROUP), "permute", token(PERMUTE), "pin", token(PIN), "pin_group", token(PINGROUP), "power", token(POWER), "restrict", token(RESTRICT), "right", token(RIGHT), "rigidly_fixed", token(RIGIDFIXED), "side", token(SIDE), "sidespace", token(SIDESPACE), "signal", token(SIGNAL), "softcell", token(SOFTCELL), "softpin", token(SOFTPIN), "stdcell", token(STDCELL), "supergroup", token(SUPERGROUP), "swap_group", token(SWAPGROUP), "top", token(TOP), "unequiv", token(UNEQUIV) } ; static int screen() { int c ; struct rw_table *low = rwtable, /* ptr to beginning */ *mid , *high = END(rwtable) ; /* ptr to end */ /* binary search to look thru table to find pattern match */ while( low <= high){ mid = low + (high-low) / 2 ; if( (c = strcmp(mid->rw_name, yytext) ) == STRINGEQ){ return( mid->rw_yylex ) ; /* return token number */ } else if( c < 0 ){ low = mid + 1 ; } else { high = mid - 1 ; } } /* at this point we haven't found a match so we have a string */ /* save the string by making copy */ yylval.string = Ystrclone( yytext ) ; return (STRING); } /* end screen function */ static int check_line_count( s ) char *s ; { if( s ){ if( strlen(s) >= YYLMAX ){ sprintf(YmsgG,"comment beginning at line %d ",line_countS+1 ); M( ERRMSG, "lex", YmsgG ) ; sprintf(YmsgG,"exceeds maximum allowed length:%d chars.\n", YYLMAX ); M( MSG, NULL, YmsgG ) ; } for( ;*s;s++ ){ if( *s == '\n'){ line_countS++; } } } } /* end check_line_count */ int yyvstop[] ={ 0, 7, 0, 7, 0, 8, 0, 7, 8, 0, 6, 0, 5, 8, 0, 5, 8, 0, 3, 5, 8, 0, 5, 8, 0, 2, 8, 0, 7, 0, 5, 0, 3, 5, 0, 2, 5, 0, 5, 0, 3, 5, 0, 2, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 1, 5, 0, 5, 0, 4, 5, 0, 1, 0, 5, 0, 1, 5, 0, 1, 0, 0}; # define YYTYPE unsigned char struct yywork { YYTYPE verify, advance; } yycrank[] ={ 0,0, 0,0, 1,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,4, 1,5, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 1,7, 9,15, 0,0, 1,8, 1,9, 1,10, 7,13, 19,19, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 25,33, 26,34, 32,24, 33,25, 34,25, 0,0, 0,0, 0,0, 1,6, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 10,16, 0,0, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 14,16, 0,0, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 15,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 15,18, 15,18, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 0,0, 0,0, 0,0, 0,0, 18,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 16,22, 15,19, 18,23, 18,18, 20,24, 0,0, 18,18, 18,18, 18,18, 0,0, 15,20, 15,19, 20,24, 20,24, 15,19, 15,21, 15,19, 17,16, 0,0, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 18,18, 0,0, 0,0, 16,22, 0,0, 0,0, 0,0, 20,25, 15,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 20,26, 20,25, 0,0, 0,0, 20,25, 20,27, 20,25, 22,28, 0,0, 22,28, 0,0, 0,0, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 23,24, 0,0, 0,0, 0,0, 0,0, 20,25, 0,0, 24,18, 0,0, 23,30, 23,24, 0,0, 0,0, 23,24, 23,31, 23,24, 24,23, 24,18, 0,0, 0,0, 24,18, 24,32, 24,18, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 0,0, 0,0, 0,0, 23,24, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 24,18, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 30,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 30,23, 30,18, 0,0, 0,0, 30,18, 30,35, 30,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 30,18, 0,0, 0,0, 0,0}; struct yysvf yysvec[] ={ 0, 0, 0, yycrank+-1, 0, yyvstop+1, yycrank+0, yysvec+1, yyvstop+3, yycrank+0, 0, yyvstop+5, yycrank+3, 0, yyvstop+7, yycrank+0, 0, yyvstop+10, yycrank+38, 0, yyvstop+12, yycrank+4, yysvec+6, yyvstop+15, yycrank+117, yysvec+6, yyvstop+18, yycrank+3, yysvec+6, yyvstop+22, yycrank+129, yysvec+6, yyvstop+25, yycrank+0, yysvec+4, yyvstop+28, yycrank+0, yysvec+6, yyvstop+30, yycrank+139, yysvec+6, yyvstop+32, yycrank+151, yysvec+6, yyvstop+35, yycrank+-208, 0, yyvstop+38, yycrank+171, yysvec+6, yyvstop+40, yycrank+211, yysvec+6, yyvstop+43, yycrank+-200, yysvec+15, 0, yycrank+-4, yysvec+15, yyvstop+45, yycrank+-243, 0, yyvstop+47, yycrank+0, yysvec+15, yyvstop+49, yycrank+249, yysvec+6, yyvstop+51, yycrank+-274, yysvec+20, 0, yycrank+-281, yysvec+15, 0, yycrank+-15, yysvec+15, yyvstop+53, yycrank+-16, yysvec+15, yyvstop+55, yycrank+0, yysvec+6, yyvstop+57, yycrank+282, yysvec+6, yyvstop+60, yycrank+303, yysvec+6, yyvstop+62, yycrank+-328, yysvec+15, 0, yycrank+0, 0, yyvstop+65, yycrank+17, 0, 0, yycrank+18, yysvec+6, yyvstop+67, yycrank+19, yysvec+6, yyvstop+69, yycrank+0, yysvec+32, yyvstop+72, 0, 0, 0}; struct yywork *yytop = yycrank+397; struct yysvf *yybgin = yysvec+1; char yymatch[] ={ 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 011 ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'*' ,'+' ,'!' ,'+' ,'.' ,'/' , '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , '0' ,'0' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 0}; char yyextra[] ={ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0}; /* ncform 4.1 83/08/11 */ int yylineno =1; # define YYU(x) x # define NLSTATE yyprevious=YYNEWLINE char yytext[YYLMAX]; struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; char yysbuf[YYLMAX]; char *yysptr = yysbuf; int *yyfnd; extern struct yysvf *yyestate; int yyprevious = YYNEWLINE; yylook(){ register struct yysvf *yystate, **lsp; register struct yywork *yyt; struct yysvf *yyz; int yych; struct yywork *yyr; # ifdef LEXDEBUG int debug; # endif char *yylastch; #ifdef linux if (yyin == NULL) yyin = stdin; if (yyout == NULL) yyout = stdout; #endif /* start off machines */ # ifdef LEXDEBUG debug = 0; # endif if (!yymorfg) yylastch = yytext; else { yymorfg=0; yylastch = yytext+yyleng; } for(;;){ lsp = yylstate; yyestate = yystate = yybgin; if (yyprevious==YYNEWLINE) yystate++; for (;;){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); # endif yyt = yystate->yystoff; if(yyt == yycrank){ /* may not be any transitions */ yyz = yystate->yyother; if(yyz == 0)break; if(yyz->yystoff == yycrank)break; } *yylastch++ = yych = input(); tryagain: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"unsigned char "); allprint(yych); putchar('\n'); } # endif yyr = yyt; if ( (long)yyt > (long)yycrank){ yyt = yyr + yych; if (yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } # ifdef YYOPTIM else if((long)yyt < (long)yycrank) { /* r < yycrank */ yyt = yyr = yycrank+(yycrank-yyt); # ifdef LEXDEBUG if(debug)fprintf(yyout,"compressed state\n"); # endif yyt = yyt + yych; if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } yyt = yyr + YYU(yymatch[yych]); # ifdef LEXDEBUG if(debug){ fprintf(yyout,"try fall back character "); allprint(YYU(yymatch[yych])); putchar('\n'); } # endif if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transition */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); # endif goto tryagain; } # endif else {unput(*--yylastch);break;} contin: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"state %d char ",yystate-yysvec-1); allprint(yych); putchar('\n'); } # endif ; } # ifdef LEXDEBUG if(debug){ fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); allprint(yych); putchar('\n'); } # endif while (lsp-- > yylstate){ *yylastch-- = 0; if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ yyolsp = lsp; if(yyextra[*yyfnd]){ /* must backup */ while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ lsp--; unput(*yylastch--); } } yyprevious = YYU(*yylastch); yylsp = lsp; yyleng = yylastch-yytext+1; yytext[yyleng] = 0; # ifdef LEXDEBUG if(debug){ fprintf(yyout,"\nmatch "); sprint(yytext); fprintf(yyout," action %d\n",*yyfnd); } # endif return(*yyfnd++); } unput(*yylastch); } if (yytext[0] == 0 /* && feof(yyin) */) { yysptr=yysbuf; return(0); } yyprevious = yytext[0] = input(); if (yyprevious>0) output(yyprevious); yylastch=yytext; # ifdef LEXDEBUG if(debug)putchar('\n'); # endif } } yyback(p, m) int *p; { if (p==0) return(0); while (*p) { if (*p++ == m) return(1); } return(0); } /* the following are only used in the lex library */ yyinput(){ #ifdef linux if (yyin == NULL) yyin = stdin; #endif return(input()); } yyoutput(c) int c; { #ifdef linux if (yyout == NULL) yyout = stdout; #endif output(c); } yyunput(c) int c; { unput(c); } graywolf-0.1.4+20170307gite1bf319/src/syntax/000077500000000000000000000000001305746555600201015ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/src/syntax/CMakeLists.txt000066400000000000000000000005601305746555600226420ustar00rootroot00000000000000 add_executable(syntax main.c output.c readcells.c ${CMAKE_SOURCE_DIR}/src/date/date.c) target_link_libraries(syntax ${CMAKE_BINARY_DIR}/src/Ylib/libycadgraywolf.so) target_link_libraries(syntax X11) target_link_libraries(syntax m) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include .) install(TARGETS syntax DESTINATION lib/graywolf/bin) graywolf-0.1.4+20170307gite1bf319/src/syntax/date.h000066400000000000000000000001071305746555600211650ustar00rootroot00000000000000#define DATE "@(#) Yale compilation date:Mon May 25 21:11:10 EDT 1992" graywolf-0.1.4+20170307gite1bf319/src/syntax/globals.h000066400000000000000000000045341305746555600217030ustar00rootroot00000000000000/* * Copyright (C) 1989 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- "@(#) globals.h version 1.1 5/5/89" FILE: globals.h CONTENTS: definitions for globals structures and variables DATE: Apr 24, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef GLOBALS_H #define GLOBALS_H #include #ifndef MATH_H #define MATH_H #include #endif /* MATH_H */ /* if not using makefile and debug is wanted add it here */ /* #define DEBUG */ /* ***********LEAVE THE BELOW UNCHANGED *************************** */ #define SYNTAX "syntax" #define HARDCELLTYPE 1 #define SOFTCELLTYPE 2 #define STDCELLTYPE 3 #define PADCELLTYPE 4 /* compile switch for globals */ #ifndef MAIN_VARS #define EXTERN extern #else #define EXTERN #endif EXTERN FILE *fpoG ; EXTERN char *cktNameG ; #endif /* GLOBALS_H */ graywolf-0.1.4+20170307gite1bf319/src/syntax/main.c000066400000000000000000000116401305746555600211730ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: main.c DESCRIPTION:This file contains main control routine for the syntax program. CONTENTS: DATE: Apr 24, 1989 REVISIONS: Dec 8, 1989 - now write temp file to be moved later so that programs that follow won't run until passing syntax. Fri Jan 25 17:57:06 PST 1991 - added debug flag to syntax. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) main.c version 1.6 2/23/91" ; #endif #define MAIN_VARS #include #include #include #include #include #include #include #include "globals.h" #define EXPECTEDMEMORY (1024 * 1024) /* 1M should be enough */ #define VERSION "v1.1" main( argc , argv ) int argc ; char *argv[] ; { char *YinitProgram(), *Ystrclone() ; char filename[LRECL] ; char filename2[LRECL] ; char *ptr ; int arg_count ; int yaleIntro() ; int debug ; FILE *fp ; /* start up cleanup handler */ YINITCLEANUP( argv[0], NULL, MAYBEDUMP ) ; Yinit_memsize( EXPECTEDMEMORY ) ; if( argc < 2 || argc > 3 ){ syntax() ; } else { debug = FALSE ; arg_count = 1 ; if( *argv[1] == '-' ){ for( ptr = ++argv[1]; *ptr; ptr++ ){ switch( *ptr ){ case 'd': debug = TRUE ; break ; default: sprintf( YmsgG,"Unknown option:%c\n", *ptr ) ; M(ERRMSG,"main",YmsgG); syntax() ; } } YdebugMemory( debug ) ; cktNameG = Ystrclone( argv[++arg_count] ); /* now tell the user what he picked */ M(MSG,NULL,"\n\nSyntax switches:\n" ) ; if( debug ){ YsetDebug( TRUE ) ; M(MSG,NULL,"\tdebug on\n" ) ; } M(MSG,NULL,"\n" ) ; } else if( argc == 2 ){ /* order is important here */ YdebugMemory( FALSE ) ; cktNameG = Ystrclone( argv[1] ); } else { syntax() ; } } /* remove old version of stat file */ sprintf( filename, "%s.stat", cktNameG ) ; Yrm_files( filename ) ; sprintf( filename, "%s.temp", cktNameG ) ; fpoG = TWOPEN( filename, "w", ABORT ) ; /* we can change this value in the debugger */ YinitProgram(SYNTAX, VERSION, yaleIntro) ; sprintf( filename, "%s.cel", cktNameG ) ; fp = TWOPEN( filename, "r", ABORT ) ; readcells( fp ) ; if(!(Ymessage_get_errorcount() ) ){ M( MSG, NULL, "No syntax errors were found\n" ) ; output() ; } else { TWCLOSE( fp ) ; TWCLOSE( fpoG ) ; YexitPgm( PGMFAIL ) ; } TWCLOSE( fp ) ; TWCLOSE( fpoG ) ; /* now move .temp file to .stat */ sprintf( filename, "%s.temp", cktNameG ) ; sprintf( filename2, "%s.stat", cktNameG ) ; YmoveFile( filename, filename2 ) ; YexitPgm( PGMOK ) ; } /* end main */ /* give user correct syntax */ syntax() { M(ERRMSG,NULL,"\n" ) ; M(MSG,NULL,"Incorrect syntax. Correct syntax:\n"); sprintf( YmsgG, "\n%s circuitName\n\n", SYNTAX ); M(MSG,NULL,YmsgG ) ; YexitPgm(PGMFAIL); } /* end syntax */ yaleIntro() { int i ; M( MSG, NULL, "\n") ; M( MSG, NULL, YmsgG) ; M( MSG, NULL, "\nTimberWolf System Syntax Checker\n"); M( MSG, NULL, "Authors: Carl Sechen, Kai-Win Lee, Bill Swartz,\n"); M( MSG, NULL, " Dahe Chen, and Jimmy Lam\n"); M( MSG, NULL, " Yale University\n"); M( MSG, NULL, "\n"); fprintf(fpoG,"%s\n",YmsgG ) ; } /* end yaleIntro */ graywolf-0.1.4+20170307gite1bf319/src/syntax/output.c000066400000000000000000000215001305746555600216030ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: output.c DESCRIPTION:This file accumulates data for TimberWolf system. CONTENTS: DATE: Apr 24, 1989 REVISIONS: May 24, 1989 - updated argument to YcurTime. May 15, 1990 - now add up cell area so that standard cell macros size will be the average macro size. Aug 3, 1990 - added port counting to output. Thu Apr 18 01:12:20 EDT 1991 - added more error checking. Wed Jun 12 13:40:11 CDT 1991 - added check for pins outside cell boundary. Wed Jul 24 21:06:02 CDT 1991 - added a more meaningful output error message. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) output.c version 1.8 7/24/91" ; #endif #include #include "globals.h" #include #include #include #include // YcurTime() is not declared in any of the above extern char *YcurTime( INT * ); #define EXPECTEDNUMNETS 10009 static int objectS = 0 ; /* number of objects read */ static int celltypeS ; /* current cell type */ static int stdcellS = 0 ; /* number of standard cells */ static int macroS = 0 ; /* number of macro cells */ static int numinstanceS = 0 ; /* number of macro instances */ static int padS = 0 ; /* number of pad cells */ static int netS = 0 ; /* number of nets */ static int equivS = 0 ; /* number of equivalent pins */ static int unequivS = 0 ; /* number of unequivalent pins */ static int pinS = 0 ; /* number of pins */ static int impS = 0 ; /* number of implicit feeds */ static int portS = 0 ; /* number of ports */ static int minxS, minyS ; /* bounding box of cell */ static int maxxS, maxyS ; /* bounding box of cell */ static char current_cellS[LRECL] ; /* the current cell name */ static char cur_pinnameS[LRECL] ; /* current pinname */ static BOOL count_portS ; /* whether a pin is a port */ static YHASHPTR netTableS ; /* hash table for cross referencing nets */ static DOUBLE cellAreaS = 0 ; /* area of the macro cells */ /* *************************************************************** */ init() { /* get ready for parsing */ /* make hash table for nets */ netTableS = Yhash_table_create( EXPECTEDNUMNETS ) ; } /* end init */ addCell( celltype, cellname ) int celltype ; char *cellname ; { strcpy( current_cellS, cellname ) ; Ysafe_free( cellname ) ; /* passify the user */ if( (++objectS % 50) == 0 ){ sprintf( YmsgG, "Read %4d objects so far...\n", objectS ) ; M( MSG, NULL, YmsgG ) ; } celltypeS = celltype ; /* save for determining instances etc. */ switch( celltype ){ case HARDCELLTYPE: case SOFTCELLTYPE: macroS++ ; numinstanceS++ ; count_portS = TRUE ; /* count pins as ports */ break ; case STDCELLTYPE: stdcellS++ ; count_portS = FALSE ; break ; case PADCELLTYPE: padS++ ; count_portS = TRUE ; break ; } } /* end addCell */ addNet( signal ) char *signal ; { int *data ; if( strcmp( signal, "TW_PASS_THRU" ) == STRINGEQ ){ impS++ ; return ; /* not a net so return */ } if(!(Yhash_search( netTableS, signal, NULL, FIND ))){ /* else a new net load data holder */ data = (int *) Ysafe_malloc( sizeof(int) ) ; *data = ++netS ; if( Yhash_search( netTableS, signal, (char *)data, ENTER )){ sprintf( YmsgG, "Trouble adding signal:%s to hash table\n", signal ) ; M(ERRMSG,"addNet",YmsgG ) ; } } pinS++ ; if( count_portS ){ portS++ ; } } /* end addNet */ addEquiv() { equivS++ ; } /* end addEquiv */ addUnEquiv() { unequivS++ ; } /* end addUnEquiv */ add_instance() { if( celltypeS == HARDCELLTYPE || celltypeS == SOFTCELLTYPE ){ numinstanceS++ ; } } /* end add_instance */ set_bbox( left, right, bottom, top ) INT left, right, bottom, top ; { minxS = left ; minyS = bottom ; maxxS = right ; maxyS = top ; } /* end set_bbox */ start_pt( x, y ) int x, y ; { Ybuster_init() ; Ybuster_addpt( x, y ) ; minxS = x ; minyS = y ; maxxS = x ; maxyS = y ; } /* end start_pt */ add_pt( x, y ) int x, y ; { Ybuster_addpt( x, y ) ; minxS = MIN( x, minxS ) ; minyS = MIN( y, minyS ) ; maxxS = MAX( x, maxxS ) ; maxyS = MAX( y, maxyS ) ; } /* end add_pt */ processCorners() { YBUSTBOXPTR bustptr ; /* get a tile from Ybuster */ DOUBLE this_cell ; /* area of the current tile */ DOUBLE l, r, b, t ; /* the coordinates of the current tile*/ if( celltypeS == HARDCELLTYPE || celltypeS == SOFTCELLTYPE ){ if( !(Ybuster_verify( current_cellS ))){ M(ERRMSG,"processCorners",YmsgG ) ; return ; } while( bustptr = Ybuster() ){ l = (DOUBLE) bustptr[1].x ; r = (DOUBLE) bustptr[3].x ; b = (DOUBLE) bustptr[1].y ; t = (DOUBLE) bustptr[3].y ; this_cell = (r - l) * (t - b) ; cellAreaS += this_cell ; } } } /* end processCorners */ check_xloc( value ) char *value ; { if( (strcmp( value, "L" ) != STRINGEQ ) && strcmp( value, "R" ) != STRINGEQ ){ sprintf( YmsgG, "x location should be L or R:%s\n", current_cellS ) ; M( ERRMSG,"check_xloc", YmsgG ) ; } Ysafe_free( value ) ; } /* end check_xloc */ check_yloc( value ) char *value ; { if( (strcmp( value, "B" ) != STRINGEQ ) && strcmp( value, "T" ) != STRINGEQ ){ sprintf( YmsgG, "y location should be B or T:%s\n", current_cellS ) ; M( ERRMSG,"check_yloc", YmsgG ) ; } Ysafe_free( value ) ; } /* end check_xloc */ check_sideplace( side ) char *side ; { INT numsides ; INT i ; numsides = strlen( side ) ; for( i = 0 ; i < numsides; i++ ){ switch( side[i] ){ case 'B' : case 'L' : case 'R' : case 'T' : break ; default: sprintf( YmsgG, "side restriction not specified properly for cell:%s\n", current_cellS ); M(ERRMSG,"check_sideplace",YmsgG ) ; } /* end switch */ } Ysafe_free( side ) ; } /* end check_sideplace */ set_pinname( pinname ) char *pinname ; { strcpy( cur_pinnameS, pinname ) ; } /* end set_pinname */ check_pos( xpos, ypos ) int xpos, ypos ; { if( xpos < minxS || xpos > maxxS || ypos < minyS || ypos > maxyS ){ sprintf( YmsgG, "Pin:%s cell:%s @(%d,%d) is outside cell boundary\n", cur_pinnameS, current_cellS, xpos, ypos ) ; M( ERRMSG, "check_pos", YmsgG ) ; } } /* end check_pos */ /* ***************************************************************** OUTPUT routine - output the results. **************************************************************** */ output() { char *yctime = (char *)YcurTime(NULL); fprintf( fpoG, "TIMESTAMP:%s\n", yctime ) ; // fprintf( fpoG, "TIMESTAMP:%s\n", YcurTime(NULL) ) ; fprintf( fpoG, "Statistics for %s:\n", cktNameG ) ; fprintf( fpoG, "num_stdcells:%d\n", stdcellS ) ; fprintf( fpoG, "num_macros:%d\n", macroS ) ; fprintf( fpoG, "num_instances:%d\n", numinstanceS ) ; fprintf( fpoG, "num_pads:%d\n", padS ) ; fprintf( fpoG, "num_nets:%d\n", netS ) ; fprintf( fpoG, "num_pins:%d\n", pinS ) ; fprintf( fpoG, "num_implicit_feeds:%d\n", impS ) ; fprintf( fpoG, "num_equivs:%d\n", equivS ) ; fprintf( fpoG, "num_unequivs:%d\n", unequivS ) ; fprintf( fpoG, "num_ports:%d\n", portS ) ; fprintf( fpoG, "macro_area:%4.3le\n", cellAreaS ) ; } /* end output */ graywolf-0.1.4+20170307gite1bf319/src/syntax/readcells.c000066400000000000000000001364021305746555600222110ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley) 01/20/90"; #endif #define YYBYACC 1 /* ----------------------------------------------------------------- FILE: readcells.c <- readcells.y <- readcells.l DESCRIPTION:This file contains the grammar (BNF) for the TimberWolfMC input file parser. The rules for lex are in readcells.l. The grammar for yacc is in readcells.y. The output of yacc (y.tab.c) is renamed to readcells.c CONTENTS: readcells( fp ) FILE *fp ; yyerror(s) char *s; yywrap() Note:readcells.c will also include the yacc parser. DATE: Aug 7, 1988 REVISIONS: Oct 27, 1988 - modified fixed and group cell code. Now accept designs without pads. Jan 29, 1989 - changed to msgG and added \n. Mar 6, 1989 - removed redundant string from padgroupname Mar 7, 1989 - now able to parse instance lists but don't process them. Mar 12, 1989 - changed group cell and supercell reference from integer to string to be easier for user. Mar 13, 1989 - added string to instance to tell them apart. Apr 24, 1989 - added standard cells to yacc. May 7, 1989 - corrected padgroup. May 11, 1989 - must have layer info for this flow. Jun 19, 1989 - added pin groups to syntax checker. Mar 39, 1990 - added new MC softpin syntax. Fri Jan 25 17:59:55 PST 1991 - added missing SC options. Thu Apr 18 01:14:09 EDT 1991 - added initial orient feature and reversed corners field. Also added more error checking and now context free language. Wed Jun 12 13:41:41 CDT 1991 - added check for pins outside boundary and fixed sidespace syntax. Wed Jul 3 13:19:19 CDT 1991 - now TimberWolf handles more than one unequiv pair. Wed Jul 24 21:07:46 CDT 1991 - added analog input to syntax. Mon Aug 12 16:52:09 CDT 1991 - now allow stdcells not to have any pins. Tue Aug 13 12:54:32 CDT 1991 - fixed problem with mirror keyword. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) readcells.y version 1.19 5/22/92" ; #endif #include #include #include #include #include #include "globals.h" #undef REJECT #ifdef DEBUG #define YYDEBUG 1 /* condition compile for yacc debug */ /* #define LEXDEBUG 1 */ /* conditional compile for lex debug */ #ifdef LEXDEBUG /* two bugs in Yale version of lex */ #define allprint(x) fprintf( stdout, "%c\n", x ) #define sprint(x) fprintf( stdout, "%s\n", x ) #endif #endif /* DEBUG */ static int line_countS ; static char bufferS[LRECL] ; typedef union { INT ival ; char *string ; double fval ; } YYSTYPE; #define INTEGER 257 #define STRING 258 #define FLOAT 259 #define ADDEQUIV 260 #define APPROXFIXED 261 #define ASPLB 262 #define ASPUB 263 #define AT 264 #define BLOCK 265 #define BOTTOM 266 #define CELL 267 #define CELLGROUP 268 #define CLASS 269 #define CONNECT 270 #define CORNERS 271 #define EQUIV 272 #define FIXED 273 #define FROM 274 #define HARDCELL 275 #define INITIALLY 276 #define INSTANCE 277 #define LAYER 278 #define LEFT 279 #define NAME 280 #define NEIGHBORHOOD 281 #define NOMIRROR 282 #define NONFIXED 283 #define NOPERMUTE 284 #define OF 285 #define ORIENT 286 #define ORIENTATIONS 287 #define PAD 288 #define PADGROUP 289 #define PERMUTE 290 #define PIN 291 #define RESTRICT 292 #define RIGHT 293 #define RIGIDFIXED 294 #define SIDE 295 #define SIDESPACE 296 #define SIGNAL 297 #define SOFTCELL 298 #define SOFTPIN 299 #define STDCELL 300 #define SUPERGROUP 301 #define TOP 302 #define PINGROUP 303 #define ENDPINGROUP 304 #define SWAPGROUP 305 #define UNEQUIV 306 #define CELLOFFSET 307 #define ECO_ADDED_CELL 308 #define LEGALBLKCLASS 309 #define CURRENT 310 #define POWER 311 #define NO_LAYER_CHANGE 312 #define KEEPOUT 313 #define YYERRCODE 256 short yylhs[] = { -1, 0, 0, 4, 4, 6, 6, 8, 8, 8, 5, 5, 12, 12, 13, 13, 7, 7, 11, 11, 21, 21, 22, 22, 22, 22, 22, 22, 9, 9, 30, 30, 32, 32, 10, 10, 40, 40, 41, 41, 41, 33, 14, 14, 15, 16, 16, 29, 39, 17, 54, 54, 31, 31, 56, 18, 18, 25, 23, 60, 60, 24, 26, 61, 62, 62, 63, 28, 57, 57, 58, 58, 58, 58, 59, 59, 27, 19, 2, 3, 45, 49, 49, 51, 53, 34, 64, 64, 36, 37, 37, 65, 65, 46, 46, 42, 43, 43, 66, 66, 38, 38, 20, 20, 69, 69, 71, 71, 70, 70, 70, 70, 72, 72, 72, 67, 67, 76, 68, 68, 77, 73, 81, 82, 82, 87, 88, 88, 83, 83, 84, 84, 85, 85, 74, 74, 90, 89, 75, 75, 92, 91, 79, 79, 79, 93, 95, 94, 94, 96, 97, 98, 98, 44, 44, 99, 99, 100, 100, 101, 101, 78, 78, 102, 102, 48, 48, 48, 86, 80, 80, 103, 47, 47, 50, 50, 104, 104, 52, 52, 55, 55, 35, 35, 105, 105, 106, 107, 107, 1, 1, 1, }; short yylen[] = { 2, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 4, 5, 1, 2, 1, 1, 1, 1, 1, 1, 2, 3, 1, 3, 5, 4, 2, 3, 1, 3, 6, 5, 4, 2, 6, 5, 4, 4, 3, 4, 4, 3, 13, 14, 8, 14, 1, 0, 8, 2, 2, 1, 2, 1, 3, 1, 1, 2, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 4, 3, 3, 4, 4, 3, 2, 3, 2, 4, 3, 1, 2, 0, 2, 4, 1, 2, 1, 1, 1, 2, 0, 1, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2, 2, 1, 2, 3, 2, 3, 6, 5, 6, 2, 2, 2, 2, 3, 0, 2, 0, 2, 0, 1, 1, 2, 0, 6, 1, 2, 0, 6, 1, 2, 1, 2, 1, 1, 2, 3, 4, 0, 1, 3, 4, 3, 3, 1, 2, 2, 2, 0, 3, 1, 2, 0, 2, 3, 2, 0, 2, 1, 0, 3, 1, 2, 2, 2, 1, 2, 1, 2, 0, 1, 1, 2, 5, 2, 3, 1, 1, 1, }; short yydefred[] = { 0, 0, 0, 0, 0, 0, 0, 5, 7, 8, 9, 0, 0, 0, 190, 189, 191, 0, 0, 0, 0, 1, 0, 12, 0, 0, 0, 0, 6, 16, 0, 0, 69, 76, 0, 0, 0, 61, 0, 0, 0, 20, 22, 23, 24, 25, 26, 27, 0, 0, 54, 0, 0, 30, 0, 0, 0, 0, 0, 36, 49, 0, 0, 0, 0, 0, 13, 14, 0, 0, 0, 0, 17, 178, 0, 0, 0, 67, 57, 59, 0, 63, 0, 0, 0, 0, 21, 73, 70, 71, 72, 0, 0, 0, 0, 0, 0, 0, 0, 184, 0, 0, 0, 0, 0, 0, 47, 48, 0, 0, 15, 0, 0, 174, 0, 0, 0, 0, 0, 179, 0, 0, 0, 180, 0, 60, 66, 0, 64, 0, 0, 0, 18, 0, 104, 0, 111, 0, 0, 0, 0, 0, 41, 31, 0, 0, 185, 0, 0, 0, 0, 37, 80, 82, 81, 176, 177, 0, 0, 175, 94, 0, 84, 83, 88, 0, 0, 45, 0, 0, 181, 65, 0, 0, 0, 106, 0, 105, 0, 0, 0, 0, 134, 138, 0, 0, 0, 0, 19, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 91, 0, 78, 0, 0, 0, 0, 117, 107, 0, 0, 0, 0, 135, 139, 123, 125, 0, 0, 0, 0, 74, 75, 0, 87, 0, 0, 100, 0, 0, 0, 95, 0, 0, 96, 98, 99, 0, 171, 173, 0, 0, 0, 92, 90, 0, 0, 0, 0, 0, 0, 129, 0, 0, 126, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 167, 89, 0, 0, 0, 0, 0, 136, 140, 131, 133, 121, 127, 0, 187, 0, 0, 0, 0, 0, 0, 0, 0, 157, 0, 146, 0, 119, 0, 0, 0, 147, 0, 79, 0, 0, 0, 122, 168, 0, 0, 56, 188, 52, 0, 0, 156, 155, 0, 159, 160, 153, 158, 163, 0, 0, 0, 148, 145, 0, 0, 0, 77, 137, 141, 0, 0, 154, 164, 0, 152, 149, 0, 0, 0, 0, 120, 150, 0, 0, 0, 170, 0, 0, 0, 0, 0, 0, 50, 0, 53, 51, }; short yydgoto[] = { 4, 294, 206, 307, 5, 21, 6, 27, 7, 8, 9, 10, 22, 65, 23, 67, 29, 11, 39, 84, 132, 40, 41, 42, 43, 44, 45, 46, 47, 12, 51, 52, 53, 94, 54, 97, 120, 167, 229, 13, 58, 59, 104, 236, 268, 24, 115, 158, 200, 68, 112, 30, 74, 31, 76, 124, 55, 48, 91, 226, 80, 82, 127, 128, 141, 204, 237, 230, 239, 133, 134, 174, 175, 231, 180, 181, 136, 240, 272, 300, 349, 137, 186, 221, 256, 284, 280, 187, 223, 182, 312, 183, 313, 301, 302, 303, 304, 305, 344, 270, 295, 296, 327, 242, 113, 98, 99, 261, }; short yysindex[] = { -162, -62, -62, -62, 0, -241, -229, 0, 0, 0, 0, -105, -72, -72, 0, 0, 0, -62, -186, -183, -62, 0, -126, 0, -116, -62, -62, -250, 0, 0, -62, -94, 0, 0, -129, -62, -67, 0, -59, -73, -105, 0, 0, 0, 0, 0, 0, 0, -173, -47, 0, -65, -116, 0, -96, -169, -116, -44, -65, 0, 0, -62, -62, -61, -62, -69, 0, 0, -62, -64, -57, -56, 0, 0, -110, -143, -62, 0, 0, 0, -36, 0, -32, -31, -157, -73, 0, 0, 0, 0, 0, -30, -29, -62, -116, -65, -49, -38, -96, 0, -25, -24, -65, -22, -38, -116, 0, 0, -62, -115, 0, -225, -215, 0, -23, -54, -62, -62, -18, 0, -216, -39, -17, 0, -62, 0, 0, -32, 0, -52, -37, -46, 0, -157, 0, -227, 0, -222, -157, -28, -15, -13, 0, 0, -10, -216, 0, -21, -20, -14, -216, 0, 0, 0, 0, 0, 0, -43, -48, 0, 0, -48, 0, 0, 0, -27, -6, 0, 1, -16, 0, 0, 4, -62, -251, 0, -227, 0, -12, -11, -9, -50, 0, 0, 7, 13, -53, 18, 0, -153, 0, 19, 8, -46, 1, 1, 3, -200, 20, 24, 0, -46, -6, 0, -161, 0, 27, 1, 11, -7, 0, 0, -9, -50, -62, -62, 0, 0, 0, 0, 26, -40, 29, 30, 0, 0, 22, 0, 57, -46, 0, -9, 59, 64, 0, -8, -111, 0, 0, 0, -4, 0, 0, 77, -46, -161, 0, 0, 66, 89, 95, -62, 60, 60, 0, 102, 51, 0, 108, 101, 114, 118, 0, -9, 103, 112, -62, -62, 73, 0, -62, 93, -121, 0, 0, 132, 122, 90, 60, 143, 0, 0, 0, 0, 0, 0, 145, 0, 157, 132, 132, 116, -99, -62, -140, -174, 0, 158, 0, 146, 0, 155, 155, -4, 0, -4, 0, 180, 132, 181, 0, 0, -222, -222, 0, 0, 0, 182, -62, 0, 0, -174, 0, 0, 0, 0, 0, 186, -62, 155, 0, 0, 165, 171, 189, 0, 0, 0, 176, 175, 0, 0, 175, 0, 0, 1, 190, 1, 195, 0, 0, 216, 1, 219, 0, 206, 225, 221, 132, 226, 132, 0, 132, 0, 0, }; short yyrindex[] = { 0, 0, 0, 0, 0, 490, 17, 0, 0, 0, 0, -175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 501, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 247, 0, 0, 0, 566, 0, 0, 0, 0, 0, 0, 517, 0, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -141, 0, 0, 0, 584, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 588, 0, 0, 251, 0, 0, 0, 602, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 178, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, -100, 0, 0, 0, 0, 0, 620, 0, 411, 0, 0, 584, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 456, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -202, 0, 0, 0, 436, 440, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 487, 0, 0, 0, 493, 0, 0, 0, 37, 0, 0, 458, 0, 0, 0, 0, 0, 0, 0, -182, -167, 0, 0, 0, 0, 0, 0, 0, 81, 0, 31, 0, 0, 0, 0, 0, 515, 0, 230, 0, 0, 0, 0, 542, 0, 0, 0, 211, 0, 0, 489, 62, 458, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, 0, 0, 0, -243, 0, 255, 0, 0, 0, 0, 547, 0, 0, 0, 292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 339, 364, 273, 0, 236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 131, 0, 389, 0, 0, 310, 0, 0, 0, 0, 0, 0, 156, 0, 0, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; short yygindex[] = { 0, -1, -187, -280, 0, 0, 0, 0, 519, 0, 0, 0, 0, 0, 504, 471, 511, 0, 509, 466, 414, 0, 522, 0, 0, 0, 0, 0, 0, 0, 503, 544, 469, -26, -2, 0, 53, 39, 367, 0, 514, 460, 0, 0, 0, 0, -181, 464, 412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 448, 0, 379, 350, -170, 0, 0, 459, 0, 415, -81, -163, 418, 0, 0, -151, 0, 254, 0, -97, 0, 0, 0, -223, 0, 0, -176, 0, -148, 0, 0, 296, 0, -212, 0, 0, 331, 307, -194, 0, 0, 491, 0, 506, 0, }; #define YYTABLESIZE 921 short yytable[] = { 17, 18, 19, 135, 216, 85, 165, 232, 233, 316, 317, 57, 46, 212, 28, 172, 60, 3, 25, 63, 249, 4, 69, 247, 70, 71, 186, 238, 334, 73, 281, 124, 105, 217, 78, 184, 216, 43, 1, 25, 130, 165, 14, 15, 16, 178, 2, 20, 155, 185, 176, 26, 135, 210, 57, 310, 128, 135, 156, 262, 106, 107, 42, 109, 274, 217, 238, 111, 263, 3, 186, 166, 26, 119, 262, 123, 105, 157, 361, 179, 363, 130, 364, 14, 15, 16, 68, 216, 87, 112, 330, 130, 142, 176, 61, 100, 246, 62, 68, 235, 88, 325, 112, 57, 55, 1, 132, 152, 68, 113, 89, 111, 101, 2, 121, 162, 163, 330, 271, 68, 58, 90, 113, 170, 114, 114, 224, 325, 77, 93, 122, 162, 58, 322, 130, 58, 3, 114, 58, 298, 225, 58, 58, 323, 324, 58, 131, 14, 15, 16, 145, 299, 331, 58, 332, 49, 169, 150, 351, 118, 353, 62, 20, 64, 58, 356, 58, 58, 58, 153, 340, 32, 209, 62, 161, 154, 62, 33, 172, 62, 130, 34, 62, 62, 193, 319, 62, 75, 235, 197, 79, 320, 267, 169, 62, 14, 15, 16, 81, 49, 35, 50, 36, 37, 38, 62, 83, 62, 62, 62, 92, 161, 93, 252, 253, 336, 337, 96, 103, 108, 64, 125, 114, 116, 117, 126, 129, 139, 140, 144, 115, 118, 147, 148, 160, 168, 161, 149, 157, 164, 169, 172, 190, 173, 191, 130, 189, 192, 199, 196, 278, 203, 198, 194, 195, 116, 179, 220, 207, 205, 202, 208, 234, 178, 218, 291, 292, 85, 214, 215, 219, 255, 266, 161, 85, 222, 227, 250, 241, 228, 46, 28, 28, 243, 248, 254, 257, 258, 271, 28, 251, 85, 118, 85, 85, 165, 85, 85, 124, 124, 46, 85, 28, 124, 172, 3, 124, 259, 124, 4, 151, 172, 28, 46, 260, 28, 264, 339, 85, 124, 124, 265, 124, 128, 128, 43, 43, 342, 128, 124, 124, 128, 124, 128, 124, 124, 273, 124, 279, 142, 275, 124, 124, 124, 128, 128, 276, 128, 130, 130, 42, 42, 277, 130, 128, 128, 130, 128, 130, 128, 128, 282, 128, 283, 144, 285, 286, 128, 128, 130, 130, 287, 130, 132, 132, 288, 267, 289, 132, 130, 130, 132, 130, 132, 130, 130, 290, 130, 297, 143, 306, 162, 309, 130, 132, 132, 308, 132, 162, 162, 311, 162, 314, 162, 132, 132, 162, 132, 162, 132, 132, 108, 132, 318, 315, 326, 169, 93, 93, 162, 93, 93, 162, 169, 169, 93, 328, 299, 169, 162, 162, 169, 162, 169, 162, 343, 109, 333, 335, 338, 110, 161, 161, 341, 169, 345, 346, 169, 169, 161, 347, 161, 354, 348, 169, 169, 165, 169, 93, 169, 169, 169, 161, 169, 352, 169, 172, 172, 169, 172, 169, 161, 161, 355, 172, 161, 357, 161, 161, 161, 358, 169, 359, 161, 169, 169, 161, 33, 161, 166, 2, 169, 169, 40, 169, 360, 169, 115, 115, 161, 362, 10, 161, 161, 161, 115, 161, 115, 161, 161, 161, 161, 161, 161, 161, 32, 182, 11, 115, 115, 183, 115, 116, 116, 161, 28, 66, 161, 115, 115, 116, 115, 116, 115, 161, 161, 110, 161, 72, 161, 161, 161, 39, 116, 116, 161, 116, 38, 161, 85, 161, 138, 188, 116, 116, 95, 116, 56, 116, 118, 118, 161, 86, 143, 161, 151, 34, 118, 244, 118, 102, 161, 161, 201, 161, 171, 161, 151, 151, 161, 118, 245, 151, 118, 102, 151, 269, 151, 29, 211, 118, 118, 177, 118, 213, 118, 350, 329, 151, 293, 321, 151, 35, 159, 146, 0, 142, 142, 151, 151, 0, 151, 0, 151, 142, 0, 142, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 142, 0, 0, 142, 144, 144, 0, 0, 0, 0, 142, 142, 144, 142, 144, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 144, 143, 143, 0, 0, 0, 0, 144, 144, 143, 144, 143, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 108, 108, 143, 0, 0, 0, 0, 0, 108, 143, 143, 0, 143, 0, 143, 0, 0, 0, 0, 0, 0, 108, 0, 0, 108, 109, 109, 0, 0, 110, 110, 108, 0, 109, 108, 0, 108, 110, 0, 0, 0, 0, 0, 0, 0, 0, 109, 93, 93, 109, 110, 0, 0, 110, 0, 93, 109, 93, 0, 109, 110, 109, 0, 110, 0, 110, 165, 165, 93, 165, 0, 93, 0, 0, 0, 0, 33, 33, 93, 93, 0, 93, 40, 40, 33, 0, 33, 0, 0, 0, 40, 0, 40, 0, 0, 0, 0, 33, 0, 166, 166, 0, 166, 40, 32, 32, 0, 33, 0, 0, 33, 0, 32, 40, 32, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 39, 39, 0, 0, 32, 38, 38, 32, 39, 0, 39, 0, 0, 38, 0, 38, 0, 0, 0, 0, 0, 39, 0, 0, 34, 34, 38, 0, 0, 0, 0, 39, 34, 0, 39, 0, 38, 0, 0, 38, 0, 0, 102, 102, 0, 34, 29, 29, 0, 0, 102, 0, 0, 0, 29, 34, 0, 0, 34, 0, 35, 35, 0, 102, 0, 0, 0, 29, 35, 0, 0, 0, 0, 102, 0, 0, 102, 29, 103, 103, 29, 35, 0, 0, 0, 0, 103, 0, 0, 0, 0, 35, 0, 0, 35, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 103, }; short yycheck[] = { 1, 2, 3, 84, 180, 0, 0, 194, 195, 289, 290, 13, 0, 176, 0, 0, 17, 0, 268, 20, 207, 0, 24, 204, 25, 26, 269, 197, 308, 30, 253, 0, 58, 181, 35, 257, 212, 0, 267, 268, 291, 257, 257, 258, 259, 272, 275, 288, 273, 271, 131, 301, 133, 304, 56, 278, 0, 138, 283, 229, 61, 62, 0, 64, 245, 213, 236, 68, 231, 298, 313, 287, 301, 74, 244, 76, 102, 292, 358, 306, 360, 0, 362, 257, 258, 259, 261, 263, 261, 291, 302, 291, 93, 174, 280, 264, 257, 280, 273, 299, 273, 295, 304, 105, 279, 267, 0, 108, 283, 291, 283, 112, 281, 275, 257, 116, 117, 329, 292, 294, 261, 294, 304, 124, 291, 286, 279, 321, 257, 0, 273, 0, 273, 273, 291, 276, 298, 304, 279, 260, 293, 282, 283, 283, 295, 286, 303, 257, 258, 259, 97, 272, 303, 294, 305, 271, 0, 104, 345, 269, 347, 261, 288, 289, 305, 352, 307, 308, 309, 284, 321, 276, 173, 273, 0, 290, 276, 282, 0, 279, 291, 286, 282, 283, 145, 284, 286, 281, 299, 150, 257, 290, 303, 0, 294, 257, 258, 259, 257, 271, 305, 273, 307, 308, 309, 305, 279, 307, 308, 309, 257, 0, 277, 214, 215, 312, 313, 313, 262, 280, 289, 257, 286, 280, 280, 257, 257, 257, 257, 278, 0, 269, 257, 257, 257, 274, 0, 259, 292, 257, 257, 293, 257, 280, 257, 291, 274, 257, 296, 263, 251, 257, 295, 274, 274, 0, 306, 310, 274, 258, 287, 257, 259, 272, 257, 266, 267, 262, 280, 280, 257, 311, 280, 0, 269, 257, 257, 266, 258, 271, 268, 267, 268, 259, 257, 259, 257, 257, 292, 275, 297, 286, 0, 288, 289, 289, 291, 292, 267, 268, 288, 296, 288, 272, 289, 288, 275, 285, 277, 288, 0, 296, 298, 301, 257, 301, 257, 318, 313, 288, 289, 257, 291, 267, 268, 288, 289, 328, 272, 298, 299, 275, 301, 277, 303, 304, 259, 306, 278, 0, 274, 310, 311, 312, 288, 289, 257, 291, 267, 268, 288, 289, 257, 272, 298, 299, 275, 301, 277, 303, 304, 259, 306, 312, 0, 257, 265, 311, 312, 288, 289, 257, 291, 267, 268, 257, 303, 274, 272, 298, 299, 275, 301, 277, 303, 304, 274, 306, 295, 0, 258, 260, 302, 312, 288, 289, 274, 291, 267, 268, 257, 270, 257, 272, 298, 299, 275, 301, 277, 303, 304, 0, 306, 297, 257, 257, 260, 288, 289, 288, 291, 292, 291, 267, 268, 296, 280, 272, 272, 298, 299, 275, 301, 277, 303, 270, 0, 257, 257, 257, 0, 267, 268, 257, 288, 274, 257, 291, 292, 275, 274, 277, 257, 278, 298, 299, 0, 301, 0, 303, 267, 268, 288, 270, 274, 272, 288, 289, 275, 291, 277, 260, 298, 257, 296, 301, 257, 303, 267, 268, 274, 288, 257, 272, 291, 292, 275, 0, 277, 0, 0, 298, 299, 0, 301, 274, 303, 267, 268, 288, 274, 0, 291, 267, 268, 275, 270, 277, 272, 298, 299, 275, 301, 277, 303, 0, 269, 0, 288, 289, 269, 291, 267, 268, 288, 6, 22, 291, 298, 299, 275, 301, 277, 303, 298, 299, 65, 301, 27, 303, 267, 268, 0, 288, 289, 272, 291, 0, 275, 40, 277, 85, 138, 298, 299, 52, 301, 13, 303, 267, 268, 288, 40, 94, 291, 105, 0, 275, 201, 277, 56, 298, 299, 161, 301, 127, 303, 267, 268, 115, 288, 202, 272, 291, 0, 275, 236, 277, 0, 174, 298, 299, 133, 301, 176, 303, 342, 301, 288, 268, 293, 291, 0, 112, 98, -1, 267, 268, 298, 299, -1, 301, -1, 303, 275, -1, 277, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 288, -1, -1, 291, 267, 268, -1, -1, -1, -1, 298, 299, 275, 301, 277, 303, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, -1, -1, 291, 267, 268, -1, -1, -1, -1, 298, 299, 275, 301, 277, 303, -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, 267, 268, 291, -1, -1, -1, -1, -1, 275, 298, 299, -1, 301, -1, 303, -1, -1, -1, -1, -1, -1, 288, -1, -1, 291, 267, 268, -1, -1, 267, 268, 298, -1, 275, 301, -1, 303, 275, -1, -1, -1, -1, -1, -1, -1, -1, 288, 267, 268, 291, 288, -1, -1, 291, -1, 275, 298, 277, -1, 301, 298, 303, -1, 301, -1, 303, 288, 289, 288, 291, -1, 291, -1, -1, -1, -1, 267, 268, 298, 299, -1, 301, 267, 268, 275, -1, 277, -1, -1, -1, 275, -1, 277, -1, -1, -1, -1, 288, -1, 288, 289, -1, 291, 288, 267, 268, -1, 298, -1, -1, 301, -1, 275, 298, 277, -1, 301, -1, -1, -1, -1, -1, -1, -1, -1, 288, -1, -1, -1, -1, -1, 267, 268, -1, -1, 298, 267, 268, 301, 275, -1, 277, -1, -1, 275, -1, 277, -1, -1, -1, -1, -1, 288, -1, -1, 267, 268, 288, -1, -1, -1, -1, 298, 275, -1, 301, -1, 298, -1, -1, 301, -1, -1, 267, 268, -1, 288, 267, 268, -1, -1, 275, -1, -1, -1, 275, 298, -1, -1, 301, -1, 267, 268, -1, 288, -1, -1, -1, 288, 275, -1, -1, -1, -1, 298, -1, -1, 301, 298, 267, 268, 301, 288, -1, -1, -1, -1, 275, -1, -1, -1, -1, 298, -1, -1, 301, -1, -1, -1, -1, 288, -1, -1, -1, -1, -1, -1, -1, -1, -1, 298, -1, -1, 301, }; #define YYFINAL 4 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 313 #if YYDEBUG char *yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"INTEGER","STRING","FLOAT", "ADDEQUIV","APPROXFIXED","ASPLB","ASPUB","AT","BLOCK","BOTTOM","CELL", "CELLGROUP","CLASS","CONNECT","CORNERS","EQUIV","FIXED","FROM","HARDCELL", "INITIALLY","INSTANCE","LAYER","LEFT","NAME","NEIGHBORHOOD","NOMIRROR", "NONFIXED","NOPERMUTE","OF","ORIENT","ORIENTATIONS","PAD","PADGROUP","PERMUTE", "PIN","RESTRICT","RIGHT","RIGIDFIXED","SIDE","SIDESPACE","SIGNAL","SOFTCELL", "SOFTPIN","STDCELL","SUPERGROUP","TOP","PINGROUP","ENDPINGROUP","SWAPGROUP", "UNEQUIV","CELLOFFSET","ECO_ADDED_CELL","LEGALBLKCLASS","CURRENT","POWER", "NO_LAYER_CHANGE","KEEPOUT", }; char *yyrule[] = { "$accept : start_file", "start_file : core pads", "start_file : core", "core : corecells", "core : corecells cellgroups", "corecells : coretype", "corecells : corecells coretype", "coretype : hardcell", "coretype : softcell", "coretype : stdcell", "pads : padcells", "pads : padcells padgroups", "padcells : padcell", "padcells : padcells padcell", "padgroups : padgroup", "padgroups : padgroups padgroup", "cellgroups : cellgroup", "cellgroups : cellgroups cellgroup", "stdcell : cellname std_fixed bbox pinlist", "stdcell : cellname optional_list std_fixed bbox pinlist", "optional_list : option", "optional_list : optional_list option", "option : celloffset", "option : eco", "option : swap_group", "option : legal_block_classes", "option : mirror", "option : initial_orient", "hardcell : hardcellname custom_instance_list", "hardcell : hardcellname fixed custom_instance_list", "custom_instance_list : custom_instance", "custom_instance_list : custom_instance_list instance custom_instance", "custom_instance : corners keep_outs class orient hardpins", "custom_instance : corners keep_outs class orient", "softcell : softname soft_instance_list", "softcell : softname fixed soft_instance_list", "soft_instance_list : soft_instance", "soft_instance_list : soft_instance_list instance soft_instance", "soft_instance : corners aspect class orient softpins mc_pingroup", "soft_instance : corners aspect class orient softpins", "soft_instance : corners aspect class orient", "instance : INSTANCE string", "padcell : padname corners cur_orient restriction sidespace hardpins", "padcell : padname corners cur_orient restriction sidespace", "padgroup : padgroupname padgrouplist restriction sidespace", "cellgroup : supergroupname supergrouplist class orient", "cellgroup : cellgroupname neighborhood cellgrouplist", "hardcellname : HARDCELL string NAME string", "softname : SOFTCELL string NAME string", "cellname : CELL string string", "neighborhood : NEIGHBORHOOD INTEGER FROM xloc INTEGER FROM yloc INTEGER FROM xloc INTEGER FROM yloc", "neighborhood : NEIGHBORHOOD FIXED INTEGER FROM xloc INTEGER FROM yloc INTEGER FROM xloc INTEGER FROM yloc", "fixed : fixedcontext AT INTEGER FROM xloc INTEGER FROM yloc", "fixed : fixedcontext NEIGHBORHOOD INTEGER FROM xloc INTEGER FROM yloc INTEGER FROM xloc INTEGER FROM yloc", "fixedcontext : FIXED", "std_fixed :", "std_fixed : initially fixed_type INTEGER FROM fixed_loc OF BLOCK INTEGER", "swap_group : SWAPGROUP string", "celloffset : CELLOFFSET offset_list", "offset_list : INTEGER", "offset_list : offset_list INTEGER", "eco : ECO_ADDED_CELL", "legal_block_classes : LEGALBLKCLASS num_block_classes block_classes", "num_block_classes : INTEGER", "block_classes : block_class", "block_classes : block_classes block_class", "block_class : INTEGER", "initial_orient : ORIENT INTEGER", "initially :", "initially : INITIALLY", "fixed_type : FIXED", "fixed_type : NONFIXED", "fixed_type : RIGIDFIXED", "fixed_type : APPROXFIXED", "fixed_loc : LEFT", "fixed_loc : RIGHT", "mirror : NOMIRROR", "bbox : LEFT INTEGER RIGHT INTEGER BOTTOM INTEGER TOP INTEGER", "xloc : STRING", "yloc : STRING", "padname : PAD string NAME string", "padgroupname : PADGROUP string PERMUTE", "padgroupname : PADGROUP string NOPERMUTE", "supergroupname : SUPERGROUP string NAME string", "cellgroupname : CELLGROUP string NAME string", "corners : CORNERS INTEGER cornerpts", "cornerpts : INTEGER INTEGER", "cornerpts : cornerpts INTEGER INTEGER", "class : CLASS INTEGER", "orient : INTEGER ORIENTATIONS orientlist cur_orient", "orient : ORIENTATIONS orientlist cur_orient", "orientlist : INTEGER", "orientlist : orientlist INTEGER", "cur_orient :", "cur_orient : ORIENT INTEGER", "aspect : ASPLB FLOAT ASPUB FLOAT", "softpins : softtype", "softpins : softpins softtype", "softtype : pintype", "softtype : softpin", "hardpins : pintype", "hardpins : hardpins pintype", "pinlist :", "pinlist : stdgrppins", "stdgrppins : std_grppintype", "stdgrppins : stdgrppins std_grppintype", "stdpins : std_pintype", "stdpins : stdpins std_pintype", "std_grppintype : pinrecord", "std_grppintype : pinrecord equiv_list", "std_grppintype : pinrecord unequiv_list", "std_grppintype : pingroup", "std_pintype : pinrecord", "std_pintype : pinrecord equiv_list", "std_pintype : pinrecord unequiv_list", "pintype : pinrecord", "pintype : pinrecord equiv_list", "pingroup : PINGROUP stdpins ENDPINGROUP", "softpin : softpin_info siderestriction", "softpin : softpin_info siderestriction softequivs", "softpin_info : SOFTPIN NAME string SIGNAL string opt_layer", "pinrecord : required_pinfo contour current power no_layer_change", "required_pinfo : PIN NAME string SIGNAL string layer", "contour : INTEGER INTEGER", "contour : num_corners pin_pts", "num_corners : CORNERS INTEGER", "pin_pts : INTEGER INTEGER", "pin_pts : pin_pts INTEGER INTEGER", "current :", "current : CURRENT FLOAT", "power :", "power : POWER FLOAT", "no_layer_change :", "no_layer_change : NO_LAYER_CHANGE", "equiv_list : equiv", "equiv_list : equiv_list equiv", "$$1 :", "equiv : EQUIV NAME string layer $$1 contour", "unequiv_list : unequiv", "unequiv_list : unequiv_list unequiv", "$$2 :", "unequiv : UNEQUIV NAME string layer $$2 contour", "softequivs : mc_equiv", "softequivs : mc_equiv user_equiv_list", "softequivs : user_equiv_list", "mc_equiv : addequiv siderestriction", "addequiv : ADDEQUIV", "user_equiv_list : user_equiv", "user_equiv_list : user_equiv_list user_equiv", "user_equiv : equiv_name siderestriction connect", "equiv_name : EQUIV NAME string opt_layer", "connect :", "connect : CONNECT", "mc_pingroup : pingroupname pingrouplist siderestriction", "mc_pingroup : mc_pingroup pingroupname pingrouplist siderestriction", "pingroupname : PINGROUP string PERMUTE", "pingroupname : PINGROUP string NOPERMUTE", "pingrouplist : pinset", "pingrouplist : pingrouplist pinset", "pinset : string FIXED", "pinset : string NONFIXED", "siderestriction :", "siderestriction : RESTRICT SIDE side_list", "side_list : INTEGER", "side_list : side_list INTEGER", "sidespace :", "sidespace : SIDESPACE FLOAT", "sidespace : SIDESPACE FLOAT FLOAT", "layer : LAYER INTEGER", "opt_layer :", "opt_layer : LAYER INTEGER", "sideplace : STRING", "restriction :", "restriction : RESTRICT SIDE sideplace", "padgrouplist : padset", "padgrouplist : padgrouplist padset", "padset : string FIXED", "padset : string NONFIXED", "supergrouplist : string", "supergrouplist : supergrouplist string", "cellgrouplist : string", "cellgrouplist : cellgrouplist string", "keep_outs :", "keep_outs : keep_out_list", "keep_out_list : keep_out", "keep_out_list : keep_out_list keep_out", "keep_out : KEEPOUT LAYER INTEGER CORNERS keep_pts", "keep_pts : INTEGER INTEGER", "keep_pts : keep_pts INTEGER INTEGER", "string : STRING", "string : INTEGER", "string : FLOAT", }; #endif #define yyclearin (yychar=(-1)) #define yyerrok (yyerrflag=0) #ifdef YYSTACKSIZE #ifndef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #endif #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 500 #define YYMAXDEPTH 500 #endif #endif int yycnprs = 0; int yydebug; int yynerrs; int yyerrflag; int yychar; short *yyssp; YYSTYPE *yyvsp; YYSTYPE yyval; YYSTYPE yylval; short yyss[YYSTACKSIZE]; YYSTYPE yyvs[YYSTACKSIZE]; #define yystacksize YYSTACKSIZE #include "readcells_l.h" /* add readcells_l.h for debug purposes */ /* ********************* #include "readcells_l.h" *******************/ /* ********************* #include "readcells_l.h" *******************/ readcells( fp ) FILE *fp ; { #ifdef YYDEBUG extern int yydebug ; yydebug = FALSE ; D( "syntax/readcells", yydebug = TRUE ; ) ; #endif yyin = fp ; line_countS = 0 ; init() ; /* parse input file using yacc */ yyparse(); } /* end readcells */ yyerror(s) char *s; { sprintf(YmsgG,"problem reading %s.cel:", cktNameG ); M( ERRMSG, "yacc", YmsgG ) ; sprintf(YmsgG, " line %d near '%s' : %s\n" , line_countS+1, yytext, s ); M( MSG,"yacc", YmsgG ) ; } /* end yyerror */ yywrap() { return(1); } #define YYABORT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int yyparse() { register int yym, yyn, yystate; #if YYDEBUG register char *yys; extern char *getenv(); if (yys = getenv("YYDEBUG")) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = (-1); yyssp = yyss; yyvsp = yyvs; *yyssp = yystate = 0; yyloop: if (yyn = yydefred[yystate]) goto yyreduce; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, shifting to state %d\n", yystate, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; #ifdef lint goto yynewerror; #endif yynewerror: #if YYDEBUG { int test_state, i, expect, two_or_more ; char err_msg[BUFSIZ] ; if( yyname[yychar] ){ sprintf( err_msg, "Found %s.\nExpected ", yyname[yychar] ) ; two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } yyerror( err_msg ) ; if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } } else { sprintf( err_msg, "Found unknown token.\nExpected "); two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } yyerror( err_msg ) ; if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } } } #else yyerror("syntax error"); if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } #endif #ifdef lint goto yyerrlab; #endif yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, error recovery shifting\ to state %d\n", *yyssp, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("yydebug: error recovery discarding state %d\n", *yyssp); #endif if (yyssp <= yyss) goto yyabort; --yyssp; --yyvsp; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, error recovery discards token %d (%s)\n", yystate, yychar, yys); } #endif yychar = (-1); goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("yydebug: state %d, reducing by rule %d (%s)\n", yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; yyval = yyvsp[1-yym]; switch (yyn) { case 33: { sprintf( YmsgG, "hardcell at line %d does not have any pins\n", line_countS+1 ) ; M(WARNMSG,"readcells",YmsgG ) ; } break; case 40: { sprintf( YmsgG, "softcell at line %d does not have any pins\n", line_countS+1 ) ; M(WARNMSG,"readcells",YmsgG ) ; } break; case 41: { add_instance() ; Ysafe_free( yyvsp[0].string ) ; } break; case 43: { sprintf( YmsgG, "pad cell at line %d does not have any pins\n", line_countS+1 ) ; M(WARNMSG,"readcells",YmsgG ) ; } break; case 47: { addCell(HARDCELLTYPE, yyvsp[0].string ) ; Ysafe_free( yyvsp[-2].string ) ; } break; case 48: { addCell(SOFTCELLTYPE, yyvsp[0].string ) ; Ysafe_free( yyvsp[-2].string ) ; } break; case 49: { addCell(STDCELLTYPE, yyvsp[0].string ) ; Ysafe_free( yyvsp[-1].string ) ; } break; case 77: { set_bbox( yyvsp[-6].ival, yyvsp[-4].ival, yyvsp[-2].ival, yyvsp[0].ival ) ; } break; case 78: { check_xloc( yyvsp[0].string ) ; } break; case 79: { check_yloc( yyvsp[0].string ) ; } break; case 80: { addCell(PADCELLTYPE, yyvsp[0].string ) ; Ysafe_free( yyvsp[-2].string ) ; } break; case 81: { addCell(PADCELLTYPE, yyvsp[-1].string ) ; } break; case 82: { addCell(PADCELLTYPE, yyvsp[-1].string ) ; } break; case 83: { Ysafe_free( yyvsp[-2].string ) ; Ysafe_free( yyvsp[0].string ) ; } break; case 84: { /* fixed locations same as pad context */ Ysafe_free( yyvsp[-2].string ) ; Ysafe_free( yyvsp[0].string ) ; } break; case 85: { processCorners() ; } break; case 86: { start_pt( yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 87: { add_pt( yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 102: { sprintf( YmsgG, "standard cell at line %d does not have any pins\n", line_countS+1 ) ; M(WARNMSG,"readcells",YmsgG ) ; } break; case 120: { Ysafe_free( yyvsp[-3].string ) ; addNet( yyvsp[-1].string ) ; } break; case 122: { set_pinname( yyvsp[-3].string ) ; addNet( yyvsp[-1].string ) ; } break; case 123: { check_pos( yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 136: { set_pinname(yyvsp[-1].string) ; } break; case 137: { addEquiv() ; } break; case 140: { set_pinname(yyvsp[-1].string) ; } break; case 141: { addUnEquiv() ; } break; case 171: { check_sideplace( yyvsp[0].string ) ; } break; case 176: { Ysafe_free( yyvsp[-1].string ) ; } break; case 177: { Ysafe_free( yyvsp[-1].string ) ; } break; case 178: { Ysafe_free( yyvsp[0].string ) ; } break; case 179: { Ysafe_free( yyvsp[0].string ) ; } break; case 180: { Ysafe_free( yyvsp[0].string ) ; } break; case 181: { Ysafe_free( yyvsp[0].string ) ; } break; case 189: { yyval.string = yyvsp[0].string ; } break; case 190: { /* convert integer to string */ /* this allows integers to be used as strings */ /* a kluge but timberwolf's old parser supported it */ sprintf( bufferS,"%d", yyvsp[0].ival ) ; /* now clone string */ yyval.string = Ystrclone( bufferS ) ; } break; case 191: { /* convert float to string */ /* this allows floats to be used as strings */ /* a kluge but timberwolf's old parser supported it */ sprintf( bufferS,"%f", yyvsp[0].fval ) ; /* now clone string */ yyval.string = Ystrclone( bufferS ) ; } break; } yyssp -= yym; yystate = *yyssp; yyvsp -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state 0 to\ state %d\n", YYFINAL); #endif yystate = YYFINAL; *++yyssp = YYFINAL; *++yyvsp = yyval; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state %d \ to state %d\n", *yyssp, yystate); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate; *++yyvsp = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: return (1); yyaccept: return (0); } graywolf-0.1.4+20170307gite1bf319/src/syntax/readcells_l.h000066400000000000000000000414461305746555600225340ustar00rootroot00000000000000#ifdef linux #include #else # include "stdio.h" #endif # define U(x) ((x)&0377) # define NLSTATE yyprevious=YYNEWLINE # define BEGIN yybgin = yysvec + 1 + # define INITIAL 0 # define YYLERR yysvec # define YYSTATE (yyestate-yysvec-1) # define YYOPTIM 1 # define YYLMAX 200 # define output(c) putc(c,yyout) # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} # define yymore() (yymorfg=1) # define ECHO fprintf(yyout, "%s",yytext) # define REJECT { nstr = yyreject(); goto yyfussy;} int yyleng; extern char yytext[]; int yymorfg; extern char *yysptr, yysbuf[]; int yytchar; #ifdef linux FILE *yyin = NULL, *yyout = NULL; #else FILE *yyin ={stdin}, *yyout ={stdout}; #endif extern int yylineno; struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops;}; struct yysvf *yyestate; extern struct yysvf yysvec[], *yybgin; /* ----------------------------------------------------------------- FILE: readcells.l DESCRIPTION:rules for lexical analyzer for syntax checker. This lexical analyzer uses a binary search to reduce the size of the f.a. generated by lex. Thanks to Gary Richey who showed me the trick. See chapter 3 of "Introduction to Compiler Construction with UNIX" by Schreiner & Friedman for more details. CONTENTS: lex rules - screen() DATE: Aug 07, 1988 - need to add SccsId in comments due to yacc static char SccsId[] = "@(#) readcells.l version 1.12 5/22/92" ; REVISIONS: Oct 6, 1988 - fixed sign mistake in INTEGER & FLOAT Feb 12, 1989 - added <> to alphanum to handle DEC case. Apr 4, 1989 - added comments over multiple lines. May 7, 1989 - corrected pad groups. Jun 19, 1989 - added pin groups to syntax. Nov 5, 1989 - Fixed problem with sign - now ? (0 or 1 occurences) instead of * (0 or more). Mar 29, 1990 - added new MC softpin syntax. Fri Jan 25 17:58:05 PST 1991 - added missing SC keywords and added new alphanum. Fri Mar 22 20:18:19 CST 1991 - made letter more general. Thu Apr 18 01:13:03 EDT 1991 - removed unneeded tokens. Wed Jul 24 21:07:46 CDT 1991 - added analog input to syntax. ----------------------------------------------------------------- */ #undef YYLMAX #define YYLMAX 2000 /* comments may be at most 2000 characters */ #define token(x) x /* makes it look like regular lex */ #define END(v) (v-1 + sizeof(v) / sizeof( v[0] ) ) /* for table lookup */ static int screen() ; static int check_line_count() ; # define YYNEWLINE 10 yylex(){ int nstr; extern int yyprevious; while((nstr = yylook()) >= 0) yyfussy: switch(nstr){ case 0: if(yywrap()) return(0); break; case 1: { /* C-style comments over multiple lines */ check_line_count(yytext) ; } break; case 2: { /* convert to an integer */ yylval.ival = atoi( yytext ) ; return (INTEGER); } break; case 3: { /* convert to an float */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 4: { /* convert to an float */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 5: { return( screen() ) ; } break; case 6: { line_countS++;} break; case 7: ; break; case 8: { return( token(yytext[0]) ) ;} break; case -1: break; default: fprintf(yyout,"bad switch yylook %d",nstr); } return(0); } /* end of yylex */ /* reserved word screener */ /* ----------------------------------------------------------------- The following is table of the reserved words - Table must be in alphabetical order for binary search to work properly. ----------------------------------------------------------------- */ static struct rw_table { /* reserved word table */ char *rw_name ; /* pattern */ int rw_yylex ; /* lex token number */ } rwtable[] = { "ECO_added_cell", token(ECO_ADDED_CELL), "addequiv", token(ADDEQUIV), "approximately_fixed", token(APPROXFIXED), "asplb", token(ASPLB), "aspub", token(ASPUB), "at", token(AT), "block", token(BLOCK), "bottom", token(BOTTOM), "cell", token(CELL), "cell_offset", token(CELLOFFSET), "cellgroup", token(CELLGROUP), "class", token(CLASS), "connect", token(CONNECT), "corners", token(CORNERS), "current", token(CURRENT), "end_pin_group", token(ENDPINGROUP), "equiv", token(EQUIV), "fixed", token(FIXED), "from", token(FROM), "hardcell", token(HARDCELL), "initially", token(INITIALLY), "instance", token(INSTANCE), "keepout", token(KEEPOUT), "layer", token(LAYER), "left", token(LEFT), "legal_block_classes", token(LEGALBLKCLASS), "name", token(NAME), "neighborhood", token(NEIGHBORHOOD), "no_layer_change", token(NO_LAYER_CHANGE), "nomirror", token(NOMIRROR), "nonfixed", token(NONFIXED), "nopermute", token(NOPERMUTE), "of", token(OF), "orient", token(ORIENT), "orientations", token(ORIENTATIONS), "pad", token(PAD), "padgroup", token(PADGROUP), "permute", token(PERMUTE), "pin", token(PIN), "pin_group", token(PINGROUP), "power", token(POWER), "restrict", token(RESTRICT), "right", token(RIGHT), "rigidly_fixed", token(RIGIDFIXED), "side", token(SIDE), "sidespace", token(SIDESPACE), "signal", token(SIGNAL), "softcell", token(SOFTCELL), "softpin", token(SOFTPIN), "stdcell", token(STDCELL), "supergroup", token(SUPERGROUP), "swap_group", token(SWAPGROUP), "top", token(TOP), "unequiv", token(UNEQUIV) } ; static int screen() { int c ; struct rw_table *low = rwtable, /* ptr to beginning */ *mid , *high = END(rwtable) ; /* ptr to end */ /* binary search to look thru table to find pattern match */ while( low <= high){ mid = low + (high-low) / 2 ; if( (c = strcmp(mid->rw_name, yytext) ) == STRINGEQ){ return( mid->rw_yylex ) ; /* return token number */ } else if( c < 0 ){ low = mid + 1 ; } else { high = mid - 1 ; } } /* at this point we haven't found a match so we have a string */ /* save the string by making copy */ yylval.string = Ystrclone( yytext ) ; return (STRING); } /* end screen function */ static int check_line_count( s ) char *s ; { if( s ){ if( strlen(s) >= YYLMAX ){ sprintf(YmsgG,"comment beginning at line %d ",line_countS+1 ); M( ERRMSG, "lex", YmsgG ) ; sprintf(YmsgG,"exceeds maximum allowed length:%d chars.\n", YYLMAX ); M( MSG, NULL, YmsgG ) ; } for( ;*s;s++ ){ if( *s == '\n'){ line_countS++; } } } } /* end check_line_count */ int yyvstop[] ={ 0, 7, 0, 7, 0, 8, 0, 7, 8, 0, 6, 0, 5, 8, 0, 5, 8, 0, 3, 5, 8, 0, 5, 8, 0, 2, 8, 0, 7, 0, 5, 0, 3, 5, 0, 2, 5, 0, 5, 0, 3, 5, 0, 2, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 1, 5, 0, 5, 0, 4, 5, 0, 1, 0, 5, 0, 1, 5, 0, 1, 0, 0}; # define YYTYPE unsigned char struct yywork { YYTYPE verify, advance; } yycrank[] ={ 0,0, 0,0, 1,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,4, 1,5, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 1,7, 9,15, 0,0, 1,8, 1,9, 1,10, 7,13, 19,19, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 25,33, 26,34, 32,24, 33,25, 34,25, 0,0, 0,0, 0,0, 1,6, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 10,16, 0,0, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 14,16, 0,0, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 15,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 15,18, 15,18, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 0,0, 0,0, 0,0, 0,0, 18,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 16,22, 15,19, 18,23, 18,18, 20,24, 0,0, 18,18, 18,18, 18,18, 0,0, 15,20, 15,19, 20,24, 20,24, 15,19, 15,21, 15,19, 17,16, 0,0, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 18,18, 0,0, 0,0, 16,22, 0,0, 0,0, 0,0, 20,25, 15,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 20,26, 20,25, 0,0, 0,0, 20,25, 20,27, 20,25, 22,28, 0,0, 22,28, 0,0, 0,0, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 23,24, 0,0, 0,0, 0,0, 0,0, 20,25, 0,0, 24,18, 0,0, 23,30, 23,24, 0,0, 0,0, 23,24, 23,31, 23,24, 24,23, 24,18, 0,0, 0,0, 24,18, 24,32, 24,18, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 0,0, 0,0, 0,0, 23,24, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 24,18, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 30,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 30,23, 30,18, 0,0, 0,0, 30,18, 30,35, 30,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 30,18, 0,0, 0,0, 0,0}; struct yysvf yysvec[] ={ 0, 0, 0, yycrank+-1, 0, yyvstop+1, yycrank+0, yysvec+1, yyvstop+3, yycrank+0, 0, yyvstop+5, yycrank+3, 0, yyvstop+7, yycrank+0, 0, yyvstop+10, yycrank+38, 0, yyvstop+12, yycrank+4, yysvec+6, yyvstop+15, yycrank+117, yysvec+6, yyvstop+18, yycrank+3, yysvec+6, yyvstop+22, yycrank+129, yysvec+6, yyvstop+25, yycrank+0, yysvec+4, yyvstop+28, yycrank+0, yysvec+6, yyvstop+30, yycrank+139, yysvec+6, yyvstop+32, yycrank+151, yysvec+6, yyvstop+35, yycrank+-208, 0, yyvstop+38, yycrank+171, yysvec+6, yyvstop+40, yycrank+211, yysvec+6, yyvstop+43, yycrank+-200, yysvec+15, 0, yycrank+-4, yysvec+15, yyvstop+45, yycrank+-243, 0, yyvstop+47, yycrank+0, yysvec+15, yyvstop+49, yycrank+249, yysvec+6, yyvstop+51, yycrank+-274, yysvec+20, 0, yycrank+-281, yysvec+15, 0, yycrank+-15, yysvec+15, yyvstop+53, yycrank+-16, yysvec+15, yyvstop+55, yycrank+0, yysvec+6, yyvstop+57, yycrank+282, yysvec+6, yyvstop+60, yycrank+303, yysvec+6, yyvstop+62, yycrank+-328, yysvec+15, 0, yycrank+0, 0, yyvstop+65, yycrank+17, 0, 0, yycrank+18, yysvec+6, yyvstop+67, yycrank+19, yysvec+6, yyvstop+69, yycrank+0, yysvec+32, yyvstop+72, 0, 0, 0}; struct yywork *yytop = yycrank+397; struct yysvf *yybgin = yysvec+1; char yymatch[] ={ 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 011 ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'*' ,'+' ,'!' ,'+' ,'.' ,'/' , '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , '0' ,'0' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 0}; char yyextra[] ={ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0}; /* ncform 4.1 83/08/11 */ int yylineno =1; # define YYU(x) x # define NLSTATE yyprevious=YYNEWLINE char yytext[YYLMAX]; struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; char yysbuf[YYLMAX]; char *yysptr = yysbuf; int *yyfnd; extern struct yysvf *yyestate; int yyprevious = YYNEWLINE; yylook(){ register struct yysvf *yystate, **lsp; register struct yywork *yyt; struct yysvf *yyz; int yych; struct yywork *yyr; # ifdef LEXDEBUG int debug; # endif char *yylastch; #ifdef linux if (yyin == NULL) yyin = stdin; if (yyout == NULL) yyout = stdout; #endif /* start off machines */ # ifdef LEXDEBUG debug = 0; # endif if (!yymorfg) yylastch = yytext; else { yymorfg=0; yylastch = yytext+yyleng; } for(;;){ lsp = yylstate; yyestate = yystate = yybgin; if (yyprevious==YYNEWLINE) yystate++; for (;;){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); # endif yyt = yystate->yystoff; if(yyt == yycrank){ /* may not be any transitions */ yyz = yystate->yyother; if(yyz == 0)break; if(yyz->yystoff == yycrank)break; } *yylastch++ = yych = input(); tryagain: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"unsigned char "); allprint(yych); putchar('\n'); } # endif yyr = yyt; if ( (long)yyt > (long)yycrank){ yyt = yyr + yych; if (yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } # ifdef YYOPTIM else if((long)yyt < (long)yycrank) { /* r < yycrank */ yyt = yyr = yycrank+(yycrank-yyt); # ifdef LEXDEBUG if(debug)fprintf(yyout,"compressed state\n"); # endif yyt = yyt + yych; if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } yyt = yyr + YYU(yymatch[yych]); # ifdef LEXDEBUG if(debug){ fprintf(yyout,"try fall back character "); allprint(YYU(yymatch[yych])); putchar('\n'); } # endif if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transition */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); # endif goto tryagain; } # endif else {unput(*--yylastch);break;} contin: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"state %d char ",yystate-yysvec-1); allprint(yych); putchar('\n'); } # endif ; } # ifdef LEXDEBUG if(debug){ fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); allprint(yych); putchar('\n'); } # endif while (lsp-- > yylstate){ *yylastch-- = 0; if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ yyolsp = lsp; if(yyextra[*yyfnd]){ /* must backup */ while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ lsp--; unput(*yylastch--); } } yyprevious = YYU(*yylastch); yylsp = lsp; yyleng = yylastch-yytext+1; yytext[yyleng] = 0; # ifdef LEXDEBUG if(debug){ fprintf(yyout,"\nmatch "); sprint(yytext); fprintf(yyout," action %d\n",*yyfnd); } # endif return(*yyfnd++); } unput(*yylastch); } if (yytext[0] == 0 /* && feof(yyin) */) { yysptr=yysbuf; return(0); } yyprevious = yytext[0] = input(); if (yyprevious>0) output(yyprevious); yylastch=yytext; # ifdef LEXDEBUG if(debug)putchar('\n'); # endif } } yyback(p, m) int *p; { if (p==0) return(0); while (*p) { if (*p++ == m) return(1); } return(0); } /* the following are only used in the lex library */ yyinput(){ #ifdef linux if (yyin == NULL) yyin = stdin; #endif return(input()); } yyoutput(c) int c; { #ifdef linux if (yyout == NULL) yyout = stdout; #endif output(c); } yyunput(c) int c; { unput(c); } graywolf-0.1.4+20170307gite1bf319/src/twflow/000077500000000000000000000000001305746555600200755ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/src/twflow/CMakeLists.txt000066400000000000000000000006261305746555600226410ustar00rootroot00000000000000 add_executable(graywolf autoflow.c findflow.c graphics.c io.c main.c program.c readobjects.c ${CMAKE_SOURCE_DIR}/src/date/date.c) target_link_libraries(graywolf ${CMAKE_BINARY_DIR}/src/Ylib/libycadgraywolf.so) target_link_libraries(graywolf X11) target_link_libraries(graywolf m) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include .) install(TARGETS graywolf DESTINATION bin) graywolf-0.1.4+20170307gite1bf319/src/twflow/autoflow.c000066400000000000000000000214431305746555600221050ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: autoflow.c DESCRIPTION:This file contains routines for following the flow. CONTENTS: auto_flow() exec_single_prog() report_problem( adjptr ) ADJPTR adjptr ; BOOL check_dependencies( adjptr ) ADJPTR adjptr ; autoflow_set_object( object ) INT object ; DATE: May 7, 1989 - original coding. REVISIONS: May 25, 1989 - added needtoExecute to handle case of no input file but an output file. Jun 19, 1989 - added $ to be substitute for designName. Jun 21, 1989 - fixed bug in auto flow code concerning multiple edges on a single program execution. Nov 23, 1990 - now exit status is correct if a program experiences trouble. Fri Feb 22 23:55:29 EST 1991 - fixed new library rename. Sun Apr 21 22:33:53 EDT 1991 - now allow optional files. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) autoflow.c version 2.4 4/21/91" ; #endif #include #include #include #include #include #define STARTOBJECT 0 /* start of the graph */ #define ERROR -1 /* error from YgetFileTime() */ static INT objectS ; /* the last program that was run */ auto_flow() { ADJPTR adjptr ; /* current edge in graph */ ADJPTR make_decision(); /* decides which way to travel */ OBJECTPTR o ; /* current object */ objectS = STARTOBJECT ; problemsG = FALSE ; unmark_edges() ; /* set all program edges to be unmarked */ while( autoflowG ){ /* loop until done */ o = proGraphG[objectS] ; if( o->numedges > 1 ){ adjptr = make_decision( o, FORWARD ) ; } else if( o->numedges == 1 ){ ASSERT( o->adjF, "auto_flow", "Null edge pointer\n" ) ; adjptr = o->adjF ; } else { /* now edges we are done */ break ; } /* new object to be executed */ objectS = adjptr->node ; /* tell graphics selected object and draw it */ G( graphics_set_object( objectS ) ) ; G( draw_the_data() ) ; if( check_dependencies( adjptr ) ){ /* program files are out of date execute program */ if( executePgm( adjptr ) ){ /* we received a non zero return code break loop */ /* report problem */ report_problem( adjptr ) ; break ; } } /* allow user to change things */ /* G( ) is NOGRAPHICS conditional compile */ G( if( graphicsG && TWinterupt() ) ){ G( process_graphics() ) ; } } /* end autoflow loop */ G( draw_the_data() ) ; } /* end autoflow */ exec_single_prog() { ADJPTR adjptr ; /* current edge in graph */ ADJPTR get_edge_from_user(); /* decides which way to travel */ ADJPTR findEdge() ; /* find the edge for the given nodes */ OBJECTPTR o ; /* current object */ char filename[LRECL] ;/* buffer for filename */ FPTR fdepend ; /* current file in question */ INT numedges ; /* count backward edges */ o = proGraphG[objectS] ; /* get backwards edge count */ numedges = 0 ; for( adjptr = o->adjB; adjptr; adjptr = adjptr->next ){ numedges++ ; } if( numedges > 1 ){ adjptr = get_edge_from_user( o, BACKWARD ) ; } else if( numedges == 1 ){ ASSERT( o->adjB, "auto_flow", "Null edge pointer\n" ) ; adjptr = o->adjB ; } else { /* now edges we are done */ return ; } /* tell graphics selected object and draw it */ G( graphics_set_object( objectS ) ) ; G( draw_the_data() ) ; /* now find forward edge */ adjptr = findEdge( adjptr->node, objectS, FORWARD ) ; /* check to see all input files exist */ for( fdepend = adjptr->ifiles;fdepend; fdepend = fdepend->next ){ ASSERTNCONT( fdepend->fname, "auto_flow","Null file name\n"); if( *fdepend->fname == '$' ){ /* suffix keyword */ sprintf( filename, "%s%s", cktNameG, fdepend->fname+1 ) ; } else { strcpy( filename, fdepend->fname ) ; } if(!(YfileExists( filename,TRUE )) && !(fdepend->optional) ){ sprintf( YmsgG, "ERROR:input file %s does not exist", filename ) ; G( TWmessage( YmsgG ) ) ; M( ERRMSG, NULL, YmsgG ) ; M( MSG, NULL, "\n" ) ; return ; } } /* end check of all input files */ if( executePgm( adjptr ) ){ /* we received a non zero return code break loop */ report_problem( adjptr ) ; } G( draw_the_data() ) ; } /* end exec_single_prog */ report_problem( adjptr ) ADJPTR adjptr ; { sprintf( YmsgG, "Trouble executing %s", proGraphG[adjptr->node]->name) ; G( TWmessage( YmsgG ) ) ; problemsG = TRUE ; } /* end report_problem */ /* returns true if files are out of date - false otherwise */ BOOL check_dependencies( adjptr ) ADJPTR adjptr ; { INT input_time ; /* last input file which was modified */ INT output_time ; /* first output file */ INT ftime ; /* time file was modified */ INT YgetFileTime() ; /* returns last time file was modified */ char filename[LRECL] ;/* buffer for filename */ FPTR fdepend ; /* current file in question */ BOOL needtoExecute ; /* TRUE if an output file doesnt exist */ /* check dependencies */ /* find the input file which was modified last */ input_time = INT_MIN ; for( fdepend = adjptr->ifiles;fdepend; fdepend = fdepend->next ){ ASSERTNCONT( fdepend->fname, "auto_flow","Null file name\n"); if( *fdepend->fname == '$' ){ /* suffix keyword */ sprintf( filename, "%s%s", cktNameG, fdepend->fname+1 ) ; } else { strcpy( filename, fdepend->fname ) ; } if(!(YfileExists( filename,TRUE ))){ continue ; } ftime = YgetFileTime( filename ) ; if( ftime == ERROR ){ Ymessage_error_count() ; } input_time = MAX( ftime, input_time ) ; } /* find the output file which was modified the earliest */ output_time = INT_MAX ; /* *************************************************************** * Conditions for program execution: * 1. Input files have later date than output files. * 2. An output file does not exist. * 3. No given output files program is assumed to always be executed. * ************************************************************* */ /* first make check if no output files exist program is executed */ if( fdepend = adjptr->ofiles ){ /* program may not need to be executed */ needtoExecute = FALSE ; } else { /* always needs to be executed */ needtoExecute = TRUE ; } for( ; fdepend; fdepend = fdepend->next ){ ASSERTNCONT( fdepend->fname,"auto_flow","Null file name\n" ); if( *fdepend->fname == '$' ){ sprintf( filename, "%s%s", cktNameG, fdepend->fname+1 ) ; } else { strcpy( filename, fdepend->fname ) ; } if(!(YfileExists( filename,TRUE ))){ /* one of the output files doesn't exist */ needtoExecute = TRUE ; continue ; } ftime = YgetFileTime( filename ) ; if( ftime == ERROR ){ Ymessage_error_count() ; } output_time = MIN( ftime, output_time ) ; } if( output_time < input_time || needtoExecute ){ /* files are out of date - program needs to be executed */ return( TRUE ) ; } return( FALSE ) ; } /* end BOOL check_dependencies */ /* allow graphics loop to change the object */ autoflow_set_object( object ) INT object ; { objectS = object ; } /* end autoflow_set_object */ graywolf-0.1.4+20170307gite1bf319/src/twflow/date.h000066400000000000000000000001071305746555600211610ustar00rootroot00000000000000#define DATE "@(#) Yale compilation date:Mon May 25 21:15:08 EDT 1992" graywolf-0.1.4+20170307gite1bf319/src/twflow/findflow.c000066400000000000000000000174011305746555600220540ustar00rootroot00000000000000/* * Copyright (C) 1990-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: findflow.c DESCRIPTION:Determine the correct flow file for the TimberWolf system. DATE: Aug 1, 1990 REVISIONS: Sun Jan 20 21:31:36 PST 1991 - ported to AIX. Sat Feb 23 04:39:32 EST 1991 - added TOMUS case. Thu Apr 18 01:18:32 EDT 1991 - now changed where to look for the flow files. User can override. ---------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) findflow.c version 1.4 4/18/91" ; #endif #include #include #include #include #include #ifndef NOGRAPHICS #include #include #endif FILE *find_flow_file( general_mode, debug, filename ) BOOL general_mode, debug ; char *filename ; { INT type ; /* design type */ INT find_design_type() ; char prefix[LRECL] ; char suffix[LRECL] ; FILE *fp ; /* ************************************************************** * Now look for twflow file. First determine prefix based on * whether it is TimberWolf mode or general mode. If general * mode the prefix is easy "user". If the mode is the TimberWolf * mode determine the design style using the syntax program. * The syntax program will tell us the number of standard cells, * macro cells etc. Use file dependancies to check if it needs * to be run. The TimberWolf prefixes are: * 1. mixed * 2. standard * 3. macro * 4. tomus * The suffix may be one of the following: * 1. Debug. * 2. No graphics. * 3. Graphics and no debug. * Next look for the flowfile in : * 1. specified flow directory. Exit if can't open. * 2. current directory. Don't exit if doesn't exist. * 3. TimberWolf directory. * ************************************************************* */ if( general_mode ){ sprintf( prefix, "user" ) ; } else { type = find_design_type() ; switch( type ){ case MIXED: sprintf( prefix, "mixed" ) ; break ; case STANDARD: sprintf( prefix, "standard" ) ; break ; case MACRO: sprintf( prefix, "macro" ) ; break ; case TOMUS: sprintf( prefix, "tomus" ) ; break ; case UNKNOWN: M( ERRMSG, "find_flow_file", "FATAL - Couldn't determine design type\n" ) ; YexitPgm( PGMFAIL ) ; } } if( debug ){ sprintf( suffix, "fdbg" ) ; } else if ( !(graphicsG) ){ sprintf( suffix, "fnog" ) ; } else { sprintf( suffix, "flow" ) ; } if( flow_dirG ){ /* first try absolute path */ sprintf( filename, "%s/%s.%s", flow_dirG, prefix, suffix ) ; if( fp = TWOPEN( filename, "r", NOABORT ) ){ return( fp ) ; } /* next try relative to TimberWolf root directory. */ sprintf( filename, "%s/bin/flow/%s/%s.%s", twdirG, flow_dirG, prefix, suffix ) ; if( fp = TWOPEN( filename, "r", NOABORT ) ){ return( fp ) ; } /* if we get here we have trouble we must abort. Write msg */ M( ERRMSG, "find_flow_file", "Could not open either\n" ) ; sprintf( YmsgG, "\n\t%s\n", filename ) ; M( ERRMSG, NULL, YmsgG ) ; M( ERRMSG, NULL, " or\n" ) ; sprintf( YmsgG, "\t%s/%s.%s\n", flow_dirG, prefix,suffix); M( ERRMSG, NULL, YmsgG ) ; show_flows() ; if( graphicsG ){ G( TWcloseGraphics() ) ; } YexitPgm(PGMFAIL) ; } sprintf( filename, "%s.%s", prefix, suffix ) ; fp = TWOPEN( filename, "r", NOABORT ) ; if( !(fp) ){ sprintf( filename, "%s/bin/flow/flow/%s.%s",twdirG,prefix,suffix ) ; fp = TWOPEN( filename, "r", ABORT ) ; } return( fp ) ; } /* end find_flow_file */ /* call syntax if necessary and then read result */ INT find_design_type() { ADJBOX syntax_info ; FBOX infile ; FBOX outfile ; INT status ; INT numtokens ; INT num_stdcell ; INT num_macro ; INT mode ; FILE *fin ; char in_name[8] ; char out_name[8] ; char buffer[LRECL] ; char *bufferptr ; char **tokens ; /* this is an easy case */ if( tomusG ){ return( TOMUS ) ; } /* set up the information to call check_dependencies */ sprintf( in_name, "$.cel" ) ; sprintf( out_name, "$.stat" ) ; infile.fname = in_name ; infile.next = NULL ; outfile.fname = out_name ; outfile.next = NULL ; syntax_info.ifiles = &infile ; syntax_info.ofiles = &outfile ; G( TWmessage( "Determining design type" ) ) ; if( !graphicsG ){ M( MSG, "find_flow", "Determining design type\n" ) ; } if( check_dependencies( &syntax_info ) ){ /* we need to execute the syntax program */ sprintf( buffer, "%s/bin/syntax %s", twdirG, cktNameG ) ; /* now log the beginning time */ Ylog_msg( "Syntax started..." ) ; G( TWstartFrame() ) ; G( TWmessage( "Calling syntax to determine design type" ) ) ; G( TWsetwindow( -165, -55, 165, 55 ) ) ; G( TWdrawCell( 0, -150, -50, 150, 50, TWRED, "syntax" ) ) ; G( TWflushFrame() ) ; /* now execute the command */ status = system( buffer ) ; if( status ){ M( ERRMSG, "find_design_type", "Trouble executing syntax\n" ) ; M( MSG, NULL, "FATAL - must exit\n\n" ) ; YexitPgm( PGMFAIL ) ; } Ylog_msg( "Syntax completed..." ) ; G( TWmessage( "Syntax completed successfully..." ) ) ; } /*********************************************************** * Read from circuitName.stat file to determine design style. ***********************************************************/ sprintf( buffer, "%s.stat", cktNameG ) ; fin = TWOPEN( buffer,"r", ABORT ) ; while( bufferptr = fgets( buffer, LRECL, fin ) ){ tokens = Ystrparser( bufferptr, ":\t\n", &numtokens ) ; if( numtokens != 2 ){ continue ; } if( strcmp( tokens[0], "num_stdcells" ) == STRINGEQ ){ num_stdcell = atoi( tokens[1] ) ; } else if( strcmp( tokens[0], "num_macros" ) == STRINGEQ ){ num_macro = atoi( tokens[1] ) ; } } TWCLOSE( fin ) ; /* now make decision based on the numbers */ if( num_stdcell > 0 && num_macro > 0 ){ mode = MIXED ; } else if( num_stdcell > 0 && num_macro == 0 ){ mode = STANDARD ; } else if( num_stdcell == 0 && num_macro > 0 ){ mode = MACRO ; } else { mode = UNKNOWN ; } D( "find_design_type", fprintf( stderr, "Found design type %d\n", mode ) ; ) ; return( mode ) ; } /* end find_design_type */ graywolf-0.1.4+20170307gite1bf319/src/twflow/globals.h000066400000000000000000000133401305746555600216720ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: globals.h DESCRIPTION:This file contains type declarations for the master program. CONTENTS: DATE: May 6, 1989 - original coding WPS. REVISIONS: Jun 19, 1989 - added marked to ADJPTR record. Nov 23, 1990 - now exit status is correct if a program experiences trouble. Sat Feb 23 04:49:55 EST 1991 - added TOMUS definitions Thu Mar 7 01:35:22 EST 1991 - now windowID is a global and twflow can inherit a window itself. Thu Apr 18 01:19:41 EDT 1991 - now user can specify a flow file. Sun Apr 21 22:34:28 EDT 1991 - now allow optional files. ----------------------------------------------------------------- */ #ifndef GLOBALS_H #define GLOBALS_H #ifndef lint static char SccsGlobals_h[] = "@(#) globals.h (Yale) version 2.6 4/21/91" ; #endif #ifndef GLOBAL_DEFS #define EXTERN extern #else #define EXTERN #endif /* if not using makefile and debug is wanted add it here */ /* #define DEBUG */ /* remove graphics lines of code if compile switch is on */ #ifdef NOGRAPHICS #define G(x_xz) #else #define G(x_xz) if( graphicsG ) x_xz #endif /* NOGRAPHICS */ #include #include /********************** DEFINE STATEMENTS *********************/ #define MASTER "twflow" /* the program name */ #define MASTERFAIL (64+1) /* catastrophic problem exit code */ #define MAXARGS 10 /* maximum number of arguments to a prog.*/ #define INPUTFILE TRUE #define OUTPUTFILE FALSE #define FORWARD TRUE #define BACKWARD FALSE /* the supported TimberWolf flows */ #define MIXED 0 #define STANDARD 1 #define MACRO 2 #define TOMUS 3 #define UNKNOWN 4 /* memory usage macro */ #define MEMUSAGE { sprintf( YmsgG,"Current memory usage:%d\n", \ YgetCurMemUse() ) ;\ M( MSG, NULL, YmsgG ) ; } /* macro to speed division by 2 */ #define DIVIDED_BY_2 >> 1 /********************** TYPEDEF STATEMENTS *********************/ typedef struct dbox { /* draw box to draw lines */ INT x1, y1 ; /* first point of line */ INT x2, y2 ; /* second point of line */ struct dbox *next ; /* next line to draw */ } DBOX, *DPTR ; typedef struct fbox { /* file box to maintain file concurrency */ char *fname ; /* name of file suffix */ BOOL optional ; /* TRUE if an optional file */ struct fbox *next ; /* next file in list */ } FBOX, *FPTR ; typedef struct adjbox { INT node ; /* head of edge */ char **argv ; /* argument vector - limited to MAXARGS */ INT argc ; /* argument count */ BOOL marked ; /* whether edge has been executed */ FPTR ifiles ; /* files program is dependent on */ FPTR ofiles ; /* files this program generates */ DPTR geometry ; /* how to draw the edge */ struct adjbox *next ; /* next edge of this node */ } ADJBOX, *ADJPTR ; typedef struct objectbox { char *name ; /* name of object */ char *path ; /* pathname of object */ INT node ; /* self index */ INT numedges ; /* number of outgoing edges */ INT l ; /* the extent of the cell bounding box */ INT r ; /* global position */ INT b ; INT t ; ADJPTR adjF ; /* the edges in the graph */ ADJPTR adjB ; } OBJECTBOX, *OBJECTPTR ; /* ******************** GLOBAL VARIABLES *********************** */ /* the graph data structure */ EXTERN OBJECTPTR *proGraphG ; /* array of pointers to program nodes */ /* the size of the data */ EXTERN INT numobjectsG ; /* number of program objects */ EXTERN char *cktNameG ; /* name of the design */ EXTERN char *twdirG ; /* name of the TimberWolf directory */ EXTERN char *flow_dirG ; /* name of user specified flow dir. */ EXTERN BOOL graphicsG ; /* whether graphics is requested */ EXTERN BOOL autoflowG ; /* whether autoflow is enabled */ EXTERN BOOL problemsG ; /* whether problems were encountered */ EXTERN BOOL tomusG ; /* TRUE if called from partitioning */ #endif /* GLOBALS_H */ graywolf-0.1.4+20170307gite1bf319/src/twflow/graphics.c000066400000000000000000000311651305746555600220470ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: graphics.c DESCRIPTION:This file contains graphic routines for twflow program. CONTENTS: init_graphics() void draw_the_data() process_graphics() ADJPTR make_decision( obj, direction ) OBJECTPTR obj ; BOOL direction ; ADJPTR get_edge_from_user( obj, direction ) OBJECTPTR obj ; BOOL direction ; graphics_set_object( object ) INT find_obj() DATE: May 7, 1989 - original coding. REVISIONS: Jun 19, 1989 - added return for no graphics case. Jun 19, 1989 - added prompt toggle. Added get_edge_from_user and modified make_decision so that multiple edge case is correct Aug 1, 1990 - modified more than one selection mechanism to make it easier for the user. Sat Feb 23 00:15:36 EST 1991 - added dump. Sat Feb 23 04:51:29 EST 1991 - added parasite mode. Sun Apr 21 22:35:09 EDT 1991 - updated to the convention. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) graphics.c version 2.6 4/21/91" ; #endif #include #include #include #include #include #include #include #include #define SLEEPTIME (unsigned) 2 #define DATADIR "./DATA" #define MENUP "twflow_menu" #define WAITMSG "graywolf is waiting for your response..." static BOOL auto_drawS = TRUE ; static BOOL promptS = FALSE ; /* whether to prompt for path */ static INT selectedObjS = 0 ; /* current selected object */ static ADJPTR selectedEdgeS = NULL ; /* current selected edge */ #ifndef NOGRAPHICS /* #define DEVELOPMENU */ /* During development use TWread_menus in place of menuS */ /* to create menu record, ie. TWread_menus(MENUP) */ #ifdef DEVELOPMENU #define MENU TWread_menus(MENUP) #else #define MENU menuS #endif #include init_graphics(argc,argv,windowId) INT argc ; char *argv[] ; INT windowId ; { INT draw_the_data() ; if( !(graphicsG) ){ return ; } if( windowId ){ /* init windows as a parasite */ fprintf( stderr,"windowId:%d\n", windowId ) ; if( !( TWinitParasite(argc,argv,TWnumcolors(),TWstdcolors(), FALSE, MENU, draw_the_data, windowId ))){ M(ERRMSG,"initgraphics","Aborting graphics."); graphicsG = FALSE ; return ; } } else { if(!(TWinitGraphics(argc,argv,TWnumcolors(),TWstdcolors(), FALSE, MENU, draw_the_data ))){ M(ERRMSG,"init_graphics","Aborting graphics."); graphicsG = FALSE ; return ; } } TWdrawMenus() ; TWflushFrame() ; } /* end init_graphics */ /* draw_the_data routine draws compaction graph */ INT draw_the_data() { INT i ; INT color ; OBJECTPTR o ; DPTR dptr ; ADJPTR eptr ; /* graphics is turned off */ if( !graphicsG ){ return ; } TWstartFrame() ; /* first draw the objects */ for( i=1; i<= numobjectsG;i++){ o = proGraphG[i] ; if( i == selectedObjS ){ color = TWRED ; } else { color = TWGREEN ; } TWdrawCell( i, o->l,o->b,o->r,o->t, color, o->name ) ; } /* end drawing the objects */ /* next draw the edges between objects */ /* go thru all the objects */ for( i=1;i<= numobjectsG;i++){ /* go thru all the edges of an object */ for( eptr = proGraphG[i]->adjF ;eptr; eptr=eptr->next){ if( eptr == selectedEdgeS ){ color = TWRED ; } else { color = TWBLUE ; } for( dptr = eptr->geometry; dptr ; dptr = dptr->next ){ TWdrawNet( i,dptr->x1,dptr->y1, dptr->x2,dptr->y2, color, NULL); } } } TWflushFrame() ; if( YdebugAssert() ){ sleep( SLEEPTIME ) ; } } /* end draw_the_data */ /* heart of the graphic system processes user input */ process_graphics() { INT selection ; /* the users pick */ INT find_obj() ; /* find the users pick */ INT x, y ; /* the picked point */ /* data might have changed so show user current config */ /* any function other that the draw controls need to worry about */ /* this concurrency problem - show user current config */ draw_the_data() ; /* use TWcheckExposure to flush exposure events since we just */ /* drew the data */ TWcheckExposure() ; TWmessage( WAITMSG ) ; M( MSG, NULL, WAITMSG ) ; M( MSG, NULL, "\n" ) ; selection = CANCEL ; while( selection != CONTINUE_PGM ){ /* loop until exit */ selection = TWcheckMouse() ; switch( selection ){ case CANCEL: /* do nothing */ break ; case AUTO_REDRAW_ON: auto_drawS = TRUE ; break ; case AUTO_REDRAW_OFF: auto_drawS = FALSE ; break ; case CLOSE_GRAPHICS: TWcloseGraphics() ; /* update all costs and reload cells */ graphicsG = FALSE ; return ; case COLORS: TWtoggleColors() ; break ; case CONTINUE_PGM: break ; case DUMP_GRAPHICS: TWsetFrame(0) ; /* update the frame count */ /* now change mode to dump to file */ TWsetMode(1) ; /* dump the data to a file now instead of screen */ draw_the_data() ; /* restore the state to previous condition */ /* and set draw to screen */ TWsetMode(0) ; break ; case EXIT_PROGRAM: TWcloseGraphics() ; YexitPgm( PGMOK ) ; return ; case FULLVIEW: TWfullView() ; break ; case REDRAW: draw_the_data() ; /* use TWcheckExposure to flush exposure events since */ /* we just drew the data */ TWcheckExposure() ; break ; case TELL_POINT: TWmessage( "Pick a point" ) ; TWgetPt( &x, &y ) ; sprintf( YmsgG,"The point is (%d,%d)",x,y ) ; TWmessage( YmsgG ) ; break ; case TRANSLATE: TWtranslate() ; break ; case ZOOM: TWzoom() ; break ; case AUTOFLOW: autoflowG = TRUE ; /* used to interupt auto flow */ auto_flow() ; break ; case PICK_PGM: selectedObjS = find_obj() ; autoflow_set_object( selectedObjS ) ; break ; case EXECUTE_PGM: exec_single_prog() ; break ; case PROMPT_ON: promptS = TRUE ; TWmessage( "Prompt on" ) ; break ; case PROMPT_OFF: promptS = FALSE ; TWmessage( "Prompt off" ) ; break ; } /* end switch */ if( auto_drawS && TWcheckExposure() ){ draw_the_data() ; } } TWmessage("Continuing - to interupt program click on top menu window") ; } /* end process_graphics */ /* get edge loops until it gets answer from user */ ADJPTR get_edge_from_user( obj, direction ) OBJECTPTR obj ; BOOL direction ; { ADJPTR adjptr ; ADJPTR start_edge ; ADJPTR findEdge() ; INT edge_count ; char *answer ; while( TRUE ){ /* loop until user makes a selection */ if( direction == FORWARD ){ start_edge = obj->adjF ; } else { start_edge = obj->adjB ; } /* count the number of edges that meet the criteria */ edge_count = 0 ; for( adjptr = start_edge ; adjptr ; adjptr = adjptr->next ){ edge_count++ ; } for( adjptr = start_edge ; adjptr ; adjptr = adjptr->next ){ if( direction == FORWARD ){ selectedEdgeS = adjptr ; } else { /* need to reverse edge so selectedEdge will match */ selectedEdgeS = findEdge( adjptr->node, obj->node, FORWARD ) ; } /* show user the edge */ draw_the_data() ; TWcheckExposure() ; if( edge_count > 1 ){ /* give directions */ sprintf( YmsgG,"%s","If edge is not correct, enter n ") ; strcat( YmsgG, "for next edge. If satisfied, enter non-null string:") ; /* look for empty string - means we are satisfied */ answer = TWgetString(YmsgG) ; if( answer ){ if( *answer != 'n' ){ return( adjptr ) ; } } else { return( adjptr ) ; } } else { /* simple case the correct edge */ return( adjptr ) ; } } /* end for loop */ } /* end while loop */ } /* end get_edge_from_user */ /* the corresponding handshake to set the highlighted drawing object */ graphics_set_object( object ) INT object ; { selectedObjS = object ; /* set the current selected object */ } /* graphics_set_object */ /* find the object in question */ INT find_obj() { INT i ; INT x, y ; /* coordinates picked by user */ INT obj ; /* selected cell */ OBJECTPTR o ; /* pointer to object */ obj = 0 ; TWmessage("Pick program by clicking any mouse button at center of object"); #ifdef NEEDED (void) sleep(SLEEPTIME) ; #endif TWgetPt( &x, &y ) ; /* look thru all programs O(programs) algorithm */ for( i=1; i<= numobjectsG;i++){ o = proGraphG[i] ; /* see if cell boundary contains this point */ if( x >= o->l && x <= o->r ){ if( y >= o->b && y <= o->t ){ selectedObjS = i ; draw_the_data() ; TWcheckExposure() ; obj = selectedObjS ; break ; } } } /* end loop */ if( obj == 0 ){ TWmessage( "No cell selected" ) ; if( selectedObjS ){ /* user didn't like any options */ selectedObjS = 0 ; draw_the_data() ; /* draw the data with highlight off */ TWcheckExposure() ; } } else { sprintf( YmsgG, "Selected program:%s", proGraphG[obj]->name ) ; TWmessage( YmsgG ) ; } return( obj ) ; } /* end find_obj */ #else /* NOGRAPHICS case */ /* get edge loops until it gets answer from user */ ADJPTR get_edge_from_user( obj, direction ) OBJECTPTR obj ; BOOL direction ; { ADJPTR adjptr ; ADJPTR findEdge() ; INT node1, node2 ; char reply[LRECL] ; while( TRUE ){ /* loop until user makes a selection */ if( direction == FORWARD ){ adjptr = obj->adjF ; } else { adjptr = obj->adjB ; } for( ; adjptr ; adjptr = adjptr->next ){ if( direction == FORWARD ){ node1 = obj->node ; node2 = adjptr->node ; } else { node1 = adjptr->node ; node2 = obj->node ; } /* tell the user the edge */ /* give directions */ fprintf( stdout,"%s-->%s", proGraphG[node1]->name, proGraphG[node2]->name ) ; fprintf( stdout,"If execution path is correct, enter y[es].\n") ; fprintf( stdout,"Otherwise enter n for next edge.\n") ; fscanf( stdout, "%s", reply ) ; if( reply ){ if( reply[0] == 'y' || reply[0] == 'Y' ){ return( adjptr ) ; } } } /* end for loop */ } /* end while loop */ } /* end get_edge_from_user */ #endif /* NOGRAPHICS */ /* make_decision asks the user for the next program to run */ ADJPTR make_decision( obj, direction ) OBJECTPTR obj ; BOOL direction ; { ADJPTR adjptr ; ADJPTR get_edge_from_user() ; if( promptS ){ adjptr = get_edge_from_user( obj, direction ) ; adjptr->marked = TRUE ; return( adjptr ) ; } else { /* ******************************************************** * Avoid asking user - use ordering information given by * the user. Take first unexecuted edge as next edge to be * executed. *********************************************************** */ if( direction == FORWARD ){ adjptr = obj->adjF ; } else { adjptr = obj->adjB ; } for( ; adjptr ; adjptr = adjptr->next ){ if( !(adjptr->marked) ){ adjptr->marked = TRUE ; return( adjptr ) ; } } /* if we didn't find any unmarked nodes we need to ask user */ adjptr = get_edge_from_user( obj, direction ) ; return( adjptr ) ; } } /* end make decision */ graywolf-0.1.4+20170307gite1bf319/src/twflow/io.c000066400000000000000000000317151305746555600206570ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: io.c DESCRIPTION:This file contains routines for handling I/O. The routines in this file build the graph. CONTENTS: init( numobj ) INT numobj ; add_object( pname, node ) char *pname ; INT node ; add_pdependency( fromNode ) INT fromNode ; add_path( pathname ) char *pathname ; set_file_type( type ) BOOL type ; add_fdependency( file ) char *file ; add_args( argument ) char *argument ; add_box( l, b, r, t ) INT l, b, r, t ; start_edge( fromNode ) INT fromNode ; add_line( x1, y1, x2, y2 ) INT x1, y1, x2, y2 ; ADJPTR findEdge( from, to, direction ) INT from, to ; BOOL direction ; process_arcs() unmark_edges() set_window() DATE: May 7, 1989 REVISIONS: Jun 19, 1989 - added unmark_edges to insure auto_flow is initialized correctly. Made list of nodes in same order as user gave so that program will be executed FIFO. Sun Apr 21 22:35:40 EDT 1991 - now allow optional files. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) io.c version 2.2 4/21/91" ; #endif #include #include #include #include #define START "start" #define OPTIONAL '*' typedef struct ebox { INT from ; /* from node for edge */ INT to ; /* to node for edge */ char **argv ; /* argument vector */ INT argc ; /* argument count */ FPTR ifiles ; /* list of files */ FPTR ofiles ; /* list of files */ DPTR dlist ; /* list of drawables */ struct ebox *next ; /* list of drawables */ } EDGEBOX, *EDGEPTR ; static INT curObjS ; /* counts the current object */ static INT boxLS, boxRS, boxTS, boxBS ; /* bounding box of objects */ static BOOL errorFlagS = FALSE ; /* records fault condition */ static BOOL inputNotOutputS ; /* the current filetype */ static OBJECTPTR objS ; /* pointer to current obj */ static ADJPTR botEdgeS ; /* the current pointer */ static EDGEPTR edgeListS = NULL ; /* list of drawable edges */ /* ***************** ERROR HANDLING ****************************** */ /* ERRORABORT is a macro which forces routines not to do any work */ /* when we find a syntax error in the input routine. */ #define ERRORABORT() \ { \ if( errorFlagS ){ \ return ; /* don't do any work for errors */ \ } \ } \ setErrorFlag() { errorFlagS = TRUE ; } /* ***************** ERROR HANDLING ****************************** */ init( numobj ) INT numobj ; { INT i ; OBJECTPTR o ; /* save number of objects in global for future use */ numobjectsG = numobj ; numobj++ ; /* add 1 to cover 0 node */ /* initialize bounding box of objects to find area for draw */ boxLS = INT_MAX ; boxBS = INT_MAX ; boxRS = INT_MIN ; boxTS = INT_MIN ; /* allocate space for graph */ proGraphG = (OBJECTPTR *) Ysafe_malloc( (numobj + 1) * sizeof(OBJECTPTR) ); for( i = 0 ; i <= numobj ; i++ ){ o = proGraphG[i] = (OBJECTPTR) Ysafe_malloc( sizeof(OBJECTBOX) ); o->node = i ; o->adjF = NULL ; o->adjB = NULL ; o->numedges = 0 ; } curObjS = -1 ; /* initialize object counter */ add_object( START, 0 ) ; } /* end init */ /* create a new object */ add_object( pname, node ) char *pname ; INT node ; { ERRORABORT() ; if( ++curObjS != node || node > numobjectsG ){ setErrorFlag() ; M(ERRMSG, "add_object", "Problem with cell number\n" ) ; return ; } objS = proGraphG[curObjS] ; objS->node = node ; objS->name = pname ; } /* end add_object */ add_pdependency( fromNode ) INT fromNode ; { OBJECTPTR from, to ; ADJPTR temp, newE ; /* edge temporary pointers */ ERRORABORT() ; if( fromNode < 0 || fromNode > numobjectsG ){ M( ERRMSG, "add_pdependency", "Node out of bounds\n" ) ; setErrorFlag() ; return ; } from = proGraphG[fromNode] ; to = objS ; /* create backward edge since we are given edges in dependency form */ if( temp = to->adjB ){ /* add at end of the list */ for( ; temp->next ; temp = temp->next ) ; newE = temp->next = (ADJPTR) Ysafe_malloc(sizeof(ADJBOX)) ; } else { /* start adjacency list */ newE = to->adjB = (ADJPTR) Ysafe_malloc(sizeof(ADJBOX)) ; } newE->next = NULL ; newE->node = fromNode ; newE->ifiles = NULL ; newE->ofiles = NULL ; newE->marked = FALSE ; /* now create forward edge */ if( temp = from->adjF ){ /* add at end of the list */ for( ; temp->next ; temp = temp->next ) ; newE = temp->next = (ADJPTR) Ysafe_malloc(sizeof(ADJBOX)) ; } else { /* start adjacency list */ newE = from->adjF = (ADJPTR) Ysafe_malloc(sizeof(ADJBOX)) ; } newE->next = NULL ; newE->node = objS->node ; newE->ifiles = NULL ; newE->ofiles = NULL ; newE->marked = FALSE ; } /* end add_pdependency */ add_path( pathname ) char *pathname ; { ERRORABORT() ; objS->path = pathname ; } /* end add_path */ /* set file type */ set_file_type( type ) BOOL type ; { inputNotOutputS = type ; } /* end set_file_type */ add_fdependency( file ) char *file ; { INT len ; FPTR temp, newF ; ERRORABORT() ; if( inputNotOutputS ){ /* now create list of files program depends on */ if( temp = edgeListS->ifiles ){ newF = edgeListS->ifiles = (FPTR) Ysafe_malloc(sizeof(FBOX)) ; /* hook to rest of list */ newF->next = temp ; } else { /* start adjacency list */ newF = edgeListS->ifiles = (FPTR) Ysafe_malloc(sizeof(FBOX)) ; newF->next = NULL ; } } else { /* now create list of files program depends on */ if( temp = edgeListS->ofiles ){ newF = edgeListS->ofiles = (FPTR) Ysafe_malloc(sizeof(FBOX)) ; /* hook to rest of list */ newF->next = temp ; } else { /* start adjacency list */ newF = edgeListS->ofiles = (FPTR) Ysafe_malloc(sizeof(FBOX)) ; newF->next = NULL ; } } newF->optional = FALSE ; len = strlen( file ) - 1 ; if( len >= 0 ){ if( file[len] == OPTIONAL ){ /* remove the OPTIONAL character */ newF->optional = TRUE ; file[len] = EOS ; } } newF->fname = file ; } /* end add_fdependency */ add_args( argument ) char *argument ; { ERRORABORT() ; ASSERT( edgeListS->argc < MAXARGS, "add_args", "Max num of args exceeded\n"); edgeListS->argv[edgeListS->argc++] = argument ; } /* end add_args */ add_box( l, b, r, t ) INT l, b, r, t ; { ERRORABORT() ; /* save bounding box of all tiles */ boxLS = MIN( l, boxLS ) ; boxBS = MIN( b, boxBS ) ; boxRS = MAX( r, boxRS ) ; boxTS = MAX( t, boxTS ) ; objS->l = l ; objS->r = r ; objS->b = b ; objS->t = t ; } /* end add_box */ /* - - - - - - - - - - - -- - - - - - - - - - - - - -- - - - - - - - Need to store drawn lines temporarily because graph has not been completed at this point. We could force user to topologically sort data but we want to make it easy for the user. It's not much trouble anyway. - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - */ start_edge( fromNode ) INT fromNode ; { EDGEPTR temp ; ERRORABORT() ; if( fromNode < 0 || fromNode > numobjectsG ){ M( ERRMSG, "start_edge", "Node out of bounds\n" ) ; setErrorFlag() ; return ; } if( temp = edgeListS ){ edgeListS = (EDGEPTR) Ysafe_malloc(sizeof(EDGEBOX)) ; /* hook to rest of list */ edgeListS->next = temp ; } else { /* start adjacency list */ edgeListS = (EDGEPTR) Ysafe_malloc(sizeof(EDGEBOX)) ; edgeListS->next = NULL ; } edgeListS->from = fromNode ; edgeListS->to = objS->node ; edgeListS->dlist = NULL ; edgeListS->ifiles = NULL ; edgeListS->ofiles = NULL ; edgeListS->argv = (char **) Ysafe_malloc( MAXARGS * sizeof(char *) ) ; edgeListS->argc = 0 ; /* update edge count for from node */ proGraphG[fromNode]->numedges++ ; } /* end start_edge */ add_line( x1, y1, x2, y2 ) INT x1, y1, x2, y2 ; { DPTR temp, dptr ; ERRORABORT() ; if( temp = edgeListS->dlist ){ dptr = edgeListS->dlist = (DPTR) Ysafe_malloc(sizeof(DBOX)) ; /* hook to rest of list */ dptr->next = temp ; } else { /* start a new draw list */ dptr = edgeListS->dlist = (DPTR) Ysafe_malloc(sizeof(DBOX)) ; dptr->next = NULL ; } dptr->x1 = x1 ; dptr->y1 = y1 ; dptr->x2 = x2 ; dptr->y2 = y2 ; boxLS = MIN( x1, boxLS ) ; boxBS = MIN( y1, boxBS ) ; boxRS = MAX( x2, boxRS ) ; boxTS = MAX( y2, boxTS ) ; } /* end add_line */ ADJPTR findEdge( from, to, direction ) INT from, to ; BOOL direction ; { ADJPTR adjptr ; ASSERT( from >= 0 && from <= numobjectsG,"findEdge", "Node out of bounds\n" ) ; if( direction == FORWARD ){ adjptr = proGraphG[from]->adjF; } else { adjptr = proGraphG[from]->adjB; } for( ; adjptr; adjptr = adjptr->next ){ if( adjptr->node == to ){ return( adjptr ) ; } } return( NULL ) ; } /* end findEdge */ /* process lines */ /* Now add the drawn lines to the graph data structure */ process_arcs() { ADJPTR adjptr ; EDGEPTR edge ; if( errorFlagS ){ M( ERRMSG, NULL, "Problem reading flow file. Aborting...\n\n" ) ; YexitPgm( PGMFAIL ) ; } /* cross reference edge to correct place */ for( edge = edgeListS; edge; edge=edge->next ){ /* find forward edge */ adjptr = findEdge( edge->from, edge->to, FORWARD ) ; if( !(adjptr) ){ sprintf( YmsgG, "Inconsistently defined edge %d -> %d \n", edge->from, edge->to ) ; M( ERRMSG, "process_arcs", YmsgG ) ; setErrorFlag() ; continue ; } adjptr->geometry = edge->dlist ; adjptr->ifiles = edge->ifiles ; adjptr->ofiles = edge->ofiles ; adjptr->argv = edge->argv ; adjptr->argc = edge->argc ; /* find backward edge */ adjptr = findEdge( edge->to, edge->from, BACKWARD ) ; if( !(adjptr) ){ sprintf( YmsgG, "Inconsistently defined edge %d -> %d \n", edge->to, edge->from ) ; M( ERRMSG, "process_arcs", YmsgG ) ; setErrorFlag() ; continue ; } adjptr->geometry = edge->dlist ; adjptr->ifiles = edge->ifiles ; adjptr->ofiles = edge->ofiles ; adjptr->argv = edge->argv ; adjptr->argc = edge->argc ; } /* exit if we get error in graph */ if( errorFlagS ){ YexitPgm( PGMFAIL ) ; } /* now free edgeList */ for( ; edgeListS; ){ edge = edgeListS ; edgeListS = edgeListS->next ; Ysafe_free( edge ) ; } G( set_window() ) ; } /* end process_arcs */ /* clean edges so everything must be checked */ unmark_edges() { INT i ; /* counter */ OBJECTPTR o ; /* object pointer */ ADJPTR adjptr ; /* pointer to edge */ for( i = 0 ; i <= numobjectsG ; i++ ){ o = proGraphG[i] ; for( adjptr = o->adjF; adjptr ; adjptr = adjptr->next ){ adjptr->marked = FALSE ; } for( adjptr = o->adjB; adjptr ; adjptr = adjptr->next ){ adjptr->marked = FALSE ; } } } /* end unmark_edges */ #ifndef NOGRAPHICS #include set_window() { INT xpand ; /* make output look nice */ INT min, max ; /* make into square */ /* also set the drawing window */ /* take min max to make window centered */ min = MIN( boxLS, boxBS ) ; max = MAX( boxRS, boxTS ) ; xpand = ( max - min ) / 10 ; min -= xpand ; max += xpand ; TWsetwindow( min , min, max, max ) ; } /* end set_window */ #endif /* NOGRAPHICS */ graywolf-0.1.4+20170307gite1bf319/src/twflow/main.c000066400000000000000000000226511305746555600211730ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * Copyright (C) 2014 Ruben Undheim * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: main.c DESCRIPTION:This file contains main control routine for Master program. CONTENTS: main( argc , argv ) INT argc ; char *argv[] ; syntax() DATE: May 5, 1989 REVISIONS: Jun 19, 1989 - added stdcell.fnog for no graphics case. Nov 2, 1989 - changed search path for files and added a -m macro switch. Aug 1, 1990 - rewrote to be MOTIF compatible. Nov 23, 1990 - now exit status is correct if a program experiences trouble. Fri Feb 22 23:54:19 EST 1991 - added lock feature for PSC. Sat Feb 23 04:52:56 EST 1991 - added parasite and tomus switches. Thu Mar 7 01:35:22 EST 1991 - now windowID is a global and twflow can inherit a window itself. Tue Apr 2 23:10:06 EST 1991 - fixed argument problem with Yfile_create_lock. Thu Apr 18 01:20:52 EDT 1991 - now user can specify a flow directory. Also added show_flows call. Sun Apr 21 22:36:29 EDT 1991 - now find the flow directory. ---------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) main.c version 2.8 4/21/91" ; #endif #include #include #include #include #include #include #include #include #define GLOBAL_DEFS #include #include "config-build.h" #define EXPECTEDMEMORY (256 * 1024) /* 256k is more than enough */ #define NULLWINDOW 0 #define VERSION "2.1" main( argc , argv ) INT argc ; char *argv[] ; { char filename[LRECL] ; /* buffer for filename */ char *ptr ; /* argument pointer */ char *Ygetenv() ; /* get environment variable */ FILE *fp ; /* file pointer */ FILE *find_flow_file() ; /* return pointer to flow file */ BOOL debug ; /* TRUE if debug on */ BOOL general_mode ; /* TRUE if top level user flow */ BOOL lock ; /* whether to create a lock file */ BOOL verbose ; /* whether to go into verbose mode.*/ BOOL parasite ; /* TRUE if we are to take over win */ INT arg_count ; /* parse the command line */ INT windowId ; /* the parasite window id */ VOID yaleIntro() ; /* give intro for program */ /* start up cleanup handler */ YINITCLEANUP( argv[0], NULL, MAYBEDUMP ) ; Yinit_memsize( EXPECTEDMEMORY ) ; flow_dirG = NIL(char *) ; /* make sure we have environment variable */ if(!(twdirG = TWFLOWDIR)) { M(ERRMSG,"twflow","Can't get environment variable 'TWDIR'\n") ; M(MSG,NULL, "Please use setenv to set 'TWDIR' to TimberWolf directory\n" ) ; YexitPgm(MASTERFAIL); } if( argc < 2 || argc > 5 ){ syntax() ; } else { #ifndef NOGRAPHICS graphicsG = TRUE ; #else graphicsG = FALSE ; #endif /* NOGRAPHICS */ windowId = NULLWINDOW ; /* initialize window to NULL */ debug = FALSE ; lock = FALSE ; tomusG = FALSE ; parasite = FALSE ; autoflowG = TRUE ; general_mode = FALSE ; verbose = FALSE ; arg_count = 1 ; if( *argv[1] == '-' ){ for( ptr = ++argv[1]; *ptr; ptr++ ){ switch( *ptr ){ case 'd': debug = TRUE ; break ; case 'g': general_mode = TRUE ; break ; case 'l': lock = TRUE ; break ; case 'n': graphicsG = FALSE ; break ; case 'p': autoflowG = FALSE ; break ; case 't': tomusG = TRUE ; break ; case 'v': verbose = TRUE ; break ; case 'w': parasite = TRUE ; break ; default: sprintf( YmsgG,"Unknown option:%c\n", *ptr ) ; M(ERRMSG,"main",YmsgG); syntax() ; } } YdebugMemory( debug ) ; YinitProgram( MASTER, VERSION, yaleIntro ); cktNameG = Ystrclone( argv[++arg_count] ); Ymessage_mode( verbose ) ; /* now tell the user what he picked */ M(MSG,NULL,"Twflow switches:\n" ) ; if( debug ){ YsetDebug( TRUE ) ; M(MSG,NULL,"\tdebug on\n" ) ; } if( graphicsG ){ M(MSG,NULL,"\tGraphics mode on\n" ) ; } else { M(MSG,NULL,"\tGraphics mode off\n" ) ; } if( parasite ){ M(MSG,NULL,"\tTwflow will inherit window\n" ) ; /* look for windowid */ if(argc != 4){ M(ERRMSG,"main","Need to specify windowID\n" ) ; syntax() ; } else { G( windowId = atoi( argv[++arg_count] ) ) ; } } if( general_mode ){ M(MSG,NULL,"\tGeneral mode on\n" ) ; } else if( tomusG ){ M(MSG,NULL,"\tTomus partition mode on\n" ) ; } else { M(MSG,NULL,"\tTimberWolf mode on\n" ) ; } M(MSG,NULL,"\n" ) ; } else if( argc <= 3 ){ /* order is important here */ YdebugMemory( FALSE ) ; cktNameG = Ystrclone( argv[arg_count] ); YinitProgram( MASTER, VERSION, yaleIntro ); } else { syntax() ; } if( ++arg_count < argc ){ /* this means we have the flow directory specified */ flow_dirG = Ystrclone( argv[arg_count] ) ; sprintf( YmsgG, "\n\tFlow directory given:%s\n\n", flow_dirG ); M( MSG,NULL, YmsgG ) ; } } /* initialize the graphics */ G( init_graphics(argc,argv,windowId) ) ; Ylog_start( cktNameG, "Program initialization completed..." ) ; if( lock ){ /* create a lock file to say we are busy */ sprintf( filename, "/tmp/twsc.%s", cktNameG ) ; (VOID) Yfile_create_lock( filename, FALSE ) ; } Ymessage_flush() ; /* ------------------ end initialization ------------------------- */ /* determine the correct flow file */ /* return file and filename */ fp = find_flow_file( general_mode, debug, filename ) ; /* now we can read this file */ readobjects( fp, filename ) ; /* If we haven't been given a flow directory override, find */ /* the flow directory. */ if(!(flow_dirG)){ sprintf( filename, "%s/bin/flow/flow", twdirG ) ; if( flow_dirG = Yfile_slink( filename )){ flow_dirG = Ystrclone( flow_dirG ) ; } else { G( TWcloseGraphics() ) ; YexitPgm(PGMFAIL); } } /* let user user see data */ G( draw_the_data() ) ; /* verify_pathnames() ; */ if( !graphicsG || autoflowG ){ /* if no graphics must go auto_flow */ autoflowG = TRUE ; auto_flow() ; } else { G( process_graphics() ) ; } G( TWcloseGraphics() ) ; if( problemsG ){ YexitPgm(PGMFAIL); } else { YexitPgm(PGMOK); } } /* end main */ /* give user correct syntax */ syntax() { M(ERRMSG,NULL,"\n" ) ; M(MSG,NULL,"Incorrect syntax. Correct syntax:\n"); sprintf( YmsgG, "\ngraywolf [-gpndw] designName [windowId] [flowdirectory]\n" ); M(MSG,NULL,YmsgG ) ; M(MSG,NULL,"\twhose options are one or more of the following:\n"); M(MSG,NULL,"\t\tg - general mode - does not use TimberWolf system\n"); M(MSG,NULL,"\t\t information. Default is TimberWolf mode\n"); M(MSG,NULL,"\t\tp - pick mode - [graphics only] wait for user\n"); M(MSG,NULL,"\t\t upon entering the program\n"); M(MSG,NULL,"\t\tn - no graphics - the default is to open the\n"); M(MSG,NULL,"\t\t display and output graphics to an Xwindow\n"); M(MSG,NULL,"\t\td - prints debug info and performs extensive\n"); M(MSG,NULL,"\t\t error checking\n"); M(MSG,NULL,"\t\tw - parasite mode will inherit a window. Requires\n"); M(MSG,NULL,"\t\t a valid windowId\n"); show_flows() ; YexitPgm(MASTERFAIL); } /* end syntax */ VOID yaleIntro() { char message[LRECL] ; sprintf( message,"\n%s\n",YmsgG) ; M(MSG,NULL,message) ; M(MSG,NULL,"Authors: Bill Swartz, Carl Sechen\n"); M(MSG,NULL," Yale University\n"); } /* end yaleIntro */ show_flows() { char command[LRECL] ; /* now show user the flow directories */ sprintf( command, "%s/bin/show_flows", twdirG ) ; Ysystem( "show_flows", ABORT, command, NULL ) ; } /* end show_flows */ graywolf-0.1.4+20170307gite1bf319/src/twflow/menus.h000066400000000000000000000020531305746555600213750ustar00rootroot00000000000000 /* TWmenu definitions */ #define TWNUMMENUS 19 #define AUTO_REDRAW_ON 1 #define AUTO_REDRAW_OFF 2 #define CLOSE_GRAPHICS 3 #define COLORS 4 #define CONTINUE_PGM 5 #define DUMP_GRAPHICS 6 #define EXIT_PROGRAM 7 #define FULLVIEW 8 #define REDRAW 9 #define TELL_POINT 10 #define TRANSLATE 11 #define ZOOM 12 #define CANCEL 0 #define AUTOFLOW 13 #define EXECUTE_PGM 14 #define PICK_PGM 15 #define PROMPT_ON 16 #define PROMPT_OFF 17 #define CANCEL 0 static TWMENUBOX menuS[20] = { "CONTROL",0,0,1,0,0, "Auto Redraw On","Auto Redraw Off",1,0,1,2, "Close Graphics",0,0,0,3,0, "Colors",0,0,0,4,0, "Continue Pgm",0,0,0,5,0, "Dump Graphics",0,0,0,6,0, "Exit Program",0,0,0,7,0, "FullView",0,0,0,8,0, "Redraw",0,0,0,9,0, "Tell Point",0,0,0,10,0, "Translate",0,0,0,11,0, "Zoom",0,0,0,12,0, "Cancel",0,0,0,0,0, "FLOW ",0,0,1,0,0, "AutoFlow",0,0,0,13,0, "Execute Pgm",0,0,0,14,0, "Pick Pgm",0,0,0,15,0, "Prompt On","Prompt Off",0,0,16,17, "Cancel",0,0,0,0,0, 0,0,0,0,0,0 } ; graywolf-0.1.4+20170307gite1bf319/src/twflow/program.c000066400000000000000000000113431305746555600217120ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: program.c DESCRIPTION:This file contains routines for executing and logging the execution times of the program. CONTENTS: BOOL executePgm( adjptr ) ADJPTR adjptr ; set_path0( pathname ) char *pathname ; DATE: May 7, 1989 - original coding. REVISIONS: Jun 19, 1989 - shortened designName to $ for substitution. Thu Mar 7 01:35:22 EST 1991 - now windowID is a global and twflow can inherit a window itself. Sun Apr 21 22:37:20 EDT 1991 - changed windowId to @WINDOWID and added @FLOWDIR. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) program.c version 2.3 4/21/91" ; #endif #include #include #include #include #include #include #include #define DESIGNNAME "$" #define DSNLEN 1 #define WINDOWID "@WINDOWID" #define FLOWDIR "@FLOWDIR" BOOL executePgm( adjptr ) ADJPTR adjptr ; { char *Yfixpath() ; /* get full pathname */ char command[LRECL] ; char window_name[LRECL] ; /* the window name */ OBJECTPTR obj ; /* current object */ INT i ; /* arg counter */ INT status ; /* program return status */ char **argv ; /* argument vector */ BOOL stateSaved ; /* whether graphics state was saved*/ obj = proGraphG[adjptr->node] ; sprintf( YmsgG, "Executing %s", obj->name) ; G( TWmessage( YmsgG ) ) ; /* build command to be executed */ command[0] = EOS ; /* clear character string */ stateSaved = FALSE ; /* for remember whether we save graphics */ /* first the program name */ if( obj->path ){ /* take users pathname */ sprintf( command, "%s", Yfixpath( obj->path,TRUE ) ) ; } else { /* otherwise take default TimberWolf directory */ sprintf( command, "%s/bin/%s", twdirG, obj->name ) ; } argv = adjptr->argv ; for( i = 0 ; i < adjptr->argc; i++ ){ strcat( command, " " ) ; if( strncmp( argv[i], DESIGNNAME, DSNLEN ) == STRINGEQ ){ /* +1 skips over $ to see if other is present */ strcat( command, cktNameG ) ; strcat( command, argv[i]+1 ) ; } else if( strcmp( argv[i], WINDOWID ) == STRINGEQ ){ /* save state of graphics before call if necessary */ if( graphicsG ){ G( sprintf( window_name, "%d", TWsaveState() ) ) ; stateSaved = TRUE ; } strcat( command, window_name ) ; } else if( strcmp( argv[i], FLOWDIR ) == STRINGEQ ){ /* add flow directory */ strcat( command, flow_dirG ) ; } else { strcat( command, argv[i] ) ; } } D( "twflow/executePgm", sprintf( YmsgG, "%s\n", command ) ) ; D( "twflow/executePgm", M( MSG, NULL, YmsgG ) ) ; /* now log the beginning time */ sprintf( YmsgG, "%s started...", obj->name ) ; Ylog_msg( YmsgG ) ; /* now execute the command */ status = system( command ) ; sprintf( YmsgG, "%s completed...", obj->name ) ; Ylog_msg( YmsgG ) ; if( stateSaved ){ /* if we save the graphics state we need to restore it */ G( TWrestoreState() ) ; } return( status ) ; } /* end execute Pgm */ graywolf-0.1.4+20170307gite1bf319/src/twflow/readobjects.c000066400000000000000000000536621305746555600225420ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley) 01/20/90"; #endif #define YYBYACC 1 /* ----------------------------------------------------------------- FILE: readobjects.c <- readobjects.y <- readobjects.l DESCRIPTION:This file contains the grammar (BNF) for reading the positions of the objects from placement routine. The rules for lex are in readobjects.l. The grammar for yacc is in readobjects.y. The output of yacc (y.tab.c) is renamed to readobjects.c CONTENTS: readobjects() yyerror(s) char *s; yywrap() Note:readobjects.c will also include the yacc parser. DATE: Apr 7, 1988 REVISIONS: Apr 20, 1989 - original coding. Apr 30, 1989 - added library change and added partition case for compaction. May 3, 1989 - changed to Y prefixes. Jun 19, 1989 - now handle multiple edges correctly. Sun Jan 20 21:31:36 PST 1991 - ported to AIX. Thu Apr 18 01:22:43 EDT 1991 - added debug switch and made output prettier for syntax errors. Sun Apr 21 22:38:38 EDT 1991 - added missing close file. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) readobjects.y version 2.5 4/21/91" ; #endif #include #include #include /* use message routines for errors. */ #include /* file opening insert file. */ #include /* use debug utilities. */ #include #undef REJECT /* undefine TWMC macro for lex's version */ #ifdef DEBUG #define YYDEBUG 1 /* condition compile for yacc debug */ #endif static INT line_countS ; static char bufferS[LRECL] ; static char *filenameS ; typedef union { INT ival ; char *string ; double fval ; } YYSTYPE; #define INTEGER 257 #define STRING 258 #define FLOAT 259 #define ARGS 260 #define COLON 261 #define DRAWN 262 #define EDGE 263 #define FULL 264 #define IFILES 265 #define NUMOBJECTS 266 #define OFILES 267 #define PATH 268 #define POBJECT 269 #define RELATIVE 270 #define YYERRCODE 256 short yylhs[] = { -1, 0, 2, 3, 3, 4, 8, 8, 9, 9, 5, 15, 16, 16, 6, 6, 11, 11, 12, 12, 17, 19, 18, 18, 13, 20, 20, 7, 10, 14, 21, 21, 22, 1, 1, 1, }; short yylen[] = { 2, 2, 2, 1, 2, 4, 1, 2, 4, 5, 3, 3, 1, 2, 3, 2, 1, 2, 1, 2, 2, 2, 1, 2, 3, 1, 2, 6, 3, 3, 1, 2, 4, 1, 1, 1, }; short yydefred[] = { 0, 0, 0, 0, 2, 0, 0, 3, 0, 0, 34, 33, 35, 0, 4, 0, 0, 0, 11, 0, 0, 0, 12, 0, 14, 0, 0, 0, 6, 0, 13, 0, 0, 7, 0, 0, 0, 0, 28, 20, 0, 0, 0, 22, 0, 0, 21, 0, 0, 0, 23, 27, 0, 0, 9, 25, 0, 0, 26, 0, 0, 30, 0, 31, 0, 32, }; short yydgoto[] = { 2, 43, 3, 6, 7, 8, 16, 21, 27, 28, 29, 35, 41, 48, 54, 9, 23, 36, 44, 42, 56, 60, 61, }; short yysindex[] = { -258, -248, 0, -259, 0, -252, -259, 0, -257, -249, 0, 0, 0, -244, 0, -246, -245, -241, 0, -252, -243, -242, 0, -238, 0, -237, -235, -242, 0, -240, 0, -234, -233, 0, -232, -236, -252, -231, 0, 0, -229, -230, -252, 0, -252, -224, 0, -227, -226, -252, 0, 0, -252, -223, 0, 0, -252, -222, 0, -220, -222, 0, -217, 0, -216, 0, }; short yyrindex[] = { 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -219, 0, 0, 0, -218, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, -225, 0, 0, 0, 0, 0, -215, 0, -221, 0, 0, 0, 2, -212, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, }; short yygindex[] = { 0, -5, 0, 0, 21, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, -7, }; #define YYTABLESIZE 273 short yytable[] = { 13, 24, 8, 29, 5, 10, 11, 12, 1, 4, 5, 15, 17, 18, 24, 19, 22, 20, 25, 30, 31, 26, 32, 37, 1, 34, 45, 14, 38, 39, 47, 40, 46, 51, 52, 59, 53, 62, 57, 50, 64, 65, 16, 15, 50, 18, 17, 55, 19, 33, 10, 58, 49, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 8, 29, 0, 0, 0, 24, 8, 29, 5, }; short yycheck[] = { 5, 0, 0, 0, 0, 257, 258, 259, 266, 257, 269, 268, 261, 257, 19, 261, 257, 262, 261, 257, 257, 263, 257, 257, 0, 265, 257, 6, 261, 261, 260, 267, 261, 257, 261, 257, 262, 257, 261, 44, 257, 257, 267, 262, 49, 260, 267, 52, 260, 27, 268, 56, 42, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 262, 263, 263, 263, -1, -1, -1, 269, 269, 269, 269, }; #define YYFINAL 2 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 270 #if YYDEBUG char *yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"INTEGER","STRING","FLOAT","ARGS", "COLON","DRAWN","EDGE","FULL","IFILES","NUMOBJECTS","OFILES","PATH","POBJECT", "RELATIVE", }; char *yyrule[] = { "$accept : start_file", "start_file : numobjects object_list", "numobjects : NUMOBJECTS INTEGER", "object_list : object", "object_list : object_list object", "object : name path draw_obj list_of_edges", "list_of_edges : edge", "list_of_edges : list_of_edges edge", "edge : edge_keyword ifiles ofiles args", "edge : edge_keyword ifiles ofiles args draw_edges", "name : pname COLON depend_list", "pname : POBJECT string INTEGER", "depend_list : INTEGER", "depend_list : depend_list INTEGER", "path : PATH COLON string", "path : PATH COLON", "ifiles : ifiletype", "ifiles : ifiletype list_of_files", "ofiles : ofiletype", "ofiles : ofiletype list_of_files", "ifiletype : IFILES COLON", "ofiletype : OFILES COLON", "list_of_files : string", "list_of_files : list_of_files string", "args : ARGS COLON list_of_args", "list_of_args : string", "list_of_args : list_of_args string", "draw_obj : DRAWN COLON INTEGER INTEGER INTEGER INTEGER", "edge_keyword : EDGE INTEGER COLON", "draw_edges : DRAWN COLON list_of_lines", "list_of_lines : line", "list_of_lines : list_of_lines line", "line : INTEGER INTEGER INTEGER INTEGER", "string : STRING", "string : INTEGER", "string : FLOAT", }; #endif #define yyclearin (yychar=(-1)) #define yyerrok (yyerrflag=0) #ifdef YYSTACKSIZE #ifndef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #endif #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 500 #define YYMAXDEPTH 500 #endif #endif int yycnprs = 0; int yydebug; int yynerrs; int yyerrflag; int yychar; short *yyssp; YYSTYPE *yyvsp; YYSTYPE yyval; YYSTYPE yylval; short yyss[YYSTACKSIZE]; YYSTYPE yyvs[YYSTACKSIZE]; #define yystacksize YYSTACKSIZE #include "readobjects_l.h" /* add readobjects.h for debug purposes */ /* ********************* #include "readobjects_l.h" *******************/ /* ********************* #include "readobjects_l.h" *******************/ readobjects( fp, filename ) FILE *fp ; char *filename ; { #ifdef YYDEBUG extern int yydebug ; yydebug = FALSE ; D( "twflow/readobjects", yydebug = TRUE ; ) ; #endif yyin = fp ; line_countS = 0 ; filenameS = filename ; /* parse input file using yacc */ yyparse(); TWCLOSE( fp ) ; process_arcs() ; } /* end readobjects */ yyerror(s) char *s; { sprintf(YmsgG,"problem reading:%s\n", filenameS ); M( ERRMSG, "yacc", YmsgG ) ; sprintf(YmsgG, " line %d near '%s' : %s\n\n" , line_countS+1, yytext, s ); M( MSG,NULL, YmsgG ) ; setErrorFlag() ; } yywrap() { return(1); } #define YYABORT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int yyparse() { register int yym, yyn, yystate; #if YYDEBUG register char *yys; extern char *getenv(); if (yys = getenv("YYDEBUG")) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = (-1); yyssp = yyss; yyvsp = yyvs; *yyssp = yystate = 0; yyloop: if (yyn = yydefred[yystate]) goto yyreduce; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, shifting to state %d\n", yystate, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; #ifdef lint goto yynewerror; #endif yynewerror: #if YYDEBUG { int test_state, i, expect, two_or_more ; char err_msg[BUFSIZ] ; if( yyname[yychar] ){ sprintf( err_msg, "Found %s.\nExpected ", yyname[yychar] ) ; two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } yyerror( err_msg ) ; if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } } else { sprintf( err_msg, "Found unknown token.\nExpected "); two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } yyerror( err_msg ) ; if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } } } #else yyerror("syntax error"); if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } #endif #ifdef lint goto yyerrlab; #endif yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, error recovery shifting\ to state %d\n", *yyssp, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("yydebug: error recovery discarding state %d\n", *yyssp); #endif if (yyssp <= yyss) goto yyabort; --yyssp; --yyvsp; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, error recovery discards token %d (%s)\n", yystate, yychar, yys); } #endif yychar = (-1); goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("yydebug: state %d, reducing by rule %d (%s)\n", yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; yyval = yyvsp[1-yym]; switch (yyn) { case 2: { init( yyvsp[0].ival ) ; } break; case 11: { add_object( yyvsp[-1].string, yyvsp[0].ival ) ; } break; case 12: { add_pdependency( yyvsp[0].ival ) ; } break; case 13: { add_pdependency( yyvsp[0].ival ) ; } break; case 14: { /* replace path is TRUE */ add_path( yyvsp[0].string ) ; } break; case 15: { add_path( NULL ) ; } break; case 20: { set_file_type( INPUTFILE ) ; } break; case 21: { set_file_type( OUTPUTFILE ) ; } break; case 22: { add_fdependency( yyvsp[0].string ) ; } break; case 23: { add_fdependency( yyvsp[0].string ) ; } break; case 25: { add_args( yyvsp[0].string ) ; } break; case 26: { add_args( yyvsp[0].string ) ; } break; case 27: { add_box( yyvsp[-3].ival, yyvsp[-2].ival, yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 28: { start_edge( yyvsp[-1].ival ) ; } break; case 32: { add_line( yyvsp[-3].ival, yyvsp[-2].ival, yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 33: { yyval.string = yyvsp[0].string ; } break; case 34: { /* convert integer to string */ /* this allows integers to be used as strings */ /* a kluge but twolf's old parser supported it */ sprintf( bufferS,"%d", yyvsp[0].ival ) ; /* now clone string */ yyval.string = (char *) Ystrclone( bufferS ) ; } break; case 35: { /* convert float to string */ /* this allows floats to be used as strings */ /* a kluge but twolf's old parser supported it */ sprintf( bufferS,"%f", yyvsp[0].fval ) ; /* now clone string */ yyval.string = (char *) Ystrclone( bufferS ) ; } break; } yyssp -= yym; yystate = *yyssp; yyvsp -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state 0 to\ state %d\n", YYFINAL); #endif yystate = YYFINAL; *++yyssp = YYFINAL; *++yyvsp = yyval; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state %d \ to state %d\n", *yyssp, yystate); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate; *++yyvsp = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: return (1); yyaccept: return (0); } graywolf-0.1.4+20170307gite1bf319/src/twflow/readobjects_l.h000066400000000000000000000356561305746555600230650ustar00rootroot00000000000000#ifdef linux # include #else # include "stdio.h" #endif # define U(x) ((x)&0377) # define NLSTATE yyprevious=YYNEWLINE # define BEGIN yybgin = yysvec + 1 + # define INITIAL 0 # define YYLERR yysvec # define YYSTATE (yyestate-yysvec-1) # define YYOPTIM 1 # define YYLMAX 200 # define output(c) putc(c,yyout) # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} # define yymore() (yymorfg=1) # define ECHO fprintf(yyout, "%s",yytext) # define REJECT { nstr = yyreject(); goto yyfussy;} int yyleng; extern char yytext[]; int yymorfg; extern char *yysptr, yysbuf[]; int yytchar; #ifdef linux FILE *yyin =NULL, *yyout =NULL; #else FILE *yyin ={stdin}, *yyout ={stdout}; #endif extern int yylineno; struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops;}; struct yysvf *yyestate; extern struct yysvf yysvec[], *yybgin; /* ----------------------------------------------------------------- "@(#) readobjects.l version 2.2 4/18/91" FILE: readobjects.l DESCRIPTION:rules for lexical analyzer in readobjects. This lexical analyzer uses a binary search to reduce the size of the f.a. generated by lex. Thanks to Gary Richey who showed me the trick. See chapter 3 of "Introduction to Compiler Construction with UNIX" by Schreiner & Friedman for more details. CONTENTS: lex rules - screen() DATE: Aug 07, 1988 - need to add SccsId in comments due to yacc REVISIONS: Oct 6, 1988 - fixed sign mistake in INTEGER & FLOAT Feb 12, 1989 - added <> to alphanum to handle DEC case. Apr 4, 1989 - added comments over multiple lines. Thu Apr 18 01:21:47 EDT 1991 - new letter and alphanum definition. ----------------------------------------------------------------- */ #undef YYLMAX #define YYLMAX 2000 /* comments may be at most 2000 characters */ #define token(x) x /* makes it look like regular lex */ #define END(v) (v-1 + sizeof(v) / sizeof( v[0] ) ) /* for table lookup */ static INT screen() ; static INT check_line_count() ; # define YYNEWLINE 10 yylex(){ int nstr; extern int yyprevious; while((nstr = yylook()) >= 0) yyfussy: switch(nstr){ case 0: if(yywrap()) return(0); break; case 1: { /* C-style comments over multiple lines */ check_line_count(yytext) ; } break; case 2: { /* convert to an integer */ yylval.ival = atoi( yytext ) ; return (INTEGER); } break; case 3: { /* convert to an integer */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 4: { /* convert to an integer */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 5: { return( screen() ) ; } break; case 6: { return(COLON); } break; case 7: { line_countS++;} break; case 8: ; break; case 9: { return( token(yytext[0]) ) ;} break; case -1: break; default: fprintf(yyout,"bad switch yylook %d",nstr); } return(0); } /* end of yylex */ /* reserved word screener */ /* ----------------------------------------------------------------- The following is table of the reserved words - Table must be in alphabetical order for binary search to work properly. ----------------------------------------------------------------- */ static struct rw_table { /* reserved word table */ char *rw_name ; /* pattern */ INT rw_yylex ; /* lex token number */ } rwtable[] = { "args", token(ARGS), "drawn", token(DRAWN), "edge", token(EDGE), "full", token(FULL), "ifiles", token(IFILES), "numobjects", token(NUMOBJECTS), "ofiles", token(OFILES), "path", token(PATH), "pobject", token(POBJECT), "relative", token(RELATIVE), } ; static INT screen() { INT c ; struct rw_table *low = rwtable, /* ptr to beginning */ *mid , *high = END(rwtable) ; /* ptr to end */ /* binary search to look thru table to find pattern match */ while( low <= high){ mid = low + (high-low) / 2 ; if( (c = strcmp(mid->rw_name, yytext) ) == STRINGEQ){ return( mid->rw_yylex ) ; /* return token number */ } else if( c < 0 ){ low = mid + 1 ; } else { high = mid - 1 ; } } /* at this point we haven't found a match so we have a string */ /* save the string by making copy */ yylval.string = (char *) Ystrclone( yytext ) ; return (STRING); } /* end screen function */ static INT check_line_count( s ) char *s ; { if( s ){ if( strlen(s) >= YYLMAX ){ sprintf(YmsgG,"comment beginning at line %d ",line_countS+1 ); M( ERRMSG, "lex", YmsgG ) ; sprintf(YmsgG,"exceeds maximum allowed length:%d chars.\n", YYLMAX ); M( MSG, NULL, YmsgG ) ; setErrorFlag() ; } for( ;*s;s++ ){ if( *s == '\n'){ line_countS++; } } } } /* end check_line_count */ int yyvstop[] ={ 0, 8, 0, 8, 0, 9, 0, 8, 9, 0, 7, 0, 5, 9, 0, 5, 9, 0, 5, 9, 0, 2, 9, 0, 6, 9, 0, 8, 0, 5, 0, 5, 0, 2, 5, 0, 5, 0, 3, 5, 0, 2, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 3, 5, 0, 4, 5, 0, 5, 0, 5, 0, 1, 5, 0, 5, 0, 1, 0, 5, 0, 1, 5, 0, 1, 0, 0}; # define YYTYPE unsigned char struct yywork { YYTYPE verify, advance; } yycrank[] ={ 0,0, 0,0, 1,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,4, 1,5, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 1,7, 8,15, 0,0, 1,6, 1,8, 1,9, 20,20, 28,35, 29,36, 34,27, 35,28, 7,13, 36,28, 7,13, 0,0, 1,10, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 1,6, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 0,0, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 9,16, 0,0, 9,17, 9,17, 9,17, 9,17, 9,17, 9,17, 9,17, 9,17, 9,17, 9,17, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 13,13, 0,0, 13,13, 0,0, 9,18, 13,14, 13,14, 13,14, 13,14, 13,14, 13,14, 13,14, 13,14, 13,14, 13,14, 14,16, 0,0, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 0,0, 0,0, 0,0, 0,0, 15,19, 0,0, 0,0, 0,0, 0,0, 9,18, 0,0, 14,18, 15,19, 15,19, 16,23, 0,0, 16,24, 16,24, 16,24, 16,24, 16,24, 16,24, 16,24, 16,24, 16,24, 16,24, 25,25, 25,25, 25,25, 25,25, 25,25, 25,25, 25,25, 25,25, 25,25, 25,25, 15,20, 16,18, 0,0, 0,0, 0,0, 0,0, 0,0, 14,18, 0,0, 15,21, 15,20, 0,0, 0,0, 15,20, 15,22, 15,20, 0,0, 19,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 15,19, 19,26, 19,19, 0,0, 0,0, 19,19, 19,19, 19,19, 16,18, 0,0, 17,16, 15,20, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 19,19, 18,18, 0,0, 18,18, 0,0, 17,18, 18,25, 18,25, 18,25, 18,25, 18,25, 18,25, 18,25, 18,25, 18,25, 18,25, 21,27, 26,27, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 21,27, 21,27, 26,32, 26,27, 0,0, 0,0, 26,27, 26,33, 26,27, 0,0, 0,0, 0,0, 23,23, 17,18, 23,31, 23,31, 23,31, 23,31, 23,31, 23,31, 23,31, 23,31, 23,31, 23,31, 21,28, 0,0, 0,0, 0,0, 0,0, 26,27, 0,0, 0,0, 27,19, 21,29, 21,28, 23,18, 0,0, 21,28, 21,30, 21,28, 0,0, 27,26, 27,19, 0,0, 0,0, 27,19, 27,34, 27,19, 0,0, 21,27, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 21,28, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 23,18, 27,19, 0,0, 0,0, 24,18, 31,31, 31,31, 31,31, 31,31, 31,31, 31,31, 31,31, 31,31, 31,31, 31,31, 32,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 32,26, 32,19, 31,18, 0,0, 32,19, 32,37, 32,19, 0,0, 0,0, 0,0, 0,0, 0,0, 24,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 32,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 31,18, 0,0, 0,0, 0,0}; struct yysvf yysvec[] ={ 0, 0, 0, yycrank+-1, 0, yyvstop+1, yycrank+0, yysvec+1, yyvstop+3, yycrank+0, 0, yyvstop+5, yycrank+3, 0, yyvstop+7, yycrank+0, 0, yyvstop+10, yycrank+38, 0, yyvstop+12, yycrank+12, yysvec+6, yyvstop+15, yycrank+3, yysvec+6, yyvstop+18, yycrank+119, yysvec+6, yyvstop+21, yycrank+0, 0, yyvstop+24, yycrank+0, yysvec+4, yyvstop+27, yycrank+0, yysvec+6, yyvstop+29, yycrank+141, yysvec+6, yyvstop+31, yycrank+153, yysvec+6, yyvstop+33, yycrank+-214, 0, yyvstop+36, yycrank+179, yysvec+6, yyvstop+38, yycrank+236, yysvec+6, yyvstop+41, yycrank+258, yysvec+6, yyvstop+43, yycrank+-231, yysvec+15, 0, yycrank+-3, yysvec+15, yyvstop+45, yycrank+-315, 0, yyvstop+47, yycrank+0, yysvec+15, yyvstop+49, yycrank+290, yysvec+6, yyvstop+51, yycrank+326, yysvec+6, yyvstop+53, yycrank+189, yysvec+6, yyvstop+56, yycrank+-284, yysvec+21, 0, yycrank+-323, yysvec+15, 0, yycrank+-4, yysvec+15, yyvstop+59, yycrank+-5, yysvec+15, yyvstop+61, yycrank+0, yysvec+6, yyvstop+63, yycrank+348, yysvec+6, yyvstop+66, yycrank+-373, yysvec+15, 0, yycrank+0, 0, yyvstop+68, yycrank+6, 0, 0, yycrank+7, yysvec+6, yyvstop+70, yycrank+9, yysvec+6, yyvstop+72, yycrank+0, yysvec+34, yyvstop+75, 0, 0, 0}; struct yywork *yytop = yycrank+449; struct yysvf *yybgin = yysvec+1; char yymatch[] ={ 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 011 ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'*' ,'+' ,'!' ,'+' ,'.' ,'/' , '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , '0' ,'0' ,':' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 0}; char yyextra[] ={ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0}; /* ncform 4.1 83/08/11 */ int yylineno =1; # define YYU(x) x # define NLSTATE yyprevious=YYNEWLINE char yytext[YYLMAX]; struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; char yysbuf[YYLMAX]; char *yysptr = yysbuf; int *yyfnd; extern struct yysvf *yyestate; int yyprevious = YYNEWLINE; yylook(){ register struct yysvf *yystate, **lsp; register struct yywork *yyt; struct yysvf *yyz; int yych; struct yywork *yyr; # ifdef LEXDEBUG int debug; # endif char *yylastch; #ifdef linux if (yyin == NULL) yyin = stdin; if (yyout == NULL) yyout = stdout; #endif /* start off machines */ # ifdef LEXDEBUG debug = 0; # endif if (!yymorfg) yylastch = yytext; else { yymorfg=0; yylastch = yytext+yyleng; } for(;;){ lsp = yylstate; yyestate = yystate = yybgin; if (yyprevious==YYNEWLINE) yystate++; for (;;){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); # endif yyt = yystate->yystoff; if(yyt == yycrank){ /* may not be any transitions */ yyz = yystate->yyother; if(yyz == 0)break; if(yyz->yystoff == yycrank)break; } *yylastch++ = yych = input(); tryagain: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"unsigned char "); allprint(yych); putchar('\n'); } # endif yyr = yyt; if ( (long)yyt > (long)yycrank){ yyt = yyr + yych; if (yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } # ifdef YYOPTIM else if((long)yyt < (long)yycrank) { /* r < yycrank */ yyt = yyr = yycrank+(yycrank-yyt); # ifdef LEXDEBUG if(debug)fprintf(yyout,"compressed state\n"); # endif yyt = yyt + yych; if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } yyt = yyr + YYU(yymatch[yych]); # ifdef LEXDEBUG if(debug){ fprintf(yyout,"try fall back character "); allprint(YYU(yymatch[yych])); putchar('\n'); } # endif if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transition */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); # endif goto tryagain; } # endif else {unput(*--yylastch);break;} contin: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"state %d char ",yystate-yysvec-1); allprint(yych); putchar('\n'); } # endif ; } # ifdef LEXDEBUG if(debug){ fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); allprint(yych); putchar('\n'); } # endif while (lsp-- > yylstate){ *yylastch-- = 0; if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ yyolsp = lsp; if(yyextra[*yyfnd]){ /* must backup */ while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ lsp--; unput(*yylastch--); } } yyprevious = YYU(*yylastch); yylsp = lsp; yyleng = yylastch-yytext+1; yytext[yyleng] = 0; # ifdef LEXDEBUG if(debug){ fprintf(yyout,"\nmatch "); sprint(yytext); fprintf(yyout," action %d\n",*yyfnd); } # endif return(*yyfnd++); } unput(*yylastch); } if (yytext[0] == 0 /* && feof(yyin) */) { yysptr=yysbuf; return(0); } yyprevious = yytext[0] = input(); if (yyprevious>0) output(yyprevious); yylastch=yytext; # ifdef LEXDEBUG if(debug)putchar('\n'); # endif } } yyback(p, m) int *p; { if (p==0) return(0); while (*p) { if (*p++ == m) return(1); } return(0); } /* the following are only used in the lex library */ yyinput(){ #ifdef linux if (yyin == NULL) yyin = stdin; #endif return(input()); } yyoutput(c) int c; { #ifdef linux if (yyout == NULL) yyout = stdout; #endif output(c); } yyunput(c) int c; { unput(c); } graywolf-0.1.4+20170307gite1bf319/src/twmc/000077500000000000000000000000001305746555600175255ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/src/twmc/CMakeLists.txt000066400000000000000000000021061305746555600222640ustar00rootroot00000000000000 add_executable(TimberWolfMC acceptt.c analyze.c compact.c config1.c config2.c configpads.c debug.c finalout.c finalpin.c gmain.c findcheck.c findcost.c findloc.c findside.c fixcell.c genorient.c graphics.c initialize.c initnets.c loadbins.c main.c makebins.c makesite.c mergecell.c neworient.c newtemp.c outgeo.c outpin.c output.c overlap.c paths.c partition.c penalties.c perimeter.c placepads.c placepin.c prboard.c readcells.c readnets.c rmain.c readpar.c reconfig.c savewolf.c scrapnet.c sortpin.c selectpin.c setpwates.c sortpad.c twstats.c uaspect.c uloop.c unbust.c uinst.c unet.c upin.c upinswap.c usite1.c usite2.c usoftmove.c utemp.c watesides.c window.c wirecosts.c wireest.c wireratio.c ${CMAKE_SOURCE_DIR}/src/date/date.c) target_link_libraries(TimberWolfMC ${CMAKE_BINARY_DIR}/src/Ylib/libycadgraywolf.so) target_link_libraries(TimberWolfMC X11) target_link_libraries(TimberWolfMC m) target_link_libraries(TimberWolfMC ${GSL_LIBRARIES}) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include .) install(TARGETS TimberWolfMC DESTINATION lib/graywolf/bin) graywolf-0.1.4+20170307gite1bf319/src/twmc/acceptt.c000066400000000000000000000057111305746555600213200ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: acceptt.c DESCRIPTION:accept routine used in simulated annealing CONTENTS: acceptt( INT ) DATE: Jan 30, 1988 REVISIONS: ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) acceptt.c version 3.3 9/5/90" ; #endif #include #include #define MASK 0x3ff static DOUBLE table1S[1024] , table2S[1024] , table3S[1024] ; init_table() { INT i2 ; table1S[0] = 1.0 ; table2S[0] = 1.0 ; table3S[0] = 1.0 ; for( i2 = 1 ; i2 <= 1023 ; i2++ ) { table1S[ i2 ] = exp( -(DOUBLE) i2 / 8.0 ) ; table2S[ i2 ] = exp( -(DOUBLE) i2 / 8192.0 ) ; table3S[ i2 ] = exp( -(DOUBLE) i2 / 8388608.0 ) ; } } INT acceptt( delta_cost ) INT delta_cost ; { INT truth ; DOUBLE fred ; register unsigned fract ; d_costG = delta_cost ; /*** make it known to the world. JL ***/ fred = ((DOUBLE) delta_cost ) / TG ; if( fred >= 0.0 ) { truth = 1 ; } else if( fred < -80.0 ) { truth = 0 ; } else if( fred > -0.0001 ) { if( 1.0 + fred > ( (DOUBLE) RAND / (DOUBLE)0x7fffffff ) ) { truth = 1 ; } else { truth = 0 ; } } else { fract = (INT)( -fred * 8388608.0 ) ; if( (table1S[ (fract >> 20) & MASK ] * table2S[ (fract >> 10) & MASK] * table3S[ fract & MASK ]) > ( (DOUBLE) RAND / (DOUBLE)0x7fffffff ) ) { truth = 1 ; } else { truth = 0 ; } } return(truth) ; } graywolf-0.1.4+20170307gite1bf319/src/twmc/analog.h000066400000000000000000000044651305746555600211500ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: analog.h CONTENTS: definitions for analog information. DATE: Dec 13, 1990 REVISIONS: ----------------------------------------------------------------- */ /* ***************************************************************** "@(#) analog.h (Yale) version 1.2 2/23/91" ***************************************************************** */ #ifndef ANALOG_H #define ANALOG_H #define INIT_DROP -1000000.0 #define NO_CONSTRAINT_ON_DROP -100000.0 #define INIT_CURRENT -1000000.0 #define NO_CURRENT_SPECIFIED -100000.0 #define INIT_CAP -1.0 #define INIT_RES -1.0 /* analog net type */ #define SHIELDING_NET 1 #define SHIELDMASK 0x1 #define NOISY_NET 2 #define NOISYMASK 0x2 #define SENSITIVE_NET 4 #define SENSITIVEMASK 0x4 /* the circuit type */ #define NO_CKT_TYPE 0 #define DIGITAL 0x1 #define ANALOG 0x2 #define MIXED 0x3 typedef struct abox { INT *x_contour ; /* x coordinates of pin contour */ INT *y_contour ; /* y coordinates of pin contour */ INT num_corners ; /* number of vertices in pin contour */ FLOAT current ; /* current for the pin */ FLOAT power ; /* power for the pin */ BOOL no_layer_change ; /* whether layer change are allowed */ } ANALOGBOX, *ANALOGPTR ; typedef struct common_pt { INT num_pins ; /* number of pins in this common point */ INT *common_set ; /* set of pins in the common point */ INT *cap_match ; /* pins that must match cap. for each cpt.*/ INT *res_match ; /* pins that must match res. for each cpt.*/ } COMMONBOX, *COMMONPTR ; typedef struct analognet { DOUBLE cap_upper_bound ; /* capacitance upper bound */ DOUBLE res_upper_bound ; /* resistance upper bound */ INT net_type ; /* noisy, sensitive, shielding */ INT num_common_points ; /* number of common points for the net */ COMMONPTR *common_pts ; /* array of the common points */ DOUBLE max_drop ; /* max voltage drop */ } ANETBOX, *ANETPTR ; #endif /* ANALOG_H */ graywolf-0.1.4+20170307gite1bf319/src/twmc/analyze.c000066400000000000000000000156501305746555600213430ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: analyze.c DESCRIPTION:This file contains routines for analyzing random to optimal wire ratio. CONTENTS: analyze( ) compare( int, INT ) DATE: Apr 4, 1988 REVISIONS: ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) analyze.c version 3.7 4/18/91" ; #endif #include #include #include #include #define CURWT 1 #define PRIORWT 1 #define KEYSTRING "TimberWolfMC reduction" #define EXPECTEDWIRERATIO 2.0 static INT *howmanyS ; extern DOUBLE wireratio() ; DOUBLE analyze() { INT **number , i , net , net1 , net2 , num , cell ; INT *count , different , cnum , c2num , *arraynet ; INT num_nets , tot_cels ; DOUBLE C , C1 , C2 , C3 , wireRatio ; PINBOXPTR pinptr ; INT comparex() ; DOUBLE weight_past_runs( /* wireRatio */ ) ; count = (INT *) Ysafe_malloc( (1 + numcellsG) * sizeof( INT ) ) ; number = (INT **) Ysafe_malloc( (1 + numnetsG) * sizeof( INT *) ) ; howmanyS = (INT *) Ysafe_malloc( (1 + numnetsG) * sizeof( INT ) ) ; arraynet = (INT *) Ysafe_malloc( (1 + numnetsG) * sizeof( INT ) ) ; for( net = 0 ; net <= numnetsG ; net++ ) { number[net] = (INT *) Ysafe_malloc( (1 + numcellsG) * sizeof(INT) ) ; } for( net = 1 ; net <= numnetsG ; net++ ) { for( cell = 0 ; cell <= numcellsG ; cell++ ) { count[cell] = 0 ; number[net][cell] = 0 ; } for( pinptr=netarrayG[net]->pins;pinptr; pinptr = pinptr->next ){ if( pinptr->cell <= numcellsG ) { count[pinptr->cell] = 1 ; } } /* * I would like to find the number of distinct nets */ for( cell = 1 ; cell <= numcellsG ; cell++ ) { if( count[cell] == 1 ) { number[net][ ++number[net][0] ] = cell ; } } } /* ********************************************************** */ num_nets = 0 ; tot_cels = 0 ; for( net1 = 1 ; net1 <= numnetsG ; net1++ ) { if( number[net1][0] <= 1 ) { continue ; } num_nets++ ; tot_cels += number[net1][0] ; } OUT1("\n\n*************************************\n"); OUT2("AVERAGE NUMBER OF CELLS PER NET: %f\n", ( (DOUBLE) tot_cels / (DOUBLE) num_nets ) ) ; OUT1("*************************************\n\n\n"); /* ********************************************************** */ for( net1 = 1 ; net1 <= numnetsG ; net1++ ) { if( number[net1][0] == 0 ) { howmanyS[net1] = 0 ; continue ; } if( number[net1][0] == 1 ) { number[net1][0] = 0 ; howmanyS[net1] = 0 ; continue ; } howmanyS[net1] = 1 ; for( net2 = net1 + 1 ; net2 <= numnetsG ; net2++ ) { if( number[net2][0] != number[net1][0] ) { continue ; } different = 0 ; for( i = 1 ; i <= numcellsG ; i++ ) { if( number[net2][i] != number[net1][i] ) { different = 1 ; break ; } } if( ! different ) { number[net2][0] = 0 ; howmanyS[net1]++ ; } } } arraynet[0] = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { if( howmanyS[net] <= 0 ) { continue ; } arraynet[ ++arraynet[0] ] = net ; } num = arraynet[0] ; arraynet[0] = arraynet[ arraynet[0] ] ; Yquicksort( (char *) arraynet , num , sizeof( INT ), comparex ) ; /* sorted: most occurrences first */ num = 0 ; cnum = 0 ; c2num = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { if( number[net][0] > 0 ) { cnum += number[net][0] - 1 ; c2num += number[net][0] ; num++ ; } } C = (DOUBLE) num / (DOUBLE) numcellsG ; C1 = (DOUBLE) cnum / (DOUBLE) num ; C2 = (DOUBLE) c2num / (DOUBLE) num ; C3 = (DOUBLE) cnum / (DOUBLE)(numcellsG - 1) ; OUT1("\n\n\n**********************************************\n\n"); OUT1("The average number of distinct nets per cell is\n"); OUT2("given by: %6.2f\n\n", C ); OUT1("The average number of cells per net is\n"); OUT2("given by: %6.2f\n\n", C2 ); OUT1("The average number of other cells per net is\n"); OUT2("given by: %6.2f\n\n", C1 ); OUT1("The ratio of total cells specified per net to\n"); OUT2("numcells is given by: %6.2f\n\n", C3 ); OUT1("The average number of cells connected to a cell is\n"); OUT2("given by: %6.2f\n\n", C * C1 ); OUT1("**********************************************\n\n\n"); wireRatio = EXPECTEDWIRERATIO ; OUT2("Expected Wire Reduction Relative to Random:%6.2f\n\n",wireRatio); FLUSHOUT(); wireRatio = weight_past_runs( wireRatio ) ; sprintf( YmsgG,"\n\nWire ratio updated to:%4.2f\n\n", wireRatio ) ; M( MSG, "analyze", YmsgG ) ; return( wireRatio ); } INT comparex( a , b ) INT *a , *b ; { return( howmanyS[*b] - howmanyS[*a] ) ; } DOUBLE weight_past_runs( wireRatio ) DOUBLE wireRatio ; { FILE *fp ; /* log file */ char buffer[LRECL], *bufferptr ; char **tokens ; /* for parsing file */ INT numtokens ; DOUBLE reduction ; /* previous value of reduction */ sprintf( buffer, "%s.log", cktNameG ) ; fp = TWOPEN( buffer, "r", NOABORT ) ; if(!(fp) ){ /* doesn't exist return calculated value */ return( wireRatio ) ; } /* parse log file */ while( bufferptr=fgets(buffer,LRECL,fp )){ /* parse file */ tokens = Ystrparser( bufferptr, ":\t\n", &numtokens ); if( numtokens == 0 ){ /* skip over empty lines */ continue ; } else if( numtokens == 5 && strcmp( tokens[3], KEYSTRING ) == STRINGEQ){ reduction = atof( tokens[4] ) ; /* weight the average towards latest run */ wireRatio = (CURWT * reduction + PRIORWT * wireRatio)/ ( CURWT + PRIORWT ) ; } } return( wireRatio ) ; } /* end weight_past_runs */ graywolf-0.1.4+20170307gite1bf319/src/twmc/compact.c000066400000000000000000000273561305746555600213340ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * Copyright (C) 2014 Ruben Undheim * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: compact.c DESCRIPTION:This file now contain call to compaction program. CONTENTS: DATE: Apr 8, 1988 REVISIONS: Nov 5, 1988 - free violations and modified position of sources and sinks. Dec 4, 1988 - corrected error in where to get data. Jan 15, 1989 - fixed constraINT problem for softcells by saving contents of tilebox and set orig_ fields correctly for compaction cycle for softcells. Jan 25, 1989 - removed incorrect force of box size to block area and added \n for new message macro. Mar 11, 1989 - added graphics conditional compile and commented out compactor state dump. Mar 30, 1989 - changed tile datastructure. Apr 17, 1989 - made compactor a separate program. May 1, 1989 - added cell partitioning flag to program. May 24, 1989 - changed name of compact program. Jun 21, 1989 - added TimberWolf directory search. Feb 7, 1990 - Now compactor uses routing tiles in order to account for routing area. Wed Jan 30 14:13:36 EST 1991 - now left justify orientation rotations. Thu Apr 11 15:25:09 EDT 1991 - added constraint compaction. Thu Apr 18 01:28:31 EDT 1991 - no graphics are passed to the compactor. Sun May 5 14:19:53 EDT 1991 - pass gridding point to compactor. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) compact.c version 3.12 5/5/91" ; #endif #include #include #include #include #include #include "config-build.h" #define VIOLATIONSONLY FALSE #define COMPACT TRUE #define COMPACTPROG "mc_compact" #define COMPACTPATH "../mc_compact" /* for compactor parser below */ #define INFOKEYWORD "numtiles" #define CELLKEYWORD "cell" #define SCELLKEYWORD "stdcell" #define TILEKEYWORD "l" compact( compactFlag ) BOOL compactFlag ; /* signals use of compaction */ { char filename[LRECL] ; char *Yrelpath() ; char *pathname ; char *twdir ; /* path of TimberWolf directory */ char *getenv() ; /* used to get TWDIR environment variable */ char buffer[LRECL], *bufferptr ; char **tokens ; /* for parsing file */ INT numtokens, line ; BOOL abort ; /* whether to abort program */ INT cell, numtiles, numcells ; INT xcenter, ycenter ; INT xoffset, yoffset ; INT l, r, b, t ; INT closegraphics() ; CELLBOXPTR cellptr ; TILEBOXPTR tileptr ; BOUNBOXPTR bounptr ; /* bounding box pointer */ RTILEBOXPTR rtptr ; /* current routing tile */ FILE *fp ; INT type ; /* ######### Create compaction file and exec compactor ######### */ /* open compaction file for writing */ sprintf(filename, "%s.mvio" , cktNameG ) ; fp = TWOPEN( filename , "w", ABORT ) ; /* first count number of tiles and cells to be output */ numtiles = 0 ; numcells = 0 ; for( cell = 1 ; cell <= endsuperG ; cell++ ){ cellptr = cellarrayG[cell] ; if( cellptr->celltype != CUSTOMCELLTYPE && cellptr->celltype != SOFTCELLTYPE ){ continue ; } numcells++ ; for( tileptr=cellptr->tiles;tileptr;tileptr = tileptr->next ){ numtiles++ ; } /* count number of routing tiles if they exist */ if( routingTilesG ){ for( rtptr = routingTilesG[cell]; rtptr; rtptr = rtptr->next){ numtiles++ ; } } } /* end counting number of tiles */ /* now need to call compactor if no cells exist in the case of a single stdcell core */ if( numtiles == 0 ){ return ; } /* NOW output data */ fprintf( fp, "numtiles:%d numcells:%d\n", numtiles, numcells ) ; for( cell = 1 ; cell <= endsuperG; cell++ ){ cellptr = cellarrayG[cell] ; type = cellptr->celltype ; if( type != CUSTOMCELLTYPE && type != SOFTCELLTYPE ){ continue ; } xcenter = cellptr->xcenter ; ycenter = cellptr->ycenter ; xoffset = cellptr->bounBox[cellptr->orient]->l ; yoffset = cellptr->bounBox[cellptr->orient]->b ; if( type == CUSTOMCELLTYPE || type == SOFTCELLTYPE ){ fprintf( fp, "cell %d x:%d y:%d offset:%d %d\n", cellarrayG[cell]->cellnum, xcenter, ycenter, xoffset, yoffset ) ; } else { fprintf( fp, "stdcell %d x:%d y:%d offset:%d %d\n", cellarrayG[cell]->cellnum, xcenter, ycenter, xoffset, yoffset ) ; } /* setup translation of output points */ bounptr = cellptr->bounBox[0] ; /* now init the translation routines using bounding box */ Ytrans_init( bounptr->l,bounptr->b,bounptr->r,bounptr->t, cellptr->orient ) ; for( tileptr=cellptr->tiles;tileptr;tileptr = tileptr->next ){ l = tileptr->left ; r = tileptr->right ; b = tileptr->bottom ; t = tileptr->top ; if( cellptr->softflag){ /* ------------------------------------------------ At this point, a softcells aspect ratio has been fixed. So after placement set orig and current fields of the tilebox to same value. After this point, the current field will be used for the border added during global route and the orig field is cell size without routing border. --------------------------------------------------*/ if( compactFlag == FALSE ){ /* 1st time compact called */ tileptr->orig_left = tileptr->left ; tileptr->orig_right = tileptr->right ; tileptr->orig_bottom = tileptr->bottom ; tileptr->orig_top = tileptr->top ; } } /* calculate orientation for cell tiles */ YtranslateC( &l,&b,&r,&t,cellptr->orient) ; fprintf( fp, "l:%d r:%d b:%d t:%d\n", l,r,b,t ) ; } /* end tiles of a cell loop */ /* output routing tiles if they exist */ if( routingTilesG ){ for( rtptr = routingTilesG[cell]; rtptr; rtptr = rtptr->next){ fprintf( fp, "l:%d r:%d b:%d t:%d\n", rtptr->x1, rtptr->x2, rtptr->y1, rtptr->y2 ) ; } } } /* end cell loop */ TWCLOSE( fp ) ; /* now call the compactor */ /* find the path of compactor relative to main program */ pathname = Yrelpath( argv0G, COMPACTPATH ) ; if( !(YfileExists(pathname))){ if( twdir = TWFLOWDIR ){ sprintf( filename, "%s/bin/%s", twdir, COMPACTPROG ) ; pathname = Ystrclone( filename ) ; } } if( doPartitionG ){ sprintf( YmsgG, "%s -vn %s %d %d %d %d %d %d", pathname, cktNameG, blockrG, blocktG, track_spacingXG,track_spacingYG, track_spacingXG, track_spacingYG); } else if( compactFlag == VIOLATIONSONLY ){ sprintf( YmsgG, "%s -vn %s %d %d %d %d %d %d", pathname, cktNameG, blockrG, blocktG, track_spacingXG,track_spacingYG, track_spacingXG, track_spacingYG ); } else if( compactFlag == COMPACT ){ /* sprintf( YmsgG, "%s -n %s %d %d 0 0 0 0", pathname, cktNameG, blockrG, blocktG ); */ sprintf( YmsgG, "%s -cn %s %d %d %d %d 0 0", pathname, cktNameG, blockrG, blocktG, track_spacingXG,track_spacingYG ); D( "twsc/compact_graphics", sprintf( YmsgG, "%s -c %s %d %d %d %d 0 0", pathname, cktNameG, blockrG, blocktG, track_spacingXG,track_spacingYG); ) ; } else { M( ERRMSG,"compact", "unknown compact flag\n" ) ; return ; } M( MSG, NULL, YmsgG ) ; M( MSG, NULL, "\n" ) ; /* Ysystme will kill program if catastrophe occurred */ Ysystem( COMPACTPROG, ABORT, YmsgG, closegraphics ) ; Ysafe_free( pathname ) ; /* free name created in Yrelpath */ /* ############# end of compactor execution ############# */ /* **************** READ RESULTS of compaction ************/ /* open compaction file for writing */ M( MSG, NULL, "Reading results of compaction...\n" ) ; sprintf(filename, "%s.mcpt" , cktNameG ) ; fp = TWOPEN( filename , "r", ABORT ) ; /* parse file */ line = 0 ; abort = FALSE ; while( bufferptr=fgets(buffer,LRECL,fp )){ /* parse file */ line ++ ; /* increment line number */ tokens = Ystrparser( bufferptr, ": \t\n", &numtokens ); if( numtokens == 0 ){ /* skip over empty lines */ continue ; } else if( strcmp( tokens[0], INFOKEYWORD ) == STRINGEQ){ /* look at first field for keyword */ /* ie. numtiles:5 numcells:4 */ if( numtokens != 4 ){ sprintf( YmsgG, "Syntax error on line:%d\n", line ) ; M(ERRMSG, "compact", YmsgG ) ; abort = TRUE ; continue ; } if( numcells != atoi(tokens[3] ) ){ M(ERRMSG, "compact", "number of cells incorrect" ) ; abort = TRUE ; } if( abort ) break ; /* no sense in reading any longer */ } else if( strcmp( tokens[0], CELLKEYWORD ) == STRINGEQ || strcmp( tokens[0], SCELLKEYWORD ) == STRINGEQ ){ /* cell 1 x:312 y:512 offet:39 40 or */ /* softcell 1 x:312 y:512 offet:39 40 */ /* look at first field for keyword */ if( numtokens != 9 ){ sprintf( YmsgG, "Syntax error on line:%d\n", line ) ; M(ERRMSG, "compact", YmsgG ) ; abort = TRUE ; continue ; } cell = atoi( tokens[1] ) ; ASSERTNCONT( cell > 0 && cell <= endsuperG, "compact", "cell out of bounds" ) ; cellptr = cellarrayG[cell] ; cellptr->xcenter = atoi(tokens[3] ) ; cellptr->ycenter = atoi(tokens[5] ) ; } else if( strcmp( tokens[0], TILEKEYWORD ) == STRINGEQ){ /* look at first field for keyword */ /* l:-115 r:270 b:-85 t:85 */ if( numtokens != 8 ){ sprintf( YmsgG, "Syntax error on line:%d\n", line ) ; M(ERRMSG, "compact", YmsgG ) ; abort = TRUE ; continue ; } } else { sprintf( YmsgG, "Syntax error on line:%d\n", line ) ; M(ERRMSG, "compact", YmsgG ) ; abort = TRUE ; continue ; } } TWCLOSE( fp ) ; if( abort ){ M(ERRMSG, "compact", "Problem with compaction. Must abort\n" ) ; closegraphics() ; YexitPgm( PGMFAIL ) ; } /* ************ END READ RESULTS of compaction ************/ } /* end compact */ #define HOWMANY 0 /* need accurate cell centers in density calculation */ get_cell_centers( cell, xc, yc ) INT cell ; INT *xc, *yc ; { INT last_core_cell ; last_core_cell = (INT) routingTilesG[HOWMANY] - 4 ; if( cell <= last_core_cell ){ *xc = cellarrayG[cell]->xcenter ; *yc = cellarrayG[cell]->ycenter ; } else { /* pad macro */ /* next line is equivalent to */ /* cell = endpadgrpsG + (cell - last_core_cell) */ cell += endpadgrpsG - last_core_cell ; *xc = cellarrayG[cell]->xcenter ; *yc = cellarrayG[cell]->ycenter ; } } /* end get_cell_centers */ graywolf-0.1.4+20170307gite1bf319/src/twmc/config1.c000066400000000000000000000224511305746555600212230ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: config1.c DESCRIPTION:configures initial macro placement CONTENTS: config1( ) DATE: Jan 30, 1988 REVISIONS: Feb 13, 1988 - passed modified number of bins to routine This takes into account only number of cell bins not border bins. Feb 27, 1988 - no longer pass number of bins to routine This makebins calculates it and this routine now calls makebins. However, we still must watch border bins. Jun 27, 1988 - add calcPinFactor for initializing feedback controller for overfilled pin site penalty. Aug 16, 1988 - fixed sqrt domain error by add temp variables. var changed to double because wraparound problem. Aug 26, 1988 - fixed sqrt domain error correctly by adding DOUBLE temp variables. Jan 29, 1989 - fixed \n problem with message macros. Mar 02, 1989 - moved calcLapFactor and calcPinFactor to penalties.c Mar 30, 1989 - changed tile datastructure. Apr 30, 1989 - added max_shortSide calculation for partition case. Apr 20, 1990 - Now take aspect ration into account. Fri Jan 25 18:02:00 PST 1991 - fixed problem with recursive sizing of data. Mon Feb 4 02:01:57 EST 1991 - added call to update wire estimator after each configuration change. Thu Oct 17 11:47:32 EDT 1991 - added initialization. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) config1.c version 3.10 10/18/91" ; #endif #include #include #include #define NUMBINSPERCELL 4 /* we want average cell to be in 4 bins for accuracy */ #define WIREAREAUNKNOWN 0 /* at this time we don't know wire area */ #define UPDATE (BOOL) FALSE /* don't initialize updateFixedCells */ config1() { CELLBOXPTR cellptr ; TILEBOXPTR tileptr ; INT l , r , b , t , cell ; INT numbins, numbinX, numbinY ; INT window ; INT closegraphics() ; char arguments[LRECL] ; char resfile[LRECL] ; char savfile[LRECL] ; BOOL parasite ; DOUBLE tileArea ; DOUBLE softArea ; DOUBLE totalArea ; DOUBLE coreArea ; DOUBLE cellArea ; DOUBLE varpercell ; DOUBLE deltaArea, deltaShort ; DOUBLE shortvarpercell ; DOUBLE var = 0.0 ; DOUBLE temp ; DOUBLE var_short = 0.0 ; DOUBLE shortSide, total_shortSide, mean_shortSide, dev_shortSide ; DOUBLE length, height, max_shortSide ; /* * Sum the areas of the cells - get total area, average cell area. */ totalArea = 0.0 ; total_shortSide = 0.0 ; softArea = 0.0 ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = cellarrayG[cell] ; for( tileptr = cellptr->tiles;tileptr; tileptr = tileptr->next ){ l = tileptr->left ; r = tileptr->right ; b = tileptr->bottom ; t = tileptr->top ; tileArea = (DOUBLE) (r - l) * (DOUBLE) (t - b) ; totalArea += tileArea ; if( cellptr->celltype == STDCELLTYPE ){ softArea += tileArea ; } /* calculate mean of smallest size of tile */ length = ABS( r - l ) ; height = ABS( t - b ) ; total_shortSide += (DOUBLE) MIN( length , height ) ; } } mean_cellAreaG = (totalArea / (DOUBLE) numcellsG) ; mean_shortSide = total_shortSide / numcellsG ; /* * Find the variance in the size of the cells. * Find the variance in the shortest side of the tiles. * Find the largest short side for configuring partition case. */ max_shortSide = (DOUBLE) INT_MIN ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = cellarrayG[cell] ; /* get total area for one cell */ cellArea = 0.0 ; for( tileptr = cellptr->tiles;tileptr; tileptr = tileptr->next ){ l = tileptr->left ; r = tileptr->right ; b = tileptr->bottom ; t = tileptr->top ; length = ABS( r - l ) ; height = ABS( t - b ) ; cellArea += (DOUBLE) length * (DOUBLE) height ; /* calculate variance of smallest size of tile */ shortSide = MIN( length , height ) ; if( cellptr->celltype != STDCELLTYPE ){ /* find the maximum shortside */ max_shortSide = MAX( max_shortSide, shortSide ) ; } deltaShort = shortSide - mean_shortSide ; var_short += deltaShort * deltaShort ; } /* note variance of area is over a cell not tile */ deltaArea = cellArea - mean_cellAreaG ; var += deltaArea * deltaArea ; } varpercell = var / (DOUBLE) numcellsG ; dev_cellAreaG = sqrt( varpercell ) ; shortvarpercell = var_short / (DOUBLE) numcellsG ; dev_shortSide = sqrt( shortvarpercell ) ; OUT2("\nTotal cell area : %4.2le\n", totalArea ) ; OUT3("mean cell area : %4.2le std deviation cell area : %4.2le\n", mean_cellAreaG, dev_cellAreaG ) ; OUT3("mean short side : %4.2le std deviation short side : %4.2le\n", mean_shortSide, dev_shortSide ) ; if( coreGivenG == 0 ) { blockrG = blocktG = (INT) sqrt( (DOUBLE) totalArea ) + 1 ; /* * Take into account the aspect ratio requested by the user */ blocktG = (INT)( sqrt(chipaspectG) * (DOUBLE) blocktG ) + 1 ; blockrG = (INT)( 1.0 / sqrt(chipaspectG) * (DOUBLE) blockrG ) + 1; blocklG = blockbG = 0 ; totChanLenG = perimG / 2 - (blockrG + blocktG) ; aveChanWidG = 0.0 ; } else { r = t = (INT) sqrt( totalArea ) + 1 ; totChanLenG = perimG / 2 - (r + t) ; aveChanWidG = 0.0 ; } slopeXG = (DOUBLE)(maxWeightG - baseWeightG) / ((DOUBLE) blockrG * 0.5 ) ; slopeYG = (DOUBLE)(maxWeightG - baseWeightG) / ((DOUBLE) blocktG * 0.5 ) ; basefactorG = (DOUBLE) baseWeightG ; wireFactorXG = wireFactorYG = 0.0 ; /* DETERMINE NUMBER OF BINS */ cellArea = (DOUBLE) (mean_shortSide + 0 * dev_shortSide ) ; cellArea *= cellArea ; coreArea = ((DOUBLE) blocktG - blockbG) * ((DOUBLE) blockrG - blocklG) ; if( 5.0 * coreArea > (DOUBLE) INT_MAX && !(cost_onlyG) ){ scale_dataG = (INT) sqrt( (10.0 * coreArea / (DOUBLE) INT_MAX)) ; scale_dataG++ ; /* round up always */ M( MSG,"config1", "Design is too large for integer operations\n"); sprintf( YmsgG, "Calling TimberWolfMC recursively to scale data by %d\n", scale_dataG ) ; M( MSG, NULL, YmsgG ) ; TWCLOSE( fpoG ) ; parasite = get_arg_string( arguments ) ; M( MSG, NULL, arguments ) ; M( MSG, NULL, "\n" ) ; Ysystem( "TimberWolfMC", ABORT, arguments, closegraphics ) ; /* go to cost only mode */ cost_onlyG = TRUE ; /* read the placement from restart file by moving sav to res */ sprintf( savfile, "%s.msav", cktNameG ) ; sprintf( resfile, "%s.mres", cktNameG ) ; /* make a system independent copy */ YcopyFile( savfile, resfile ) ; if( parasite ){ /* if we save the graphics state we need to restore it */ G( TWrestoreState() ) ; } restartG = TRUE ; scale_dataG = 1 ; } numbins = (INT) ((DOUBLE) NUMBINSPERCELL * coreArea / (DOUBLE) cellArea ) ; if( numbins <= 1 ){ M(ERRMSG,"config1","number of bins calculated is <= 1. Must exit.\n"); closegraphics() ; YexitPgm( FAIL ) ; } /* makebins determines globals maxBinX and maxBinY */ makebins( numbins ) ; /***** calculate the core configuration constants for wire estimation */ blockmxG = (blockrG + blocklG) / 2 ; blockmyG = (blocktG + blockbG) / 2 ; halfXspanG = (blockrG - blocklG) / 2 ; halfYspanG = (blocktG - blockrG) / 2 ; /* take account of border for loadbins */ numbinX = maxBinXG - 1; numbinY = maxBinYG - 1; binWidthXG = (blockrG - blocklG) / numbinX ; if( (blockrG - blocklG - binWidthXG * numbinX) >= numbinX / 2 ) { binWidthXG++ ; } binXOffstG = blocklG + 1 - binWidthXG ; binWidthYG = (blocktG - blockbG) / numbinY ; if( (blocktG - blockbG - binWidthYG * numbinY) >= numbinY / 2 ) { binWidthYG++ ; } binYOffstG = blockbG + 1 - binWidthYG ; updateFixedCells( UPDATE ) ; /* place fixed cells */ if( !(cost_onlyG) ){ loadbins( WIREAREAUNKNOWN ) ; } placepads() ; bdxlengthG = blockrG - blocklG ; bdylengthG = blocktG - blockbG ; OUT3("bdxlength:%d bdylength:%d\n",bdxlengthG,bdylengthG); FLUSHOUT(); /* update for wire estimation algorithm */ resize_wire_params() ; return ; } /* end config1 */ graywolf-0.1.4+20170307gite1bf319/src/twmc/config2.c000066400000000000000000000116031305746555600212210ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: config2.c DESCRIPTION:configures initial macro placement CONTENTS: config2( INT, INT, double ) DATE: Jan 30, 1988 REVISIONS: Feb 13, 1988 - passed modified number of bins to routine This takes into account only number of cell bins not border bins. Mar 30, 1989 - changed tile datastructure. Apr 28, 1989 - changed arguments to config2. Jun 15, 1989 - now call reconfig for common code. Oct 3, 1989 - made totalArea a DOUBLE. Oct 20, 1989 - now take average of track pitch in both directions. Apr 23, 1990 - Now calculate total area based on all instances so that the wire estimation will be correct. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) config2.c version 3.3 9/5/90" ; #endif #include #include config2( numbinX, numbinY, wire_red_ratio ) INT numbinX ; INT numbinY ; DOUBLE wire_red_ratio ; { INT inst ; /* counter */ INT numinst ; /* number of cell instances */ INT l, r, b, t, cell, tempint, side, soft_count ; CELLBOXPTR cellptr ; TILEBOXPTR tileptr ; DOUBLE totalArea, temp ; DOUBLE temp1, fraction ; INSTBOXPTR instptr ; /* * Sum the areas of the cells over all instances */ totalArea = 0.0 ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = cellarrayG[cell] ; /* look at all the instances */ if( instptr = cellptr->instptr ){ numinst = instptr->numinstances ; } else { numinst = 1 ; } for( inst = 0 ; inst < numinst; inst++ ){ if( instptr ){ tileptr = instptr->tile_inst[inst] ; } else { tileptr = cellptr->tiles ; } for( ; tileptr ; tileptr = tileptr->next ) { l = tileptr->left ; r = tileptr->right ; b = tileptr->bottom ; t = tileptr->top ; totalArea += (DOUBLE) (r - l) * (t - b) ; } } } temp = avg_funcG / wire_red_ratio ; totNetLenG = (INT) temp ; /* calculate number of softiles */ soft_count=0 ; for( cell = 1; cell <= numcellsG ; cell++ ) { if( cellarrayG[cell]->softflag == 1 ) { soft_count++ ; } } fraction = (DOUBLE) soft_count / (DOUBLE) numcellsG ; temp1 = (DOUBLE) (totNetLenG) / (1.0 + (fraction / (sqrt( (DOUBLE) numcellsG )))) ; totNetLenG = (INT) temp1 ; if( coreGivenG == 0 ) { blockrG = blocktG = (INT) sqrt( totalArea ) ; totChanLenG = perimG / 2 - (blockrG + blocktG) ; temp = ((DOUBLE) totNetLenG / (DOUBLE) totChanLenG) / ((DOUBLE) layersFactorG) ; } else { r = t = (INT) sqrt( totalArea ) ; totChanLenG = perimG / 2 - (r + t) ; temp = ((DOUBLE) totNetLenG / (DOUBLE) totChanLenG) / ((DOUBLE) layersFactorG) ; } side = (INT)(sqrt(((DOUBLE) totalArea) / (DOUBLE) numcellsG)) ; OUT2("\n\nAVERAGE CELL SIDE WITHOUT ROUTING AREA: %d\n\n",side ); tempint = (INT)( temp ) + 3 ; /* d+1 tracks + roundoff */ tempint += defaultTracksG ; tempint *= (track_spacingXG + track_spacingYG) / 2 ; aveChanWidG = ( (DOUBLE) tempint / 1.8) + 2.0 ; OUT2("\n\nConfiguration Data\nInternal Channel Length:%d\n", totChanLenG ) ; OUT2("Average Channel Width (un-normalized):%f\n\n", temp ) ; OUT2("Average Channel Width:%f\n\n", aveChanWidG ) ; reconfigure( numbinX, numbinY, (DOUBLE) totalArea ) ; return ; } graywolf-0.1.4+20170307gite1bf319/src/twmc/configpads.c000066400000000000000000000574431305746555600220230ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: configpads.c DESCRIPTION:Configure pads CONTENTS: DATE: Jan 29, 1989 - added heading. REVISIONS: Jan 29, 1989 - removed message about pad limited designs. Mar 30, 1989 - changed tile datastructure. Apr 30, 1989 - fixed problem with padgroups. Rewrote major sections of the algorithm. Sat Feb 23 00:17:28 EST 1991 - added placepads algorithm. Tue Mar 19 16:31:45 CST 1991 - added core expansion code. Thu Apr 18 01:29:33 EDT 1991 - fixed problem with align_pads when no pads are on a given side. Thu Aug 29 15:44:00 CDT 1991 - added overflow processing code. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) configpads.c version 3.10 11/23/91" ; #endif #include #include #include #include /* ***************** STATIC FUNCTION DEFINITIONS ******************* */ static BOOL check_overflow( P1(BOOL retain_pad_groups) ) ; static move_clockwise( P4(INT pad, INT side, INT cw_side, INT moveable_cw) ) ; static move_counterclockwise( P4(INT pad,INT side,INT ccw_side,INT m_ccw ) ) ; static update_pad_position( P3(PADBOXPTR pad,INT current_side, INT move_side) ); static expand_core( P1(INT side) ) ; static INT compare_overflow( P2(INT *side1, INT *side2) ) ; static update_pad_groups( P1(void) ) ; static resort_place_array( P1(void) ) ; static child_constraints(P5(PADBOXPTR pad,INT side,DOUBLE lb,DOUBLE ub,BOOL s)); static place_variable( P3(INT first,INT numpads,INT side) ) ; /* ***************** STATIC VARIABLE DEFINITIONS ******************* */ static INT overflowS[5] ; /* amount of overflow on each side */ static INT side_lengthS[5] ; /* sum of pad lengths on a side */ static INT first_pad_on_sideS[5] ; /* index of first pad on side */ static INT last_pad_on_sideS[5] ; /* index of last pad on side */ static INT pad_extraS ; /* insure that sort works correctly */ align_pads() { INT pad ; /* counter */ INT side ; /* current pad side */ INT last ; /* index of last pad on side */ INT first ; /* index of first pad on side */ INT count ; /* count number of overflow iterations */ INT length ; /* length of current pad */ INT needed ; /* extra space needed on each side */ INT numpads ; /* number of pads on this side */ INT cum_space ; /* cum_space on this side */ INT padspacing ; /* padspacing method for current side*/ INT extra_space ; /* slack on a side */ BOOL overflow_exists ; /* if set, overflow still exists */ BOOL retain_pad_groups ; /* if set, padgroups will not be moved from side */ PADBOXPTR padptr ; /* current pad info */ DOUBLE left_edge ; /* left edge of the placed pad */ DOUBLE extra_space_per_pad ; /* how much left over per pad */ count = 0 ; retain_pad_groups = TRUE ; pad_extraS = 100000 ; do { overflow_exists = check_overflow( retain_pad_groups ) ; if( overflow_exists ){ resort_place_array() ; } if( ++count >= 3 ){ retain_pad_groups = FALSE ; } } while( overflow_exists ) ; update_pad_groups() ; for( side = 1 ; side <= 4 ; side++ ) { if(!(first_pad_on_sideS[side])){ /* there are no pads on this side */ continue ; } extra_space = perdimG[ side%2 ] - side_lengthS[side] ; /* check to see if we have overflow */ if( extra_space <= 0 ){ /* we must perform abut padspacing on this side */ padspacing = ABUT_PADS ; } else { /* do what the user requested */ padspacing = padspacingG ; } first = first_pad_on_sideS[side] ; last = last_pad_on_sideS[side] ; numpads = last - first + 1 ; switch( padspacing ){ case UNIFORM_PADS: extra_space_per_pad = (DOUBLE) extra_space / (DOUBLE) (numpads+1) ; left_edge = (DOUBLE) coreG[side%2][MINI] ; for( pad = 1; pad <= numpads; pad++ ){ padptr = placearrayG[first + pad - 1] ; /* calculate the placement of the left edge of the pad */ left_edge += extra_space_per_pad ; /* now find the center of the current pad */ padptr->position = ((INT) left_edge ) + padptr->length / 2 ; /* now set left edge for next pad */ left_edge += (DOUBLE) (padptr->length + min_pad_spacingG) ; } break ; case ABUT_PADS: extra_space_per_pad = (DOUBLE) extra_space / 2.0 ; left_edge = (DOUBLE) coreG[side%2][MINI] + extra_space_per_pad ; for( pad = 1; pad <= numpads; pad++ ){ padptr = placearrayG[first + pad - 1] ; /* now find the center of the current pad */ padptr->position = ((INT) left_edge ) + padptr->length / 2 ; /* now set left edge for next pad */ left_edge += (DOUBLE) (padptr->length + min_pad_spacingG) ; } break ; case VARIABLE_PADS: /* we now we can fit it on this side */ place_variable( first, numpads, side ) ; break ; case EXACT_PADS: break ; } /* end switch */ } /* end loop on sides */ } /* end align_pads */ /* ***************************************************************** */ static BOOL check_overflow( retain_pad_groups ) BOOL retain_pad_groups ; { INT i ; /* counter */ INT pad ; /* counter */ INT side ; /* current pad side */ INT cw_pad ; /* pad to move in clockwise direction */ INT ccw_pad ; /* pad to move in ccw direction */ INT length ; /* length of current pad */ INT clockwise ; /* the side in the clockwise direction */ INT counterclockwise ; /* the side in the ccw direction */ INT overflow_cw ; /* amount of overflow when pad is moved cw */ INT overflow_ccw ; /* amount of overflow when pad is moved ccw */ INT moveable_cw ; /* size of pad to be moved cw */ INT moveable_ccw ; /* size of pad to be moved ccw */ INT side_open[5] ; /* whether side has been processed */ INT sort_overflow[5] ; /* index for sorted overflow */ INT compare_overflow() ; /* sort the sides for overflow */ PADBOXPTR padptr ; /* current pad info */ /* first accummulate the sum of all the pads on a given side */ /* also find the first and last pad on a given side */ for( side = 1 ; side <= 4 ; side++ ) { overflowS[side] = 0 ; side_lengthS[side] = 0 ; first_pad_on_sideS[side] = 0 ; last_pad_on_sideS[side] = -1 ; } for( pad = 1 ; pad <= numpadsG ; pad++ ) { padptr = placearrayG[pad] ; side = padptr->padside ; length = padptr->length ; /* this will add one too many min_pad_spacing */ /* subtract it below */ side_lengthS[side] += length + min_pad_spacingG ; if(!(first_pad_on_sideS[side])){ first_pad_on_sideS[side] = pad ; } last_pad_on_sideS[side] = pad ; } /* check for overflow on the sides */ for( side = 1 ; side <= 4 ; side++ ) { /* adjust extra min_pad_spacing */ if(first_pad_on_sideS[side]){ /* there are pads on this side */ side_lengthS[side] -= min_pad_spacingG ; } overflowS[side] = side_lengthS[side] - perdimG[ side%2 ] ; } /* check to see if we have overflow */ if( overflowS[L] <= 0 && overflowS[R] <= 0 && overflowS[B] <= 0 && overflowS[T] <= 0 ){ /* there is no overflow */ return( FALSE ) ; } /* overflow exists so resolve the conflict. */ /* first sort the overflow */ for( i = 1 ; i <= 4; i++ ){ /* initialize sort_overflow array */ sort_overflow[i] = i ; side_open[i] = TRUE ; } Yquicksort( &(sort_overflow[1]), 4, sizeof(INT), compare_overflow ); for( i = 1; i <= 4; i++ ){ side = sort_overflow[i] ; side_open[side] = FALSE ; if( overflowS[side] <= 0 ){ continue ; } /* find clockwise side */ clockwise = side + 1 ; if( clockwise > 4 ) clockwise = 1 ; /* wrap around */ /* find counter clockwise side */ counterclockwise = side - 1 ; if( counterclockwise < 1 ) counterclockwise = 4 ; /* wrap around */ do { /* look for the last valid pad on side to move clockwise */ /* make sure side is still open */ cw_pad = 0 ; if( side_open[clockwise] ){ for( pad = last_pad_on_sideS[side];pad >= first_pad_on_sideS[side]; pad-- ){ padptr = placearrayG[pad] ; if( padptr->padside != side ){ /* this means we already moved this pad from this side */ continue ; } if( retain_pad_groups && padptr->hierarchy != NONE ){ /* if the retain_pad_group switch is on, we ignore any */ /* pad in a padgroup */ continue ; } if( padptr->valid_side[ALL] || padptr->valid_side[clockwise] ){ cw_pad = pad ; moveable_cw = padptr->length + min_pad_spacingG ; break ; } } /* end pad = last_pad_on_side... */ } /* end side_open[clockwise... */ /* look for the first valid pad on side to move counterclockwise */ /* make sure side is still open */ ccw_pad = 0 ; if( side_open[counterclockwise] ){ for( pad = first_pad_on_sideS[side]; pad <= last_pad_on_sideS[side]; pad++ ){ padptr = placearrayG[pad] ; if( padptr->padside != side ){ /* this means we already moved this pad from this side */ continue ; } if( retain_pad_groups && padptr->hierarchy != NONE ){ /* if the retain_pad_group switch is on, we ignore any */ /* pad in a padgroup */ continue ; } if( padptr->valid_side[ALL] || padptr->valid_side[counterclockwise] ){ ccw_pad = pad ; moveable_ccw = padptr->length + min_pad_spacingG ; break ; } } /* end pad = first_pad_on_side... */ } /* end side_open[counterclockwise... */ if( cw_pad && ccw_pad ){ /* this is the case where there are two valid pads which can be moved */ /* pick the pad && side which has smaller overflow */ overflow_cw = overflowS[clockwise] + moveable_cw ; ; overflow_ccw = overflowS[counterclockwise] + moveable_ccw ; ; if( overflow_cw <= overflow_ccw ){ move_clockwise( cw_pad, side, clockwise, moveable_cw ) ; } else { move_counterclockwise( ccw_pad, side, counterclockwise, moveable_ccw ) ; } } else if( cw_pad ){ move_clockwise( cw_pad, side, clockwise, moveable_cw ) ; } else if( ccw_pad ){ move_counterclockwise( ccw_pad, side, counterclockwise, moveable_ccw ) ; } else { /* no more pads to move, we need to expand core */ expand_core( side ) ; return( TRUE ) ; } } while( overflowS[side] > 0 ) ; } /* end for( i = 1; i <= 4; i++ ) ... */ /* if we get here, we had some overflow */ return( TRUE ) ; } /* end check_overflow */ static move_clockwise( pad, side, clockwise_side, moveable_cw ) INT pad, side, clockwise_side, moveable_cw ; { PADBOXPTR padptr ; /* current pad info */ /* move pad */ padptr = placearrayG[pad] ; padptr->padside = clockwise_side ; /* determine position */ update_pad_position( padptr, side, clockwise_side ) ; /* reset the overflows */ overflowS[side] -= moveable_cw ; overflowS[clockwise_side] += moveable_cw ; } /* end move_clockwise */ static move_counterclockwise( pad, side, counterclockwise, moveable_ccw ) INT pad, side, counterclockwise, moveable_ccw ; { PADBOXPTR padptr ; /* current pad info */ /* move pad */ padptr = placearrayG[pad] ; padptr->padside = counterclockwise ; update_pad_position( padptr, side, counterclockwise ) ; /* determine position */ /* reset the overflows */ overflowS[side] -= moveable_ccw ; overflowS[counterclockwise] += moveable_ccw ; } /* end move_counterclockwise */ static update_pad_position( padptr, current_side, move_side ) PADBOXPTR padptr ; /* current pad info */ INT current_side ; INT move_side ; { INT dimension ; /* the X or Y dimension */ dimension = move_side % 2 ; switch( current_side ){ case L: padptr->position = coreG[dimension][MINI] - ++pad_extraS; break ; case T: padptr->position = coreG[dimension][MAXI] + ++pad_extraS ; break ; case R: padptr->position = coreG[dimension][MAXI] + ++pad_extraS ; break ; case B: padptr->position = coreG[dimension][MINI] - ++pad_extraS; break ; } /* end switch side ... */ } /* end update_pad_position */ static expand_core( side ) INT side ; { INT i ; /* counter */ INT pad ; /* counter */ INT overflow_amount ; /* amount to expand */ INT amount ; /* amount to add to each pad half of a side */ INT expansion ; /* amount to expand a dimension */ PADBOXPTR padptr ; /* current pad info */ overflow_amount = 0 ; /* determine how much to expand by */ /* normally we assume that all sides can help reduce overflow */ /* if we find that the overflow_amount < 0 or overflow_amount is only */ /* 25% of the overflow on a side, it means that some sides */ /* have non moveable pads. We need to make the overflow amount the given side */ for( i = 1; i <= 4 ; i++ ){ overflow_amount += overflowS[i] ; } if( overflow_amount < 0 || overflow_amount < 0.25 * overflowS[side] ){ overflow_amount = overflowS[side] ; } /* now divide the amount equally in both dimensions */ expansion = overflow_amount / 2 ; if( expansion <= 0 ) expansion = 1 ; amount = expansion / 2 ; coreG[X][MINI] -= amount ; coreG[X][MAXI] += (expansion - amount ) ; coreG[Y][MINI] -= amount ; coreG[Y][MAXI] += (expansion - amount ) ; /* expand in X and Y directions */ /* we to search all the pads since they may not be in order */ for( pad = 1 ; pad <= numpadsG ; pad++ ) { padptr = placearrayG[pad] ; side = padptr->padside ; padptr->position += amount ; } /* now reset the perimeters */ perdimG[X] = coreG[X][MAXI] - coreG[X][MINI] ; perdimG[Y] = coreG[Y][MAXI] - coreG[Y][MINI] ; } /* end expand_core */ static INT compare_overflow( side1, side2 ) INT *side1, *side2 ; { /* sort largest to smallest */ return( overflowS[*side2] - overflowS[*side1] ) ; } /* end compare_overflow */ static INT compare_placearray( padptr1, padptr2 ) PADBOXPTR *padptr1, *padptr2 ; { PADBOXPTR pad1, pad2; pad1 = *padptr1 ; pad2 = *padptr2 ; if( pad1->padside != pad2->padside) { return( pad1->padside - pad2->padside ) ; } if( pad1->position < pad2->position ){ return( -1 ) ; } else if( pad1->position > pad2->position ){ return( 1 ) ; } else { return( 0 ) ; } } /* end compare_placearray */ static resort_place_array() { Yquicksort( &(placearrayG[1]), numpadsG, sizeof(PADBOXPTR), compare_placearray ); } /* end resort_place_array */ /* ***************************************************************** */ /* set the lo_pos and hi_pos fields for the pads */ static update_pad_groups() { INT i ; /* pad counter */ DOUBLE lobound ; /* lower bound on position */ DOUBLE hibound ; /* upper bound on position */ BOOL spacing_restricted ; /* whether spacing is restricted */ PADBOXPTR pad ; /* current pad */ if( padspacingG != VARIABLE_PADS ){ return ; } /* now update the lo_pos and hi_pos fields of the pad */ for( i = 1 ; i <= totalpadsG; i++ ) { pad = padarrayG[i]; /* make copy of these we don't want to change roots copy */ lobound = pad->lowerbound ; hibound = pad->upperbound ; spacing_restricted = pad->fixed ; if( pad->padtype == PADGROUPTYPE && pad->hierarchy == ROOT ){ child_constraints( pad, pad->padside, lobound, hibound, spacing_restricted ) ; } else if( pad->padtype == PADCELLTYPE && pad->hierarchy == NONE ) { /* the case of a pad that is not in a padgroup */ calc_constraints( pad, pad->padside, &lobound, &hibound, &spacing_restricted, &(pad->lo_pos), &(pad->hi_pos) ) ; } } } /* end update_pad_groups */ /* this will set the constaints for pad groups and children of them */ static child_constraints( pad, side, lb, ub, spacing_restricted ) PADBOXPTR pad ; INT side ; DOUBLE lb, ub ; BOOL spacing_restricted ; { INT i ; /* pad counter */ INT howmany ; /* number of children */ PADBOXPTR child ; /* current child */ calc_constraints( pad, side, &lb, &ub, &spacing_restricted, &(pad->lo_pos), &(pad->hi_pos) ); if( pad->padtype != PADCELLTYPE ){ howmany = pad->children[HOWMANY] ; for( i = 1 ;i <= howmany ; i++ ){ child = padarrayG[ pad->children[i] ] ; child_constraints( child, side, lb, ub,spacing_restricted ) ; } } } /* end child_constraints */ /* ***************************************************************** */ calc_constraints( pad, side, lb, ub, spacing_restricted,lowpos, uppos ) PADBOXPTR pad ; INT side ; DOUBLE *lb, *ub ; BOOL *spacing_restricted ; INT *lowpos, *uppos ; { DOUBLE lowbound, hibound ; /* determine spacing restrictions */ if( *spacing_restricted ){ /* this is the case that the spacing has been restricted */ if( pad->fixed ){ /* if the padgroup bounds have been fixed, */ /* force position to be within bound */ /* assume we are ok and then correct it */ lowbound = pad->lowerbound ; if( lowbound < *lb ){ lowbound = *lb ; } if( lowbound > *ub ){ lowbound = *ub ; } hibound = pad->upperbound ; if( hibound < *lb ){ hibound = *lb ; } if( hibound > *ub ){ hibound = *ub ; } } else { /* this pad is not fixed use the given ub and lb */ lowbound = *lb ; hibound = *ub ; } } else { if( pad->fixed ){ /* the padgroup bounds have not been fixed */ /* just take the pad's restricted position */ lowbound = pad->lowerbound; hibound = pad->upperbound; *spacing_restricted = TRUE ; } } if( *spacing_restricted ){ *lowpos = (INT) ( lowbound * (DOUBLE)perdimG[side%2] ) ; *lowpos += coreG[side%2][MINI] ; *uppos = (INT) ( hibound * (DOUBLE)perdimG[side%2] ) ; *uppos += coreG[side%2][MINI] ; } else { *lowpos = -1 ; *uppos = PINFINITY ; } /* **** END spacing restriction calculations *** */ /* return low bound */ *lb = lowbound ; *ub = hibound ; } /* end calc_constraints */ /* ***************************************************************** */ static place_variable( first, numpads, side ) INT first, numpads, side ; { INT pad ; /* counter */ INT left_edge ; /* current left edge of pad */ INT right_edge ; /* current right edge of pad */ INT half_length ; /* half the span of a pad */ INT valid_left_edge ;/* this position is open for the pad leftedge*/ INT valid_right_edge;/* this position is open for the pad rightedge*/ PADBOXPTR padptr ; /* current pad info */ valid_left_edge = 0 ; for( pad = 0; pad < numpads; pad++ ){ padptr = placearrayG[first + pad ] ; /* now find the left edge of the current pad */ half_length = padptr->length / 2 ; left_edge = padptr->position - half_length ; valid_left_edge = MAX( valid_left_edge, padptr->lo_pos ) ; if( left_edge < valid_left_edge ){ /* need to remove overlap */ /* so left edge of pad becomes valid_left_edge */ left_edge = valid_left_edge ; /* calculate new padptr position */ padptr->position = valid_left_edge + half_length ; } /* now calculate the new valid left edge */ valid_left_edge = left_edge + padptr->length + min_pad_spacingG ; } D( "placepads/after_left_edge", print_pads( "pads after left_edge\n", placearrayG, numpadsG ) ; ) ; valid_right_edge = coreG[side%2][MAXI] ; /* now condense pads if they exceed the length of the side */ for( pad = numpads-1; pad >= 0; pad-- ){ padptr = placearrayG[first + pad] ; /* now find the left edge of the current pad */ half_length = padptr->length / 2 ; half_length = padptr->length - half_length ; right_edge = padptr->position + half_length ; valid_right_edge = MIN( valid_right_edge, padptr->hi_pos ) ; if( right_edge > valid_right_edge ){ /* need to remove overlap */ /* so left edge of pad becomes valid_left_edge */ right_edge = valid_right_edge ; /* calculate new padptr position */ padptr->position = valid_right_edge - half_length ; } else { break ; } /* now calculate the new valid right edge */ valid_right_edge = right_edge - padptr->length - min_pad_spacingG ; } } /* end place_variable */ dimension_pads() { INT i ; /* pad counter */ PADBOXPTR pad ; /* current pad */ PINBOXPTR pin ; /* current pin */ CELLBOXPTR cptr ; /* current cell */ for( i = 1 ; i <= numpadsG; i++ ) { pad = padarrayG[i]; cptr = cellarrayG[pad->cellnum] ; switch( pad->padside) { case L: cptr->xcenter = coreG[X][MINI] - pad->height / 2 ; cptr->ycenter = pad->position ; break; case T: cptr->xcenter = pad->position ; cptr->ycenter = coreG[Y][MAXI] + pad->height / 2 ; break; case R: cptr->xcenter = coreG[X][MAXI] + pad->height / 2 ; cptr->ycenter = pad->position ; break; case B: cptr->xcenter = pad->position ; cptr->ycenter = coreG[Y][MINI] - pad->height / 2 ; break; } /* end switch on side */ /* now update the pins */ for( pin = cptr->pinptr; pin ; pin = pin->nextpin ){ REL_POST( cptr->orient, pin->xpos, pin->ypos, /* result */ pin->txpos, pin->typos, /* cell relative */ cptr->xcenter, cptr->ycenter ) ; /* cell center */ } } } /* dimension_pads */ /* ***************************************************************** */ orient_pads() { INT i ; /* counter */ PADBOXPTR pad ; /* current pad info */ CELLBOXPTR cptr ; /* current cell */ for( i = 1; i <= numpadsG; i++ ){ pad = placearrayG[i]; cptr = cellarrayG[pad->cellnum] ; switch( pad->padside ){ case L: /* rotate 270 | -90 */ cptr->orient = 7 ; cptr->ycenter = cptr->xcenter; break; case T: /* rotate180 */ cptr->orient = 3 ; break; case R: /* rotate90 */ cptr->orient = 6 ; cptr->ycenter = cptr->xcenter; break; case B: cptr->orient = 0 ; break; default: OUT1("\nNON-PADS or PAD w/o side not rotated "); break; } } } /* end orient_pads */ /* ***************************************************************** */ graywolf-0.1.4+20170307gite1bf319/src/twmc/custom.h000066400000000000000000000540731305746555600212210ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: custom.h CONTENTS: definitions for globals structures and variables file organized - defines, typedefs, globals. DATE: Jan 29, 1988 REVISIONS: Feb 13, 1988 - changed numBinsX & numBinsY -> maxBinX and maxBinY. Also redefine LOCBOX to be termbox. Feb 19, 1988 - changed aveChanWid to DOUBLE from int. Oct 21, 1988 - remove Hweight and Vweight from DIMBOX. Oct 26, 1988 - updated FIXEDBOX for neighborhoods. changed PATHNETPTR to generic pointer and added groupbox to cell data structure. Dec 3, 1988 - added PSETPTR record for timing driven code - add list of paths to cell record. Jan 20, 1989 - added softPinArrayG for softcells. Feb 26, 1989 - added G suffix for all global variables. - changed SetBin to SETBIN so looks like macro. - added CUSTOM_H compile switch. Mar 01, 1989 - remove netctr variable. - made iteration a global variable. Mar 02, 1989 - moved start_overlap, end_overlap, etc. to penalties.c Mar 07, 1989 - added numinstancesG to list of cell info. Mar 12, 1989 - added group_nested field to CELLBOX so that groups can be hierarchical. Mar 16, 1989 - rewrote entire netlist data structures. Deleted unnecessary data structures. Mar 30, 1989 - changed tile datastructure and MOVEBOX. May 18, 1989 - added layer and HOWMANYORIENTs. May 18, 1989 - removed extraneous variables. Added pad control variables and defines. Jul 19, 1989 - added numstdcellG global for avoiding work. Oct 18, 1989 - removed pitch and track_spacing. Added two wire factors - one for each direction. Mar 28, 1990 - major rewrite of softcell code. Apr 11, 1990 - changed group record. Nov 23, 1990 - changed mean_cellAreaG and dev_cellareaG to doubles. Sun Dec 16 00:27:36 EST 1990 - modified to handle analog information. Thu Jan 17 00:45:41 PST 1991 - added numpins to VERTBOX. Mon Feb 4 02:03:45 EST 1991 - added new definitions to make a correct softpin placer. Wed Feb 13 23:34:29 EST 1991 - rewrote pad code. Sat Feb 23 00:19:51 EST 1991 - finalized pad data structure to be like placepad algorithm. Thu Apr 18 01:30:38 EDT 1991 - got rid of grid variables now use library function. Sun May 5 14:22:05 EDT 1991 - now user can set origin. Mon May 6 02:34:54 EDT 1991 - added lo and hi pos to make pin placement better. Thu Aug 22 22:08:22 CDT 1991 - added unique_classG to fix problem with fixed cells. ----------------------------------------------------------------- */ /* ***************************************************************** "@(#) custom.h (Yale) version 3.15 8/22/91" ***************************************************************** */ #ifndef CUSTOM_H #define CUSTOM_H #include #include #ifndef CUSTOM_DEFS #define EXTERN extern #else #define EXTERN #endif /* ----------------------------------------------------------------- DEFINE STATEMENTS FOR PLACEMENT STAGE ----------------------------------------------------------------- */ #define SETBINX(x) (( (TrybinG=((x)-binXOffstG)/binWidthXG)<0 ) ? 0 : \ ((TrybinG>maxBinXG) ? maxBinXG : TrybinG )) #define SETBINY(x) (( (TrybinG=((x)-binYOffstG)/binWidthYG)<0 ) ? 0 : \ ((TrybinG>maxBinYG) ? maxBinYG : TrybinG )) #define PICK_INT(l,u) (((l)<(u)) ? ((RAND % ((u)-(l)+1))+(l)) : (l)) #define deltaX 2 #define deltaY 2 #define EXPCELLPERBIN 5 /* we expect no more than 5 cells in a bin */ #define HOWMANYORIENT 8 /* control for pad spacing */ #define UNIFORM_PADS 0 #define VARIABLE_PADS 1 #define ABUT_PADS 2 #define EXACT_PADS 3 /* ----------------------------------------------------------------- STUCTURE AND TYPEDEFS FOR PLACEMENT STAGE ----------------------------------------------------------------- */ typedef struct glistbox { /* generic list */ union { INT net ; /* make code easier to read */ INT path ; INT cell ; INT side ; } p ; struct glistbox *next ; } GLISTBOX , *GLISTPTR ; typedef struct movebox { INT xcenter ; INT ycenter ; INT r ; INT l ; INT t ; INT b ; DOUBLE rw ; /* the tile weights */ DOUBLE lw ; DOUBLE tw ; DOUBLE bw ; INT binR ; INT binL ; INT binT ; INT binB ; INT cell ; INT orient ; INT numtiles ; BOOL loaded_previously ; } MOVEBOX, *MOVEBOXPTR ; typedef struct eq_pinbox { /* for hard equiv pins and addequiv pins */ char *pinname ; /* equivalent pin name */ INT *restrict1 ; /* softpin is restricted to these sides */ INT *txpos ; /* array of cell instance xpos. cell rel. */ INT *typos ; /* array of cell instance ypos. cell rel. */ INT layer ; /* layer of the equivalent pin */ struct eq_pinbox *next; /* pointer to next equivalent pin */ } EQUIVBOX, *EQUIVPTR ; typedef struct sbox { struct pinbox **children; /* array of the pin's children */ struct pinbox *parent; /* pointer back to softpin pinbox */ INT *restrict1 ; /* softpin is restricted to these sides */ INT hierarchy ; /* type of pin root leaf, subroot etc */ INT side ; /* current side of the softpin */ BOOL permute ; /* true if rank ordered */ BOOL ordered ; /* true if ordered in a group */ BOOL fixed ; /* true if rank is fixed */ INT lo_pos ; /* low valid position */ INT hi_pos ; /* hi valid position */ FLOAT lowerbound ; /* bounds of a pingroup */ FLOAT upperbound ; /* upper bound of a pin group */ } SOFTBOX, *SOFTBOXPTR ; typedef struct pinbox { struct pinbox *next ; /* next pin for this net */ struct pinbox *nextpin ; /* next pin for this cell */ SOFTBOXPTR softinfo ; /* soft pin info if appl. otherwise NULL */ char *pinname ; /* pin record */ INT pin ; /* global index of pin */ INT net ; /* global index of net */ INT cell ; /* global index of cell */ INT xpos ; /* global x position */ INT ypos ; /* global y position */ INT instance ; /* current cell instance */ INT txpos_new ; /* proposed cell relative position of pin */ INT typos_new ; /* proposed cell relative position of pin */ INT txpos ; /* current cell relative position of pin */ INT typos ; /* current cell relative position of pin */ INT *txpos_orig ; /* orig array of cell inst xpos. cell rel.*/ INT *typos_orig ; /* orig array of cell inst ypos. cell rel.*/ INT newx ; /* scratch for determining new global xpos*/ INT newy ; /* scratch for determining new global ypos*/ INT flag ; INT skip ; INT layer ; /* layer information */ INT type ; /* softpin, hardpin, equiv pin */ FLOAT *timing ; /* array of timing information for a pin */ SOFTBOXPTR *soft_inst ; /* array of spin info if appl. o.w. NULL */ EQUIVPTR eqptr ; /* list of equivalent pins */ ANALOGPTR analog ; /* analog information if given */ ANALOGPTR *ainst ; /* analog instance information */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Note: For all pins t?pos_orig is what the user gave us. We need to use original position to calculate new pin position for aspect ratio moves for softcells and for outputing pin information to global router for hard pins. T?pos is the current x and y positions of the pin and for hard cells it is the average of all the equivs for a pin and for softcells it is the current position due to the current aspect ratio. For softcell, softinfo is valid otherwise it is NULL. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ } *PINBOXPTR , PINBOX ; typedef struct tilebox { DOUBLE lweight ; DOUBLE rweight ; DOUBLE bweight ; DOUBLE tweight ; INT left ; /* current tile sides */ INT right ; INT bottom ; INT top ; INT orig_left ;/* original tile sides specified by user */ INT orig_right ;/* for hard cell left = orig_left, that is */ INT orig_bottom ;/* sides don't change throughout run. But for */ INT orig_top ;/* soft cells use this to calculate current side*/ struct tilebox *next ; /* next tile in list */ } *TILEBOXPTR , TILEBOX ; typedef struct psidebox { INT length ; DOUBLE pincount; INT vertical ; INT position ; } PSIDEBOX ; typedef struct { INT r ; INT l ; INT t ; INT b ; } BOUNBOX, *BOUNBOXPTR ; typedef struct { INT *x ; /* the current positions of vertices */ INT *x_orig ; /* the original positions of vertices */ INT *x_new ; /* the proposed positions of the vertices */ INT *y ; /* the current positions of vertices */ INT *y_orig ; /* the original positions of vertices */ INT *y_new ; /* the proposed positions of the vertices */ FLOAT *numpins; /* number of pins on each side */ } VERTBOX, *VERTBOXPTR ; typedef struct { INT fixedType ; /* POINT, NEIGHBORHOOD, GROUP, FIXEDGROUP */ INT xcenter ; INT ycenter ; BOOL leftNotRight ; BOOL bottomNotTop ; INT xloc1 ; /* for fixing cell within a neighborhood */ INT yloc1 ; /* remembers relative position to core */ INT xloc2 ; INT yloc2 ; BOOL leftNotRight2 ; BOOL bottomNotTop2 ; INT x1, y1 ; /* global position */ INT x2, y2 ; INT xspan ; /* for speed of calculation */ INT yspan ; } FIXEDBOX, *FIXEDBOXPTR ; typedef struct pad_rec { INT cellnum ; /* index in carray */ INT length ; INT height ; INT position ; /* linear placement position for a side */ INT tiebreak ; /* ideal location to place the pad */ INT *children ; /* added for pad code */ INT padside ; /* current side */ INT padtype ; /* type of pad - pad or padgroup */ INT hierarchy ; /* type of pad - root, lead, pad, etc */ INT lo_pos ; /* low valid position -1 if every valid */ INT hi_pos ; /* hi valid position PINFINITY if valid */ BOOL ordered ; /* whether a pad is ordered in a group */ BOOL permute ; /* whether rank is to be enforced */ BOOL fixed ; /* whether pad is fixed on a side */ BOOL valid_side[5] ; /* valid side a pad may be placed */ DOUBLE lowerbound ; DOUBLE upperbound ; } PADBOX, *PADBOXPTR ; typedef struct { /* keeps track of group information */ FIXEDBOXPTR fixed ; /* the groups neighborhood */ GLISTPTR cells ; /* the cells of a group */ } GROUPBOX, *GROUPBOXPTR ; typedef struct { char **name_inst ; /* array of names for each instance */ INT numinstances ; /* number of instances for this cell */ INT *numtile_inst ; /* number of tiles for each instance */ INT *numsides ; /* array of number of sides for inst. */ TILEBOXPTR *tile_inst ; /* array of tile lists for each inst */ BOUNBOXPTR **bounBox ; /* the bbox in each view 0 each inst */ VERTBOXPTR *vert_inst ; /* array of vertices of cell orient 0 */ } INSTBOX, *INSTBOXPTR ; typedef struct cellbox { char *cname ; INT cellnum ; INT class ; INT xcenter ; INT ycenter ; INT orientList[9] ; INT orient ; INT numpins ; /* number of pins for this cell */ INT numtiles ; /* number of tiles in current instance */ INT numsides ; /* number of sides for the current inst */ INT cur_inst ; /* current instance of cell [0,numinst] */ BOOL softflag ; /* TRUE if it is a soft cell */ CELLTYPE celltype ; /* custom, soft , pad etc */ GLISTPTR paths ; /* paths of a cell */ GLISTPTR nets ; /* all the nets that a cell is on */ FIXEDBOXPTR fixed ; /* cell can't move if non NULL */ INSTBOXPTR instptr ; /* valid if cell has instances */ PADBOXPTR padptr ; /* if pad - pad attributes */ GROUPBOXPTR group ; /* whether cell belongs to a group */ BOOL group_nested ; /* shows whether this cell is nested */ DOUBLE orig_aspect ; /* original aspect ratio */ DOUBLE aspect ; /* current aspect ratio */ DOUBLE aspUB ; /* aspect ratio upper bound */ DOUBLE aspLB ; /* aspect ration lower bound */ TILEBOXPTR tiles ; /* current tiles of a cell-head of list */ VERTBOXPTR vertices ; /* array of vertices of cell orient 0 */ BOOL boun_valid ; /* boundary calc. - use delayed calc. */ BOUNBOXPTR *bounBox ; /* the bounding box excluding routing */ PINBOXPTR pinptr ; /* all the pins of a cell */ PINBOXPTR *softpins ; /* all the pins including softpingroups */ } *CELLBOXPTR , CELLBOX ; typedef struct netbox { char *nname ; /* net name */ PINBOXPTR pins ; /* pins of this net */ GLISTPTR paths ; /* paths which this net belongs */ INT skip ; INT xmin ; INT newxmin ; INT xmax ; INT newxmax ; INT ymin ; INT nflag ; INT newymin ; INT ymax ; INT newymax ; INT numpins ; INT Bnum ; /* no. of pins on the bottom edge of bb */ INT Lnum ; /* no. of pins on the left edge of bb */ INT Rnum ; /* no. of pins on the right edge of bb */ INT Tnum ; /* no. of pins on the top edge of bb */ INT newBnum ; /* no. of pins on the bottom edge of bb */ INT newLnum ; /* no. of pins on the left edge of bb */ INT newRnum ; /* no. of pins on the right edge of bb */ INT newTnum ; /* no. of pins on the top edge of bb */ INT newhalfPx ; /* new half perimeter bounding box for x */ INT newhalfPy ; /* new half perimeter bounding box for y */ INT halfPx ; /* current half perimeter bounding box for x */ INT halfPy ; /* current half perimeter bounding box for y */ FLOAT driveFactor ; /* driver strength of this net */ FLOAT max_driver ; /* largest driver on this net */ FLOAT min_driver ; /* smallest driver on this net */ ANETPTR analog_info ; /* for analog nets */ } *NETBOXPTR , NETBOX ; typedef struct kbox { INT cap ; INT HV ; INT sp ; INT x ; INT y ; } KBOX , *KBOXPTR ; typedef struct pathbox { INT lo_path_len ; /* lower bound on the calculated half perim */ INT hi_path_len ; /* upper bound on the calculated half perim */ INT new_lo_path_len ; /* new low path */ INT new_hi_path_len ; /* new upper path */ INT priority ; INT upper_bound ; INT lower_bound ; GLISTPTR nets ; struct pathbox *next ; /* build a list first then array for speed */ } PATHBOX , *PATHPTR ; typedef struct binbox { INT left ; INT right ; INT top ; INT bottom ; INT penalty ; INT nupenalty ; INT *cells ; /* array of cells in bin */ INT space ; /* size of binbox->cells array */ } BINBOX , *BINBOXPTR ; typedef struct psetrec { INT member; /* integer for determining membership */ INT path ; /* data */ struct psetrec *next ; } PSETBOX, *PSETPTR ; /* path set record */ /* ---------------------------------------------------------- The global variable definitions ---------------------------------------------------------- */ EXTERN CELLBOXPTR *cellarrayG ; EXTERN CELLBOXPTR *activeCellarrayG ; /* cells that are active */ EXTERN CELLBOXPTR *softPinArrayG ; /* softcells that have pins */ EXTERN NETBOXPTR *netarrayG ; /* array of nets */ EXTERN PATHPTR *patharrayG ; /* array of paths */ EXTERN PINBOXPTR *termarrayG ; /* array of pins */ EXTERN BINBOXPTR **binptrG ; /* overlap data structure */ EXTERN INT **net_cap_matchG ; /* set of match nets */ EXTERN INT **net_res_matchG ; /* set of match nets */ /* ---------------------------------------------------------- The global variable definitions for Jimmy's controller. ---------------------------------------------------------- */ EXTERN INT d_costG; EXTERN DOUBLE init_accG; EXTERN DOUBLE ratioG ; /* ---------------------------------------------------------- global definitions for overlap calculations ---------------------------------------------------------- */ /* move box array */ EXTERN MOVEBOXPTR *old_aposG, *new_aposG, *old_bposG, *new_bposG ; /* first element of move box array */ EXTERN MOVEBOXPTR old_apos0G, new_apos0G, old_bpos0G, new_bpos0G ; EXTERN BINBOXPTR newbptrG; /* *** bin cell ptr *** */ EXTERN INT *newCellListG ; /* *** bin cell list *** */ EXTERN INT TrybinG ; /* used in setBin calculations */ /* ---------------------------------------------------------- global definitions for configuration calculations ---------------------------------------------------------- */ EXTERN INT bdxlengthG , bdylengthG ; EXTERN INT blocklG , blockrG , blocktG , blockbG ; EXTERN INT blockmxG , blockmyG ; EXTERN INT halfXspanG , halfYspanG ; EXTERN DOUBLE chipaspectG ; /* ---------------------------------------------------------- cells are arranged in cellarray in the following fashion: 1. - core cells - custom and softcells 1..numcells. 1a.- core cells may have instances. so add numinstances to all below. 2. - super cells - numcells+1..numcells+numsupercells. 3. - pad cells - numcells+numsupercells+11.. numcells+numsupercells+numpads. 4 - pad groups - numcells+numsupercells+numpads+1.. numcells+numpads+numpadgroups 5. - padmacros - always four-for channel graph generator. see outgeo.c. We have the following definitions to simplify region indexes: endsuper = numcells + numsupercells + numinstances ; endpads = numcells+numsupercells+numpads ; endpadgrps = numcells+numsupercells+numpads+numpadgroups ; totalcells = numcells+numsupercells+numpads+numpadgroups+NUMPADMACROS ; ---------------------------------------------------------- */ EXTERN INT numcellsG ; EXTERN INT numpadsG ; EXTERN INT totalpadsG ; EXTERN INT numsoftG ; EXTERN INT numstdcellG ; EXTERN INT numpadgroupsG ; EXTERN INT numinstancesG ; EXTERN INT numsupercellsG ; EXTERN INT numpathsG ; EXTERN INT endpadsG ; EXTERN INT endpadgrpsG ; EXTERN INT endsuperG ; EXTERN INT totalcellsG; EXTERN INT activecellsG; /* number of active cells not fixed or merged */ EXTERN INT numnetsG ; EXTERN INT numpinsG ; EXTERN INT maxBinXG ; EXTERN INT maxBinYG ; EXTERN INT binWidthXG ; EXTERN INT binWidthYG ; EXTERN INT binXOffstG ; EXTERN INT binYOffstG ; EXTERN INT maxWeightG ; EXTERN INT baseWeightG; EXTERN DOUBLE mean_cellAreaG ; EXTERN DOUBLE dev_cellAreaG ; EXTERN DOUBLE slopeXG ; EXTERN DOUBLE slopeYG ; EXTERN DOUBLE basefactorG; EXTERN DOUBLE aveChanWidG; EXTERN DOUBLE wireFactorXG; EXTERN DOUBLE wireFactorYG; /* ---------------------------------------------------------- global definitions for cost function ---------------------------------------------------------- */ EXTERN INT penaltyG ; EXTERN INT binpenalG ; EXTERN INT funccostG ; EXTERN INT offsetG ; EXTERN INT timingcostG ; EXTERN INT timingpenalG ; EXTERN DOUBLE coreFactorG ; EXTERN DOUBLE lapFactorG ; EXTERN DOUBLE timeFactorG ; EXTERN DOUBLE vertical_wire_weightG ; EXTERN DOUBLE vertical_path_weightG ; /* annealing stuff */ EXTERN DOUBLE TG ; EXTERN FILE *fpoG ; EXTERN INT randVarG ; EXTERN INT attmaxG ; EXTERN INT iterationG ; EXTERN DOUBLE pinsPerLenG ; EXTERN INT layersFactorG ; EXTERN INT unique_classG ; /* ---------------------------------------------------------- global definitions for calculated statistics ---------------------------------------------------------- */ EXTERN INT perimG ; EXTERN INT totChanLenG ; EXTERN INT totNetLenG ; EXTERN DOUBLE aveCellSideG ; EXTERN DOUBLE expandExtraG ; EXTERN INT flipsG ; EXTERN DOUBLE avg_funcG , avgsG ; EXTERN INT iwireG, iwirexG , iwireyG , icostG ; EXTERN INT fwireG, fwirexG , fwireyG , fcostG ; /* control for pad code */ EXTERN INT padspacingG ; /* may be UNIFORM, VARIABLE, or ABUT */ EXTERN BOOL contiguousG ; EXTERN BOOL external_pad_programG ; /* TRUE for calling placepads */ EXTERN INT min_pad_spacingG ; EXTERN INT coreG[2][2] ; EXTERN INT perdimG[2] ; EXTERN PADBOXPTR *padarrayG ; /* array of all the pads and padgroups */ EXTERN PADBOXPTR *sortarrayG ; /* the sorted array of pads */ EXTERN PADBOXPTR *placearrayG ; /* array where the pads will be placed */ /* control gridding of cells */ EXTERN BOOL gridGivenG ; EXTERN BOOL gridCellsG ; EXTERN BOOL coreGivenG ; EXTERN INT x_originG, y_originG ; #undef EXTERN #endif /* CUSTOM_H */ graywolf-0.1.4+20170307gite1bf319/src/twmc/date.h000066400000000000000000000001071305746555600206110ustar00rootroot00000000000000#define DATE "@(#) Yale compilation date:Mon May 25 21:18:34 EDT 1992" graywolf-0.1.4+20170307gite1bf319/src/twmc/debug.c000066400000000000000000000317611305746555600207670ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: debug.c DESCRIPTION:debug routines CONTENTS: dbins( ) DATE: Feb 13, 1988 REVISIONS: Jan 29, 1989 - changed msg to YmsgG. Feb 01, 1989 - move all graphic routines to graphics.c Mar 30, 1989 - changed tile datastructure. Apr 23, 1990 - moved graph routines to library. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) debug.c version 3.3 9/5/90" ; #endif #include /* #include */ #include #include #include #define CELLEST 0 #define CELLBORDER 1 #define TRUECELL 2 /* ***************************************************************** DUMP CELL BIN LISTS */ dcellList( cell ) INT cell ; { INT binX, binY, limit ; INT *cellList, i ; BINBOXPTR bptr ; printf("Dumping bin cell list...\n") ; binX = SETBINX( cellarrayG[cell]->xcenter ) ; binY = SETBINY( cellarrayG[cell]->ycenter ) ; bptr = binptrG[binX][binY] ; cellList = bptr->cells ; printf("bin:(%2d,%2d) ",binX,binY ); printf("cellList: %0x ", cellList ); printf("numcells: %d ", cellList[0] ); printf("space: %d\n", bptr->space ); printf("Cells in bin: \n "); limit = cellList[0] ; for( i=1;i<=limit;i++ ){ printf("%d ", cellList[i] ) ; if( ( i % 10 ) == 0 ){ printf("\n") ; } } printf("\n") ; } /* end dbins */ /* ***************************************************************** CHECK CELL BIN LIST FOR CORRECT NUMBER */ BOOL checkbinList() { INT x, y ; INT *cellList ; BINBOXPTR bptr ; CELLBOXPTR ptr ; INT numcells_in_bin = 0 ; INT i ; INT cell ; INT celltype ; BOOL found ; for( y=0;y<=maxBinYG;y++ ){ for( x=0;x<=maxBinXG;x++ ){ bptr = binptrG[x][y] ; cellList = bptr->cells ; numcells_in_bin += ABS( cellList[0] ) ; } } if( numcells_in_bin != numcellsG ){ return(FALSE) ; } /* now test to see if all the cells are in their correct bins */ for( cell = 1; cell<= endsuperG; cell++ ){ ptr = cellarrayG[cell] ; celltype = ptr->celltype ; if( celltype != CUSTOMCELLTYPE && celltype != SOFTCELLTYPE ){ continue ; } x = SETBINX( ptr->xcenter ) ; y = SETBINY( ptr->ycenter ) ; bptr = binptrG[x][y] ; cellList = bptr->cells ; found = FALSE ; for( i = 1; i <= cellList[0] ; i++ ){ if( cellList[i] == ptr->cellnum ){ found = TRUE ; break ; } } if( !found ){ sprintf( YmsgG, "Problem with cell:%d bins\n" ) ; M( ERRMSG, "checkbinList", YmsgG ) ; return(FALSE) ; } } return( TRUE ) ; } /* end checkbinList */ /* ***************************************************************** DUMP CELL BIN LISTS */ dbinList( flag ) INT flag ; { INT x, y, limit ; INT *cellList, i ; BINBOXPTR bptr ; printf("Dumping bin cell list...\n") ; for( y=0;y<=maxBinYG;y++ ){ for( x=0;x<=maxBinXG;x++ ){ bptr = binptrG[x][y] ; cellList = bptr->cells ; if( flag ){ /* prINT all bins */ printf("bin:(%2d,%2d) ",x,y ); printf("cellList: %0x ", cellList ); printf("numcells: %d ", cellList[0] ); printf("space: %d ", bptr->space ); printf("cells: "); limit = cellList[0] ; for( i=1;i<=limit;i++ ){ printf("%2d ", cellList[i] ) ; if( ( i % 10 ) == 0 ){ printf("\n") ; } } printf("\n") ; } else { /* print non empty bins */ if( cellList[0] ){ printf("bin:(%2d,%2d) ",x,y ); printf("cellList: %0x ", cellList ); printf("numcells: %d ", cellList[0] ); printf("space: %d ", bptr->space ); printf("cells: "); limit = cellList[0] ; for( i=1;i<=limit;i++ ){ printf("%2d ", cellList[i] ) ; if( ( i % 10 ) == 0 ){ printf("\n") ; } } printf("\n") ; } } } } } /* end dbins */ /* ***************************************************************** DUMP OVERLAP BIN STRUCTURE */ dbins( flag ) BOOL flag ; { INT x, y ; INT cost ; BINBOXPTR bptr; if( flag ){ printf("Dumping bins...\n") ; printf(" x y left right bottom top pen nupen \n") ; for( y=0;y<=maxBinYG;y++ ){ for( x=0;x<=maxBinXG;x++ ){ bptr = binptrG[x][y] ; printf("%2d %2d %11d %10d %11d %10d:%6d %6d\n", x, y, bptr->left, bptr->right, bptr->bottom, bptr->top, bptr->penalty, bptr->nupenalty ) ; } } } /* now calculate the penalties */ cost = 0 ; for( x= 0 ; x <= maxBinXG; x++ ) { for( y = 0 ; y <= maxBinYG; y++ ) { bptr = binptrG[x][y] ; cost += ABS( bptr->penalty ) ; } } printf("cost = %d\n", cost ) ; cost = 0 ; for( x= 0 ; x <= maxBinXG; x++ ) { for( y = 0 ; y <= maxBinYG; y++ ) { bptr = binptrG[x][y] ; cost += ABS( bptr->nupenalty ) ; } } printf("nucost = %d\n", cost ) ; } /* end dbins */ /* ***************************************************************** DUMP MOVEBOX STRUCTURE */ dmove() { INT i; printf("Dumping movebox records...") ; for( i=0 ; i<= 1; i++ ){ printf("\ntileptr %d:\n",i ) ; printf(" old_apos0 new_apos0 old_bpos0 new_bpos0\n") ; printf("xcenter %6d %6d %6d %6d\n", old_aposG[i]->xcenter,new_aposG[i]->xcenter,old_bposG[i]->xcenter,new_bposG[i]->xcenter) ; printf("ycenter %6d %6d %6d %6d\n", old_aposG[i]->ycenter,new_aposG[i]->ycenter,old_bposG[i]->ycenter,new_bposG[i]->ycenter) ; printf("cell %6d %6d %6d %6d\n", old_aposG[i]->cell,new_aposG[i]->cell,old_bposG[i]->cell,new_bposG[i]->cell) ; printf("orient %6d %6d %6d %6d\n", old_aposG[i]->orient,new_aposG[i]->orient,old_bposG[i]->orient,new_bposG[i]->orient) ; printf("aspChange %6d %6d %6d %6d\n", old_aposG[i]->loaded_previously,new_aposG[i]->loaded_previously, old_bposG[i]->loaded_previously,new_bposG[i]->loaded_previously) ; printf("l %6d %6d %6d %6d\n", old_aposG[i]->l,new_aposG[i]->l,old_bposG[i]->l,new_bposG[i]->l) ; printf("r %6d %6d %6d %6d\n", old_aposG[i]->r,new_aposG[i]->r,old_bposG[i]->r,new_bposG[i]->r) ; printf("b %6d %6d %6d %6d\n", old_aposG[i]->b,new_aposG[i]->b,old_bposG[i]->b,new_bposG[i]->b) ; printf("t %6d %6d %6d %6d\n", old_aposG[i]->t,new_aposG[i]->t,old_bposG[i]->t,new_bposG[i]->t) ; printf("binL %6d %6d %6d %6d\n", old_aposG[i]->binL,new_aposG[i]->binL,old_bposG[i]->binL,new_bposG[i]->binL) ; printf("binR %6d %6d %6d %6d\n", old_aposG[i]->binR,new_aposG[i]->binR,old_bposG[i]->binR,new_bposG[i]->binR) ; printf("binB %6d %6d %6d %6d\n", old_aposG[i]->binB,new_aposG[i]->binB,old_bposG[i]->binB,new_bposG[i]->binB) ; printf("binT %6d %6d %6d %6d\n", old_aposG[i]->binT,new_aposG[i]->binT,old_bposG[i]->binT,new_bposG[i]->binT) ; } /* end for loop */ } /* end dmove */ /* ***************************************************************** DUMP TILEPTR STRUCTURE */ dtile(cell) INT cell ; { CELLBOXPTR ptr ; TILEBOXPTR t ; printf("Dumping tileptr records for cell %d...", cell ) ; ptr = cellarrayG[cell] ; for( t=ptr->tiles;t;t=t->next ){ printf(" left right bottom top\n") ; printf("%6d %6d %6d %6d\n", t->left,t->right,t->bottom,t->top) ; } /* end for loop */ } /* end dtile */ /* ***************************************************************** RELOAD BINS same as loadbins make call because of dbx bug. Also reinitializes nupenalty field */ dloadbins( flag ) BOOL flag ; { INT x, y ; dbins( TRUE ) ; loadbins( flag ) ; for( x = 0; x<= maxBinXG; x++){ for( y = 0; y<= maxBinYG; y++){ binptrG[x][y]->nupenalty = 0 ; } } dbins( TRUE ) ; } /* ***************************************************************** DUMP CURRENT CELL AREAS */ dcellareas() { printf("Area without routing area:%d\n",calc_cellareas(FALSE) ) ; printf("Area with estimated routing area:%d\n",calc_cellareas(TRUE) ) ; } /* end dcellareas */ #ifdef NEEDED DORIENT( cell ) INT cell ; { FILE *fp ; CELLBOXPTR cptr ; TILEBOXPTR tileptr ; TERMBOXPTR termptr ; INT i ; INT x ; INT y ; INT orient ; INT newx, newy ; INT x0, x1, y0, y1 ; char filename[LRECL] ; char label[LRECL] ; system("rm -f DATA/*" ) ; for( i= 0; i<=7; i++ ){ cptr = cellarrayG[cell] ; cptr->orient = i ; /* dump force results serially from processors [0][k] */ /* first dump the objects */ sprintf(filename,"%s/cell.file.%d",dataDir,k) ; if( fp = TWOPEN(filename,"w", ABORT )){ x = cptr->xcenter ; y = cptr->ycenter ; orient = cptr->orient ; /* name the cell and change colors for pretty picture */ sprintf(label,"C%d orient:%d",i,orient) ; for( tileptr=cptr->tiles;tileptr;tileptr=tileptr->nexttile ) { /* first get orientation from orientation */ /* add cell offset */ x0 = x + tileptr->left ; x1 = x + tileptr->right ; y0 = y + tileptr->bottom; y1 = y + tileptr->top ; fprintf(fp,"%d, %d, %d, %d, color: %s, label: %s\n", x0,y0,x1,y1, ROWCOLOR, label ) ; } /* end for loop */ } else { printf("WARNING[dumpMC]:could not open %s - dump aborted.\n", filename) ; return ; } fclose(fp) ; /* now build net file */ /* nets are the interconnections between the cells */ sprintf(filename,"%s/net.file.%d",dataDir,k ) ; if( fp = fopen(filename,"w" )){ fclose(fp) ; } /* now build pin file */ /* pins are the terminal points on a net */ sprintf(filename,"%s/pin.file.%d",dataDir,k ) ; if( fp = fopen(filename,"w" )){ /* get target position from Rotational record */ x = cptr->xcenter ; y = cptr->ycenter ; termptr = cptr->termptr ; for( ; termptr != TERMNULL ; termptr = termptr->nextterm ) { switch( orient ){ case 0: newx = x + termptr->xpos ; newy = y + termptr->ypos ; break ; case 1: newx = x + termptr->xpos ; newy = y - termptr->ypos ; break ; case 2: newx = x - termptr->xpos ; newy = y + termptr->ypos ; break ; case 3: newx = x - termptr->xpos ; newy = y - termptr->ypos ; break ; case 4: newx = x + termptr->ypos ; newy = y + termptr->xpos ; break ; case 5: newx = x - termptr->ypos ; newy = y - termptr->xpos ; break ; case 6: newx = x - termptr->ypos ; newy = y + termptr->xpos ; break ; case 7: newx = x + termptr->ypos ; newy = y - termptr->xpos ; break ; } fprintf(fp,"%d, %d, %d, %d, %d, color: %s\n", i,newx-1,newy-1,newx+1,newy+1, PINCOLOR ) ; } } else { printf("ERROR[dumpMC]: could not open %s\n",filename) ; return ; } fclose(fp) ; /* increment k afterwards */ k++ ; } } /* end dumpForce */ dsoftpins( cell ) INT cell ; { INT pin ; PINBOXPTR *sarray ; /* array of just the soft pins of a cell */ sarray = cellarrayG[cell]->softpins ; for( pin = 1; pin <= cellarrayG[cell]->numsoftpins;pin++ ) { fprintf( stderr, " %d ", sarray[pin]->softinfo->site ); if( pin % 15 == 0 ){ fprintf( stderr, "\n" ) ; } } fprintf( stderr, "\n" ) ; } #endif graywolf-0.1.4+20170307gite1bf319/src/twmc/dens.h000066400000000000000000000021621305746555600206300ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: dens.h CONTENTS: definitions for cell routing area tiles. DATE: Jan 20, 1990 REVISIONS: Thu Jan 17 00:46:38 PST 1991 - added side to RTILEBOX and added the TILE macro definitions. Wed May 1 19:16:12 EDT 1991 - added switchbox definition. ----------------------------------------------------------------- */ /* ***************************************************************** static char SccsId[] = "@(#) dens.h version 3.5 5/1/91" ; ***************************************************************** */ #ifndef DENS_H #define DENS_H #undef EXTERN #ifndef DENS_DEFS #define EXTERN extern #else #define EXTERN #endif #define TILEL 1 #define TILET 2 #define TILER 3 #define TILEB 4 typedef struct rtilebox { INT x1 ; INT y1 ; INT x2 ; INT y2 ; INT side ; BOOL switchbox ; struct rtilebox *next ; } RTILEBOX, *RTILEBOXPTR ; /* list of tiles to be added to each cell to accommodate routing */ EXTERN RTILEBOXPTR *routingTilesG ; #endif /* DENS_H */ graywolf-0.1.4+20170307gite1bf319/src/twmc/dialog.h000066400000000000000000000030701305746555600211350ustar00rootroot00000000000000static TWDIALOGBOX dialogS[53] = { 1,5,8," ACCEPT ",2,4,0, 1,25,8," CANCEL ",2,2,0, 2,15,9,"Edit Cell",0,4,0, 3,5,13,"Name",0,5,0, 4,5,12,"Number",0,5,0, 5,5,8,"Xcenter:",0,5,0, 5,14,8,"10",1,5,0, 6,5,8,"Ycenter:",0,5,0, 6,14,8,"10",1,5,0, 7,5,7,"Orient:",3,5,10, 7,14,2,"0 ",2,5,1, 7,16,2,"1 ",2,5,1, 7,18,2,"2 ",2,5,1, 7,20,2,"3 ",2,5,1, 7,22,2,"4 ",2,5,1, 7,24,2,"5 ",2,5,1, 7,26,2,"6 ",2,5,1, 7,28,2,"7 ",2,5,1, 9,5,19,"Valid orientations",0,5,0, 10,7,1,"0",3,5,20, 10,14,5,"valid",2,7,2, 10,25,7,"invalid",2,4,2, 11,7,1,"1",3,5,23, 11,14,5,"valid",2,7,3, 11,25,7,"invalid",2,4,3, 12,7,1,"2",3,5,26, 12,14,5,"valid",2,7,4, 12,25,7,"invalid",2,4,4, 13,7,1,"3",3,5,29, 13,14,5,"valid",2,7,5, 13,25,7,"invalid",2,4,5, 14,7,1,"4",3,5,32, 14,14,5,"valid",2,7,6, 14,25,7,"invalid",2,4,6, 15,7,1,"5",3,5,35, 15,14,5,"valid",2,7,7, 15,25,7,"invalid",2,4,7, 16,7,1,"6",3,5,38, 16,14,5,"valid",2,7,8, 16,25,7,"invalid",2,4,8, 17,7,1,"7",3,5,41, 17,14,5,"valid",2,7,9, 17,25,7,"invalid",2,4,9, 19,5,5,"Fixed",3,5,44, 19,14,3,"on ",2,7,10, 19,25,3,"off",2,4,10, 21,1,35,"To change case fields put pointer",0,5,0, 22,1,35,"in window and click. To change",0,5,0, 23,1,35,"input fields put pointer in window",0,5,0, 24,1,35,"and back up over current contents",0,5,0, 25,1,35,"using the delete key. After modifying",0,5,0, 26,1,35,"the field, hit the return key.",0,5,0, 0,0,0,0,0,0,0 } ; graywolf-0.1.4+20170307gite1bf319/src/twmc/finalout.c000066400000000000000000000175771305746555600215330ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: finalout.c DESCRIPTION:control loop after end of the simulated annealing algorithm. CONTENTS: finalout() DATE: Feb 5, 1988 REVISIONS: Dec 3, 1988 - added end of program for partition strategy. - added timing driven info to output. Dec 4, 1988 - added prnt_cost to make output easier - put addition and subtraction of pins in conditional compile. Mar 2, 1989 - removed annealing code. - added graphics wait loop. Mar 11,1989 - added graphics conditional compile. Nov 5,1989 - consolidated output routines and return early in partition case. Feb 7, 1990 - added final pin anneal at low temperature. Removed doborder now use routing tiles. Apr 28,1990 - stop updating pin positions halfway thru compaction cycle. Mon Jan 7 18:29:53 CST 1991 - removed annoying wait state which confuses people. Thu Jan 17 00:52:38 PST 1991 - added adapt_wire_estimator. Fri Jan 25 18:03:22 PST 1991 - added quickroute and removed unnecessary variables. Mon Feb 4 02:04:59 EST 1991 - let quickroute perform global routing. Tue Mar 12 17:02:16 CST 1991 - now no longer determine side of pad in partitioning case. Thu Apr 18 01:31:34 EDT 1991 - flush output. Sun May 5 14:26:56 EDT 1991 - replace config3 with reorigin. Tue Jun 11 13:59:27 CDT 1991 - need to insure that we update softpin final positions. Wed Jul 24 20:48:13 CDT 1991 - now always wait for user at the end of annealing if requested. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) finalout.c (Yale) version 3.15 7/24/91" ; #endif #include #include /* redefine flags for easier reading */ #define VIOLATIONSONLY FALSE #define COMPACT TRUE #define CHANNELGRAPH FALSE #define UPDATE_ROUTING TRUE #define NOCONSTRAINTS FALSE #define CONSTRAINTS TRUE finalout() { INT c ; INT bbtop, bbbottom, bbleft, bbright ; /* dump the results of the placement to graphics file */ G( graphics_dump() ) ; G( TWsetMode(1) ) ; G( draw_the_data() ) ; G( TWsetMode(0) ) ; /* we known wire area at this point don't need to estimate */ turn_wireest_on(FALSE) ; /* let the user know which pins we couldn't place */ set_pin_verbosity( TRUE ) ; /* before channel graph generation and global routing let use tweak */ /* placement if desired */ if( doGraphicsG && wait_for_userG ){ G( TWmessage( "TimberWolfMC waiting for your response" ) ) ; G( process_graphics() ) ; } savewolf( TRUE ) ; /* for debug purposes force save to occur */ if( scale_dataG > 1 ){ /* end of the line for scaled case - will return to parent to continue using saved placement. */ closegraphics() ; YexitPgm( PGMOK ) ; } grid_cells() ; /* force cells to grid locations */ compact(VIOLATIONSONLY); /* remove cell overlap */ /* if this is a partitioning run determine row placement */ if( doPartitionG && !(quickrouteG) ){ set_determine_side( FALSE ) ; /* allow SC to pick side */ G( set_graphic_context( PARTITION_PLACEMENT ) ) ; config_rows() ; print_paths() ; /* print path information */ Output( 0 ) ; return ; } /* do final placement of pads using virtual core to insure pads */ /* are outside of core */ setVirtualCore( TRUE ) ; placepads() ; /* before channel graph generation and global routing let use tweak */ /* placement if desired */ check_graphics() ; if( !scale_dataG ){ /* reload bins to get new overlap penalty */ loadbins(FALSE) ; /* wireArea not known */ } prnt_cost( "\nFINAL PLACEMENT RESULTS AFTER VIOLATION REMOVAL ARE:\n" ) ; print_paths() ; /* print path information */ Output( 0 ) ; if( doCompactionG > 0 || quickrouteG ) { gmain( CHANNELGRAPH ) ; rmain( NOCONSTRAINTS ) ; gmain( UPDATE_ROUTING ) ; adapt_wire_estimator() ; check_graphics() ; if( quickrouteG ){ return ; } for( c = 1 ; c <= doCompactionG ; c++ ) { funccostG = findcost() ; sprintf(YmsgG,"\n\nCompactor Pass Number: %d begins with:\n", c ) ; prnt_cost( YmsgG ) ; wirecosts() ; grid_cells() ; /* force cells to grid locations */ compact(COMPACT); /* remove white space */ reorigin() ; check_graphics() ; sprintf(YmsgG,"\n\nCompactor Pass Number: %d after cost:\n", c ) ; prnt_cost( YmsgG ) ; Output( c ) ; gmain( CHANNELGRAPH ) ; if( c == doCompactionG ){ rmain( CONSTRAINTS ) ; } else { rmain( NOCONSTRAINTS ) ; gmain( UPDATE_ROUTING ) ; adapt_wire_estimator() ; check_graphics() ; } } /* end compaction - global route loop */ } else { if( doChannelGraphG ) { gmain( CHANNELGRAPH ) ; } if( doGlobalRouteG ) { rmain( CONSTRAINTS ) ; } } prnt_cost("\nTIMBERWOLFMC FINAL RESULTS ARE:\n" ) ; return ; } /* end finalout */ Output( cycle ) INT cycle ; { if( cycle == 0 || cycle < doCompactionG / 2 ){ update_pins( FALSE ) ; /* update the _orig fields */ } outgeo() ; output(NULL) ; outpin() ; if( doPartitionG ){ output_partition() ; } return ; } /* end Output */ /* print out the current cost to the user */ prnt_cost( out_string ) char *out_string ; { INT xspan ; INT yspan ; funccostG = findcost() ; OUT2("%s", out_string ) ; OUT2(" routing cost :%d\n", funccostG ) ; OUT2(" overlap penalty :%d\n", binpenalG); OUT2(" lapFactor * overlap :%d\n", penaltyG); OUT2(" timing penalty :%d\n", timingpenalG ); OUT2("+ timeFactor * timepen:%d\n", timingcostG ); OUT1("-------------------------------------\n" ) ; OUT2(" total cost :%d\n", (funccostG + penaltyG + timingcostG) ) ; wirecosts() ; find_core_boundary( &blocklG, &blockrG, &blockbG, &blocktG ) ; OUT5("\n\nCORE Bounding Box: l:%d r:%d b:%d t:%d\n", blocklG , blockrG , blockbG , blocktG ) ; xspan = blockrG - blocklG ; yspan = blocktG - blockbG ; OUT2( " xspan = %d\n", xspan ) ; OUT2( " yspan = %d\n", yspan ) ; OUT2( " core area = %4.2le\n\n", (DOUBLE) xspan * (DOUBLE) yspan ); OUT1("-------------------------------------\n" ) ; Ymessage_flush() ; }/* end print_current_cost */ check_graphics() { if( doGraphicsG && wait_for_userG ){ G( TWmessage( "TimberWolfMC waiting for your response" ) ) ; G( process_graphics() ) ; } else { G( draw_the_data() ) ; } } /* end check_graphics */ graywolf-0.1.4+20170307gite1bf319/src/twmc/finalpin.c000066400000000000000000000636771305746555600215140ustar00rootroot00000000000000/* * Copyright (C) 1988-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: finalpin.c DESCRIPTION:main routine DATE: Jan 29, 1988 REVISIONS: Feb 7, 1990 - complete rewrite of finalpin. Now uses low temperature anneal. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) finalpin.c version 3.6 4/3/92" ; #endif #include #include #define HOWMANY 0 #define EXPECTEDNUMSITES 500 finalpin() { } #ifdef LATER static DOUBLE aspFactorS ; /* used to calculate diff from orig */ static INT oleftS ; /* used to calculate diff from orig */ static INT obottomS ; /* used to calculate diff from orig */ static INT Hdiv2S ; /* used to calculate diff from orig */ static INT Wdiv2S ; /* used to calculate diff from orig */ static INT instS ; /* used to calculate diff from orig */ /* perform a low temperature anneal on pins */ final_pin_place() { INT i ; /* counter */ INT attempts ; /* number of moves made */ INT nummoves ; /* number of moves to do on a cell */ INT selection ; /* select a cell with softpins */ INT nsoftpin_cells ; /* number of cells with softpins */ CELLBOXPTR acellptr; /* current cell with softpins */ /* don't perform if cost only is specified in input file */ /* scale data variable is necessary for recursive TimberWolfMC call */ if( /* cost_onlyG || */ scale_dataG > 1 ){ return ; } /* now check to see if we have any soft pins if not return */ if( (nsoftpin_cells = (int) softPinArrayG[HOWMANY] ) == 0 ){ return ; } /* make new site arrays for pins */ for( i = 1; i <= nsoftpin_cells; i++ ){ update_sites( softPinArrayG[i] ) ; } findcost() ; /* continue with a low Temp anneal */ TG = 10.0 ; attempts = 0 ; if( overpenalG ){ /* make pinFactor 1 order more important than wirelength */ pinFactorG = 10.0 * (DOUBLE) funccostG / (DOUBLE) overpenalG ; /* also set softPinArrayG to look at cells with overlap */ } else { /* otherwise use previous pinFactorG */ /* make 1 order more important */ pinFactorG *= 10.0 ; } while( attempts < attmaxG ) { /* to make pin moves more efficient, use softPinArrayG */ /* which keeps track of all softcells which have pins */ /* which can move. softPinArrayG[0] holds size of array */ selection = PICK_INT( 1, (int) softPinArrayG[HOWMANY] ); /* now get cellptr */ acellptr = softPinArrayG[selection] ; /* pick number of pins moves to be attempted */ /* PIN_MOVE is beginning of sequence. */ if( overpenalG && !(doPartitionG) ){ /* if a penalty exists do many moves */ nummoves = acellptr->numsoftpins ; } else { nummoves = 1 ; /* no penalty try to reduce wirelen */ } /* *********** NOW EVALUATE THE PROPOSED MOVE ********* */ /* now try softpin moves */ for( i=1; i<= nummoves; i++ ){ selectpin( acellptr ) ; } /* *********** END OF PROPOSED MOVE EVALUATION ********* */ attempts++ ; D( "finalpin", checkcost() ) ; /* if debug on check cost after each move */ } /* ****** END OF ANNEALING LOOP **************** */ /* verify incremental and current costs after each iteration */ D( "finalpin", checkcost() ) ; /* ----------------------------------------------------------------- now output statistics for this temperature. */ OUT1("\n\nPin place optimizer\n"); OUT1("\nI T funccost overpen x pinFact = overfill pinflips\n"); OUT2("%3d ",iterationG ); OUT2("%4.2le ",TG ); OUT2("%4.2le ",(DOUBLE) funccostG ); OUT2("%4.2le ",(DOUBLE) overpenalG ); OUT2("%4.2le ",(DOUBLE) pinFactorG ); OUT2("%4.2le ",(DOUBLE) overfillG ); OUT3("%3d/%3d\n\n",flippG,attpG ); FLUSHOUT() ; return ; } /* end final_pin_place */ /* ***************************************************************** */ update_sites( cellptr ) CELLBOXPTR cellptr ; { INT i ; /* counter */ INT j ; /* counter */ INT k ; /* counter */ INT site ; /* current site */ INT numsites ; /* number of sites for the cell */ INT span_side ; /* find total length of cell side */ INT l, r, b, t ; /* left, right, bottom, top of tile */ INT grid ; /* grid the sites */ INT save_x ; /* save the x offset */ INT save_y ; /* save the y offset */ INT trueSpan ; /* span modified by aspect ratio */ INT oldx, oldy ; /* traverse the cells point list */ INT newx, newy ; /* traverse the cells point list */ INT numpoints ; /* number of points in arb rect fig */ INT tile_count ; /* count the number of tiles */ INT HnotV ; /* TRUE horizontal edge FALSE vert */ INT side ; /* current side of the cell */ INT start ; /* where to start the sites on a side */ INT stop ; /* where to stop the sites on a side */ INT span ; /* span of this side */ INT numsoftpins ; /* number of soft pins for cell */ INT sites_this_side ; /* number of sites this side */ INT firstSite ; /* first site on the current side */ INT lastSite ; /* last site on the current side */ INT newfirstSite ; /* first site on this new side */ INT newlastSite ; /* last site on this new side */ INT lastPin ; /* last pin on the current side */ BOOL RTnotLB ; /* TRUE right top FALSE edge L or B */ CONTENTPTR *sitePtr ; /* pointer to array of site for cell */ CONTENTPTR this_site ; /* current site record */ CONTENTPTR *free_site ; /* used to free old site array */ TILEBOXPTR tileptr ; /* look at tiles of the cell */ BUSTBOXPTR PtsOut ; /* contains the pts of arb rect fig. */ BUSTBOXPTR unbust() ; /* returns the vertex list of cell */ SIDEBOXPTR side_array ; /* the sites of a given side */ PINBOXPTR *curSidePins ; /* the pins on the current side */ PINBOXPTR pin ; /* current pin */ SOFTBOXPTR softinfo ; /* soft information on pin */ static INT sort_softpins() ; /* sort pins on a side */ static CONTENTPTR *check_alloc() ;/* check allocation of site pointer */ side_array = (SIDEBOXPTR) Ysafe_malloc( (cellptr->numsides + 1) * sizeof(SIDEBOX) ) ; numsoftpins = cellptr->numsoftpins ; init_hard_struct( cellptr ) ; initPts(FALSE) ; /* no need to add extra points created with buster */ tile_count = 0 ; for( tileptr = cellptr->tiles;tileptr;tileptr = tileptr->next ) { l = tileptr->orig_left ; r = tileptr->orig_right ; b = tileptr->orig_bottom ; t = tileptr->orig_top ; addPts( ++tile_count, l , r , b , t ) ; } PtsOut = unbust() ; numpoints = PtsOut[HOWMANY].xc ; ASSERTNRETURN( numpoints > 0, NULL, "numpoints <= 0\n" ) ; ASSERTNRETURN((numpoints % 2)==0,NULL,"numpoints not multiple 2\n" ) ; /* remember old offset in order to set it back when done */ /* grid doesn't matter always the same */ Yget_gridx( &grid, &save_x ) ; Yget_gridy( &grid, &save_y ) ; sitePtr = check_alloc( NULL, EXPECTEDNUMSITES ) ; numsites = 0 ; side = 0 ; for( k = 1 ; k <= numpoints; k++ ) { oldx = PtsOut[k].xc ; oldy = PtsOut[k].yc ; if( k == 1 ){ /* now set grid from this point */ Yset_gridx( track_spacingXG, oldx ) ; Yset_gridy( track_spacingYG, oldy ) ; } if( k == numpoints ){ newx = PtsOut[1].xc ; newy = PtsOut[1].yc ; } else { newx = PtsOut[k+1].xc ; newy = PtsOut[k+1].yc ; } /* new side */ side++ ; /* now check the direction */ if( oldy == newy ){ HnotV = TRUE ; if( oldx < newx ){ /* side going to the right */ RTnotLB = TRUE ; /* calculate valid first locations */ start = oldx ; stop = newx ; Ygridx_up( &start ) ; Ygridx_down( &stop ) ; /* avoid pins at the corners */ if( start == oldx ){ /* at the start of the edge */ start += track_spacingXG ; } if( stop == newx ){ /* at the end of the edge */ stop -= track_spacingXG ; } } else { /* side going to the left */ RTnotLB = FALSE ; /* calculate valid first locations */ start = newx ; stop = oldx ; Ygridx_up( &start ) ; Ygridx_down( &stop ) ; /* avoid pins at the corners */ if( start == newx ){ /* at the start of the edge */ start += track_spacingXG ; } if( stop == oldx ){ /* at the end of the edge */ stop -= track_spacingXG ; } } /* now find the span of the side */ span = ABS( stop - start ) ; sites_this_side = (span / track_spacingXG) + 1 ; firstSite = numsites + 1 ; numsites += sites_this_side ; sitePtr = check_alloc( sitePtr, numsites ) ; /* store this information in side_array */ side_array[side].firstSite = firstSite ; side_array[side].lastSite = numsites ; /* now set the sites */ for( site = firstSite ; site <= numsites; site++ ){ this_site = sitePtr[site] ; this_site->capacity = 1 ; this_site->HorV = 0 ; /* 1 means horizontal */ this_site->span = track_spacingXG ; this_site->ypos = this_site->ypos_orig = oldy ; if( RTnotLB ){ /* to the right */ this_site->xpos = this_site->xpos_orig = start + (site - firstSite) * track_spacingXG ; } else { /* to the bottom */ this_site->xpos = this_site->xpos_orig = stop - (site - firstSite) * track_spacingXG ; } } } else if ( oldx == newx ){ HnotV = FALSE ; if( oldy < newy ){ /* side going to the top */ RTnotLB = TRUE ; /* calculate valid first locations */ start = oldy ; stop = newy ; Ygridy_up( &start ) ; Ygridy_down( &stop ) ; /* avoid pins at the corners */ if( start == oldy ){ /* at the start of the edge */ start += track_spacingYG ; } if( stop == newy ){ /* at the end of the edge */ stop -= track_spacingYG ; } } else { /* side going to the bottom */ RTnotLB = FALSE ; /* calculate valid first locations */ start = newy ; stop = oldy ; Ygridy_up( &start ) ; Ygridy_down( &stop ) ; /* avoid pins at the corners */ if( start == newy ){ /* at the start of the edge */ start += track_spacingXG ; } if( stop == oldy ){ /* at the end of the edge */ stop -= track_spacingYG ; } } /* now find the span of the side */ span = ABS( stop - start ) ; sites_this_side = (span / track_spacingYG) + 1 ; firstSite = numsites + 1 ; numsites += sites_this_side ; sitePtr = check_alloc( sitePtr, numsites ) ; /* store this information in side_array */ side_array[side].firstSite = firstSite ; side_array[side].lastSite = numsites ; /* now set the sites */ for( site = firstSite ; site <= numsites; site++ ){ this_site = sitePtr[site] ; this_site->capacity = 1 ; this_site->HorV = 1 ; /* 1 means vertical */ this_site->span = track_spacingYG ; this_site->xpos = this_site->xpos_orig = oldx ; if( RTnotLB ){ /* to the top */ this_site->ypos = this_site->ypos_orig = start + (site - firstSite) * track_spacingYG ; } else { /* to the bottom */ this_site->ypos = this_site->ypos_orig = stop - (site - firstSite) * track_spacingYG ; } } } else { M( ERRMSG, "update_sites", "problem with unbust\n" ) ; return ; } } if( numsoftpins > numsites ){ M( ERRMSG, "update_sites", "There are more pins than valid locations\n" ) ; sprintf( YmsgG, "\t - %d sites < %d pins for cell:%d\n", numsites,numsoftpins); OUT1( YmsgG ) ; M( MSG, NULL, YmsgG ) ; M( MSG, NULL, "\tSome pins will be placed with design rule violations\n" ) ; } curSidePins = (PINBOXPTR *) Ysafe_calloc( numsoftpins+1,sizeof(PINBOXPTR) ); /* initialize all the pins to not placed use the newsite field */ for( j = 1; j <= numsoftpins; j++ ){ pin = cellptr->softpins[j] ; softinfo = pin->softinfo ; softinfo->newsite = FALSE ; } for( side = 1; side <= cellptr->numsides ; side++ ){ /* find first Site of this side */ firstSite = cellptr->sideArray[side]->firstSite ; lastSite = cellptr->sideArray[side]->lastSite ; newfirstSite= side_array[side].firstSite ; newlastSite= side_array[side].lastSite ; /* now find all the pins on this side */ lastPin = 0 ; for( j = 1; j <= numsoftpins; j++ ){ pin = cellptr->softpins[j] ; softinfo = pin->softinfo ; site = softinfo->site ; if( site >= firstSite && site <= lastSite ){ /* pin belongs on this side */ curSidePins[++lastPin] = pin ; } } /* end loading all the pins on this side */ /* calculate the number of sites on this side */ site = newlastSite - newfirstSite + 1 ; if( lastPin > site ){ sprintf( YmsgG, "more pins:%d than sites:%d for cell:%s side:%d\n", lastPin, site, cellptr->cname, side ) ; M( WARNMSG,"update_sites", YmsgG ) ; } /* now sort pins so that most important pins are placed first */ Yquicksort( (char *) &(curSidePins[1]),lastPin, sizeof(PINBOXPTR), sort_softpins ) ; find_closest_site( cellptr, sitePtr, curSidePins, lastPin, newfirstSite, newlastSite ) ; } /* ********** NOW UPDATE CELL AND FREE MEMORY ********** */ Ysafe_free( curSidePins ) ; /* now replace the side_array and site array in data structures */ free_site = cellptr->siteContent ; for( i = 1; i <= cellptr->numsites; i++ ){ Ysafe_free( free_site[i] ) ; } Ysafe_free( cellptr->siteContent ) ; cellptr->siteContent = sitePtr ; cellptr->numsites = numsites ; /* now take care of the site array */ for( side = 1; side <= cellptr->numsides ; side++ ){ cellptr->sideArray[side]->firstSite = side_array[side].firstSite ; cellptr->sideArray[side]->lastSite = side_array[side].lastSite ; } Ysafe_free( side_array ) ; } /* end update_sites */ find_closest_site( cellptr, sitePtr, curSidePins, numsoftpins, firstSite, lastSite ) CELLBOXPTR cellptr ; CONTENTPTR *sitePtr ; PINBOXPTR *curSidePins ; INT numsoftpins ; INT firstSite ; INT lastSite ; { INT i ; /* counter */ INT j ; /* counter */ INT m ; /* counter */ INT seq ; /* length of current pin sequence */ INT cur_site ; /* current site */ INT xpos, ypos ; /* position of current pin site */ INT hit ; /* matching site in new array */ INT sum ; /* number of continuous open sites*/ INT seqcount ; /* number of continuous open sites*/ INT seqsite ; /* place to put start of seq. */ INT psite ; /* site counter */ INT distant ; /* distance to matching position */ INT ldist ; /* lower dist to match position */ INT udist ; /* upper dist to match position */ BOOL *ok_to_place ; /* ok to place seq starting here */ SOFTBOXPTR softinfo ; /* softinfo on pin */ PINBOXPTR pin ; /* current pin */ CONTENTPTR sptr ; /* current site pointer */ /* allocate temp space for placing sequences */ ok_to_place = (BOOL *) Ysafe_malloc( (lastSite-firstSite+2)*sizeof(BOOL)); for( j = 1; j <= numsoftpins; j++ ){ pin = curSidePins[j] ; softinfo = pin->softinfo ; if( softinfo->newsite ){ /* newsite is used here to note whether we placed pin already */ continue ; } /* find current position of pin */ cur_site = softinfo->site ; sptr = cellptr->siteContent[cur_site] ; seq = softinfo->sequence ; if( softinfo->numranges == 0 ){ /* a hard pin place first using position not site position */ /* use original location */ find_new_hard_pos( pin ) ; xpos = pin->txpos ; ypos = pin->typos ; } else { /* a soft pin use the site place as a first guess */ xpos = sptr->xpos ; ypos = sptr->ypos ; } hit = 0 ; distant = INT_MAX ; /* find best place for pin given current condition */ if( sptr->HorV ){ /* vertical edge */ for( m = firstSite ; m <= lastSite ; m++ ) { /* * Find the site with the nearest ypos */ if( ABS(sitePtr[m]->ypos - ypos ) < distant ) { distant = ABS( sitePtr[m]->ypos - ypos ) ; hit = m ; } } } else { /* horizontal edge */ for( m = firstSite ; m <= lastSite ; m++ ) { /* * Find the site with the nearest xpos */ if( ABS( sitePtr[m]->xpos - xpos ) < distant ) { distant = ABS( sitePtr[m]->xpos - xpos ) ; hit = m ; } } } /* NOW THAT WE FOUND THE CORRESPONDING SITE PLACE THE PINS */ if( hit ) { /* see if this position is taken */ if( seq > 1 ){ /* find the number of free spaces above and below this spot */ sum = 0 ; for( psite = hit; psite <= lastSite; psite++ ){ if( sitePtr[psite]->contents != 0 || ++sum >= seq ){ break ; } } if( sum >= seq ){ /* enough room place sequence */ for( seqcount = 0; seqcount < seq; seqcount++ ){ set_pin_n_site( sitePtr, pin, hit + seqcount ) ; /* get next pin */ pin = termarrayG[pin->pin + 1] ; } } else { /* --------------------------------------------------- Look up and down for sites that have adjoining open open sites. We mark every site that has enough room. */ seqcount = 0 ; for( i = firstSite; i <= lastSite; i++ ){ ok_to_place[i-firstSite] = FALSE ; } for( i = firstSite; i <= lastSite; i++ ){ if( sitePtr[i]->contents == 0 ){ if( ++seqcount >= seq ){ /* firstSite is offset in ok_to_place */ ok_to_place[i-firstSite-seq+1] = TRUE ; } } else { /* reset counter */ seqcount = 0 ; } } /* now find the closest site to hit */ distant = INT_MAX ; seqsite = 0 ; for( m = firstSite ; m <= lastSite ; m++ ) { /* * Find the site with the following sites open. */ if( ok_to_place[m - firstSite] ){ if( ABS(m - hit ) < distant ) { distant = ABS( m - hit ) ; seqsite = m ; } } } if( seqsite ){ /* we found a valid site place pins starting here */ /* enough room place sequence */ for( seqcount = 0; seqcount < seq; seqcount++ ){ set_pin_n_site( sitePtr, pin, seqsite+seqcount ) ; /* get next pin */ pin = termarrayG[pin->pin + 1] ; } } else { /* out of luck place at hit increment the overflow */ sprintf( YmsgG, "Sequence overflow for sequence starting with\n"); M( ERRMSG, NULL, YmsgG ) ; OUT1( YmsgG ) ; sprintf( YmsgG, " pin:%s cell:%d\n", pin->pinname,pin->cell ) ; M( ERRMSG, NULL, YmsgG ) ; OUT1( YmsgG ) ; for( seqcount = 0; seqcount < seq; seqcount++ ){ set_pin_n_site( sitePtr, pin, hit+seqcount ) ; /* get next pin */ pin = termarrayG[pin->pin + 1] ; } } } } else { /* find closest site that is open */ if( sitePtr[hit]->contents == 0 ){ /* place pin here */ set_pin_n_site( sitePtr, pin, hit ) ; } else { /* look up and down for closest free spot */ udist = INT_MAX ; ldist = INT_MAX ; for( psite = hit; psite >= firstSite; psite-- ){ if( sitePtr[psite]->contents == 0 ){ ldist = hit - psite ; break ; } } for( psite = hit; psite <= lastSite; psite++ ){ if( sitePtr[psite]->contents == 0 ){ udist = psite - hit ; break ; } } if( ldist < udist ){ /* place at lowest site */ set_pin_n_site( sitePtr, pin, hit - ldist ) ; } else if( udist < ldist ){ /* place at upper site */ set_pin_n_site( sitePtr, pin, hit + udist ) ; } else if( udist == ldist ){ if( udist == INT_MAX ){ /* no place to go add more to hit site */ set_pin_n_site( sitePtr, pin, hit ) ; sprintf( YmsgG, "Overfill for pin:%s cell:%d\n", pin->pinname, pin->cell) ; OUT1( YmsgG ) ; M( ERRMSG, NULL, YmsgG ) ; } else { /* just pick lower site as default */ set_pin_n_site( sitePtr, pin, hit - ldist ) ; } } } } } else { M( ERRMSG, "find_closest_site", "Problem with finding pinsite\n"); return ; } } /* end for loop */ Ysafe_free( ok_to_place ) ; } /* end find_closest_site */ static INT sort_softpins( pinAptr, pinBptr ) PINBOXPTR *pinAptr, *pinBptr ; { PINBOXPTR pinA ; /* pinA dereference for ease of use */ PINBOXPTR pinB ; /* pinB dereference for ease of use */ SOFTBOXPTR sinfoA ; /* softpin info on pinA */ SOFTBOXPTR sinfoB ; /* softpin info on pinA */ pinA = *pinAptr ; pinB = *pinBptr ; sinfoA = pinA->softinfo ; sinfoB = pinB->softinfo ; /* hardpins must be placed first */ if( sinfoA->numranges == 0 && sinfoB->numranges == 0 ){ return( 0 ) ; } else if( sinfoA->numranges == 0 ){ return( -1 ) ; } else if( sinfoB->numranges == 0 ){ return( 1 ) ; } /* now check the sequences */ /* we want sequences followed by isolated pins */ /* pins of sequence will be place by the sequence pin */ if( sinfoA->sequence > 1 && sinfoB->sequence > 1 ){ return( sinfoA->sequence - sinfoB->sequence ) ; } else if( sinfoA->sequence > 1 ){ return( -1 ) ; } else if( sinfoB->sequence > 1 ){ return( 1 ) ; } else if( sinfoA->sequence == 1 && sinfoB->sequence == 1 ){ return( 0 ) ; } else if( sinfoA->sequence == 1 ){ return( -1 ) ; } else if( sinfoB->sequence == 1 ){ return( 1 ) ; } else { return( 0 ) ; } } /* end sort_softpins */ /* maintain allocation of sites */ static CONTENTPTR *check_alloc( sites, numsites ) CONTENTPTR *sites ; INT numsites ; { INT i ; /* counter */ INT oldAlloc ; /* old allocation */ static INT siteAllocS ; /* current site allocation */ if( sites ){ if( numsites >= siteAllocS ){ oldAlloc = siteAllocS ; siteAllocS = numsites + EXPECTEDNUMSITES + 1 ; sites = (CONTENTPTR *) Ysafe_realloc( sites, siteAllocS * sizeof(CONTENTPTR) ) ; for( i = oldAlloc; i < siteAllocS; i++ ){ sites[i] = (CONTENTPTR) Ysafe_calloc( 1,sizeof(CONTENTBOX) ) ; } } } else { /* start new site array */ siteAllocS = numsites + 1 ; sites = (CONTENTPTR *) Ysafe_calloc( siteAllocS,sizeof(CONTENTPTR) ) ; for( i = 1; i <= numsites; i++ ){ sites[i] = (CONTENTPTR) Ysafe_calloc( 1,sizeof(CONTENTBOX) ) ; } } return( sites ) ; } /* end check_alloc */ static set_pin_n_site( site_array, pin, site ) CONTENTPTR *site_array ; PINBOXPTR pin ; INT site ; { SOFTBOXPTR softinfo ; CONTENTPTR sptr ; softinfo = pin->softinfo ; softinfo->site = site ; softinfo->newsite = TRUE ; sptr = site_array[site] ; sptr->contents++ ; pin->txpos = sptr->xpos ; pin->typos = sptr->ypos ; /* set original field */ pin->txpos_orig[instS] = sptr->xpos ; pin->typos_orig[instS] = sptr->ypos ; } /* ****************************************************************** */ static init_hard_struct( cellptr ) CELLBOXPTR cellptr ; { INT oright, otop ; /* calculate difference from bbox */ DOUBLE val ; /* temp */ BOUNBOXPTR bounptr ; /* bounding box pointer */ INSTBOXPTR instptr ; /* pointer to instance info */ if( cellptr->orient <= 3 ) { aspFactorS = sqrt( cellptr->aspect / cellptr->orig_aspect ) ; } else { aspFactorS = sqrt( cellptr->orig_aspect / cellptr->aspect ) ; } if( instptr = cellptr->instptr ){ instS = instptr->cur_inst ; } else { instS = 0 ; } /* use original bounding box to calculate changes */ bounptr = cellptr->bounBox[8] ; /* original bbox */ oleftS = bounptr->l ; obottomS = bounptr->b ; oright = bounptr->r ; otop = bounptr->t ; val = (DOUBLE) (otop - obottomS) * aspFactorS ; Hdiv2S = ROUND( val ) / 2 ; val = (DOUBLE) (oright - oleftS) / aspFactorS ; Wdiv2S = ROUND( val ) / 2 ; } /* end init_hard_struct */ static find_new_hard_pos( pin ) PINBOXPTR pin ; { DOUBLE val ; val = (DOUBLE)(pin->txpos_orig[instS] - oleftS) / aspFactorS ; pin->txpos = ROUND( val ) - Wdiv2S ; val = (DOUBLE)(pin->typos_orig[instS] - obottomS) * aspFactorS ; pin->typos = ROUND( val ) - Hdiv2S ; } /* end find_new_hard_pos */ #endif graywolf-0.1.4+20170307gite1bf319/src/twmc/findcheck.c000066400000000000000000000102131305746555600216040ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: findcheck.c DESCRIPTION:final check CONTENTS: finalcheck() DATE: Jan 30, 1988 REVISIONS: Jul 21, 1988 - fixed softcell code. Oct 25, 1988 - remove weights from funccost Mar 30, 1989 - changed tile datastructure. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) findcheck.c version 3.3 9/5/90" ; #endif #include #include #include finalcheck() { NETBOXPTR netptr ; PINBOXPTR pinptr ; CELLBOXPTR ptr ; INT cell , net ; INT x , y , xc , yc ; INT orient ; fcostG = 0 ; fwireG = 0 ; fwirexG = 0 ; fwireyG = 0 ; for( cell = 1 ; cell <= totalcellsG; cell++ ) { ptr = cellarrayG[cell] ; orient = ptr->orient ; xc = ptr->xcenter ; yc = ptr->ycenter ; for( pinptr = ptr->pinptr ; pinptr ; pinptr = pinptr->nextpin ) { /* rel position is a macro which calculates absolute pin loc */ /* defined in relpos.h */ REL_POS( orient, pinptr->xpos, pinptr->ypos, /* result */ pinptr->txpos, pinptr->typos, /* cell relative */ xc, yc ) ; /* cell center */ } } for( net = 1 ; net <= numnetsG ; net++ ) { netptr = netarrayG[net] ; if( netptr->skip ) { continue ; } for( pinptr = netptr->pins ;pinptr ; pinptr = pinptr->next ) { if( pinptr ) { break ; } if( pinptr->skip ) { continue ; } netptr->xmin = netptr->xmax = pinptr->xpos ; netptr->ymin = netptr->ymax = pinptr->ypos ; pinptr = pinptr->next ; break ; } for( ; pinptr ; pinptr = pinptr->next ) { if( pinptr->skip ) { continue ; } x = pinptr->xpos ; y = pinptr->ypos ; if( x < netptr->xmin ) { netptr->xmin = x ; } else if( x > netptr->xmax ) { netptr->xmax = x ; } if( y < netptr->ymin ) { netptr->ymin = y ; } else if( y > netptr->ymax ) { netptr->ymax = y ; } } fwirexG += netptr->xmax - netptr->xmin ; fwireyG += netptr->ymax - netptr->ymin ; fwireG += netptr->xmax - netptr->xmin + netptr->ymax - netptr->ymin; fcostG += ( netptr->xmax - netptr->xmin ) + ( netptr->ymax - netptr->ymin ) ; } return; } initcheck() { NETBOXPTR netptr ; INT net ; icostG = 0 ; iwireG = 0 ; iwirexG = 0 ; iwireyG = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { netptr = netarrayG[net] ; iwirexG += netptr->xmax - netptr->xmin ; iwireyG += netptr->ymax - netptr->ymin ; iwireG += netptr->xmax - netptr->xmin + netptr->ymax - netptr->ymin; icostG += ( netptr->xmax - netptr->xmin) + ( netptr->ymax - netptr->ymin) ; } return; } graywolf-0.1.4+20170307gite1bf319/src/twmc/findcost.c000066400000000000000000000253011305746555600215030ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: findcost.c DESCRIPTION:function calculates initial cost CONTENTS: findcost( ) DATE: Jan 29, 1988 REVISIONS: Oct 22, 1988 - now take square root of the penalty since square gives large variance compared to linear terms in cost function. Dec 3, 1988 - added timing driven penalty to cost function. Mar 7, 1989 - added test for totalcells loop. Mar 16, 1989 - rewrote the netlist data structures. Mar 20, 1989 - deleted argument to checkcost. May 11, 1989 - eliminated doPartition flag Feb 8, 1989 - added test for wraparound for large designs using cost only. Bin penalty doesn't matter. Apr 23, 1990 - added new debug code. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) findcost.c version 3.7 11/23/91" ; #endif #include #include #include findcost() { NETBOXPTR netptr ; PINBOXPTR pinptr ; CELLBOXPTR ptr ; BINBOXPTR bptr ; GLISTPTR net_of_path ; INT cell , net ; INT x , y , cost ; INT orient ; INT length, pathcount ; INT low_length, high_length ; PATHPTR path ; cost = 0 ; /* ************** calculate global coordinates of the pins *************/ for( cell = 1 ; cell <= totalcellsG ; cell++ ) { ptr = cellarrayG[cell] ; /* avoid work if cell is not custom,soft, or pad cell */ if( ptr->celltype != CUSTOMCELLTYPE && ptr->celltype != SOFTCELLTYPE && ptr->celltype != PADCELLTYPE ){ continue ; } orient = ptr->orient ; /* go thru all pins of the cell */ for( pinptr = ptr->pinptr ; pinptr ; pinptr = pinptr->nextpin ) { /* debug - calculate global position for pins */ /* complain if different from incremental */ D( "findcost", REL_POS( orient, x, y, /* result */ pinptr->txpos, pinptr->typos, /* relative */ ptr->xcenter, ptr->ycenter ) ; /* cell center */ if( x != pinptr->xpos ){ D( "findcost/print",fprintf( stderr,"xpos incorrect\n")) ; } else if( y != pinptr->ypos ){ D( "findcost/print",fprintf( stderr,"ypos incorrect\n")) ; } ) ; /* end debug macro */ /* rel pos is a macro which calculates absolute pin location */ /* defined in relpos.h */ REL_POS( orient, pinptr->xpos, pinptr->ypos, /* result */ pinptr->txpos, pinptr->typos, /* cell relative */ ptr->xcenter, ptr->ycenter ) ; /* cell center */ } } /* end calculation of pin global coordinates */ /* ********* calculate net half perimeter bounding box *********** */ for( net = 1 ; net <= numnetsG ; net++ ) { netptr = netarrayG[net] ; if(!(netptr)) { continue ; } if( netptr->skip == 1 ) { continue ; } /* for debug initialize the new fields so we can see difference */ D( "findcost/netcalc", netptr->newxmin = netptr->xmin ; netptr->newymin = netptr->ymin ; netptr->newxmax = netptr->xmax ; netptr->newymax = netptr->ymax ; ) ; /* find first pin that we don't have skip field set */ /* initialize bounding box pin count to 1 */ for( pinptr = netptr->pins;pinptr; pinptr = pinptr->next ) { if( pinptr->skip == 1 ) { continue ; } netptr->xmin = netptr->xmax = pinptr->xpos ; netptr->ymin = netptr->ymax = pinptr->ypos ; netptr->Lnum = netptr->Rnum = 1 ; netptr->Bnum = netptr->Tnum = 1 ; pinptr = pinptr->next ; break ; } /* Now find whether this pin impacts the bounding box */ /* Note when we get more than one pin on the bounding box */ for( ; pinptr ; pinptr = pinptr->next ) { if( pinptr->skip == 1 ) { continue ; } x = pinptr->xpos ; y = pinptr->ypos ; if( x < netptr->xmin ) { netptr->xmin = x ; netptr->Lnum = 1 ; } else if( x == netptr->xmin ) { netptr->Lnum++ ; if( x == netptr->xmax ) { netptr->Rnum++ ; } } else if( x > netptr->xmax ) { netptr->xmax = x ; netptr->Rnum = 1 ; } else if( x == netptr->xmax ) { netptr->Rnum++ ; } if( y < netptr->ymin ) { netptr->ymin = y ; netptr->Bnum = 1 ; } else if( y == netptr->ymin ) { netptr->Bnum++ ; if( y == netptr->ymax ) { netptr->Tnum++ ; } } else if( y > netptr->ymax ) { netptr->ymax = y ; netptr->Tnum = 1 ; } else if( y == netptr->ymax ) { netptr->Tnum++ ; } } /* calculate cost using a vertical wire weight */ cost += netptr->halfPx = netptr->newhalfPx = netptr->xmax - netptr->xmin ; netptr->halfPy = netptr->newhalfPy = netptr->ymax - netptr->ymin ; cost = cost + (INT)( vertical_wire_weightG * (DOUBLE) netptr->halfPy ) ; /* check to make sure calculation jives */ D( "findcost/netcalc", if( netptr->newxmin != netptr->xmin ){ D( "findcost/print",fprintf( stderr,"netptr->xmin wrong\n")); } if( netptr->newxmax != netptr->xmax ){ D( "findcost/print",fprintf( stderr,"netptr->xmax wrong\n")); } if( netptr->newymin != netptr->ymin ){ D( "findcost/print",fprintf( stderr,"netptr->ymin wrong\n")); } if( netptr->newymax != netptr->ymax ){ D( "findcost/print",fprintf( stderr,"netptr->ymax wrong\n")); } ) ; } /* end half perimeter bounding box calculation */ /* now calculate the penalties */ /* first the timing penalty */ timingpenalG = 0 ; for( pathcount = 1 ; pathcount <= numpathsG ; pathcount++ ) { path = patharrayG[pathcount] ; ASSERTNCONT( path, "findcost", "pointer to path is NULL" ) ; low_length = 0 ; high_length = 0 ; /* ----------------------------------------------------------------- For all nets k of a path i: We use the minimum strength driver for each net to calculate the lower bound on the length and the maximum strength driver for the upper bound on the length. The user must take false paths into account when specifying the driver strengths. ------------------------------------------------------------------ */ for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; netptr = netarrayG[net] ; /* accumulate length of path */ length = netptr->halfPx + (INT)(vertical_path_weightG * (DOUBLE) netptr->halfPy) ; low_length = low_length + (INT) (netptr->max_driver * (FLOAT) length + netptr->driveFactor ) ; high_length = high_length + (INT) (netptr->min_driver * (FLOAT) length + netptr->driveFactor ) ; } /* save result */ path->lo_path_len = path->new_lo_path_len = low_length ; path->hi_path_len = path->new_hi_path_len = high_length ; /* ----------------------------------------------------------- Calculate penalty - no penalty if within target window: lowerbound <= length <= upperbound Otherwise calculate penalties ------------------------------------------------------------- */ if( high_length > path->upper_bound ){ timingpenalG += high_length - path->upper_bound ; } else if( low_length < path->lower_bound ){ timingpenalG += path->lower_bound - low_length ; } } /* scale timing penalty */ timingcostG = (INT) ( timeFactorG * (DOUBLE) timingpenalG ) ; /* next the overlap penalty */ binpenalG = 0 ; for( x= 0 ; x <= maxBinXG; x++ ) { for( y = 0 ; y <= maxBinYG; y++ ) { bptr = binptrG[x][y] ; binpenalG += ABS( bptr->penalty ) ; } } /* wrap around case */ if( binpenalG < 0 ){ binpenalG = INT_MAX ; } /* scale penalty */ penaltyG = (INT) ( lapFactorG * sqrt( (DOUBLE) binpenalG ) ) ; return( cost ) ; } /* end findcost */ #ifdef DEBUG checkcost() { INT incr_funccost, incr_penalty, incr_time ; INT incr_overpenal, incr_timepen ; INT x, y ; BOOL flag ; /* verify incremental cost equals the true cost */ /* save value of the current costs derived from incremental calculations */ DS( incr_funccost = funccostG ; ) ; DS( incr_penalty = penaltyG ; ) ; DS( incr_overpenal = binpenalG ; ) ; DS( incr_time = timingcostG ; ) ; DS( incr_timepen = timingpenalG ; ) ; /* calculate current cost from scratch */ /* verify current cost == incremental cost */ funccostG = findcost() ; if( funccostG != incr_funccost ){ M( ERRMSG,"checkcost", "Incremental wire cost does not equal current cost\n" ) ; } if( penaltyG != incr_penalty ){ M( ERRMSG, "checkcost", "Incremental overlap penalty does not equal current penalty\n" ) ; } if( binpenalG != incr_overpenal ){ M( ERRMSG, "checkcost", "Incremental overlap penalty does not equal current penalty\n" ) ; } if( timingcostG != incr_time ){ M( ERRMSG, "checkcost", "Incremental timing penalty does not equal current timing\n" ) ; } if( timingpenalG != incr_timepen ){ M( ERRMSG, "checkcost", "Incremental timing penalty does not equal current timing\n" ) ; } D( "checkcost", /* drastic test */ incr_penalty = penaltyG ; incr_overpenal = binpenalG ; flag = FALSE ; loadbins( flag ) ; for( x = 0; x<= maxBinXG; x++){ for( y = 0; y<= maxBinYG; y++){ binptrG[x][y]->nupenalty = 0 ; } } if( penaltyG != incr_penalty ){ M( ERRMSG, "checkcost", "Incremental overlap penalty != current penalty\n" ) ; } if( binpenalG != incr_overpenal ){ M( ERRMSG, "checkcost", "Incremental overlap penalty != current penalty\n" ) ; } ) ; } /* end checkcost */ #endif /* DEBUG */ graywolf-0.1.4+20170307gite1bf319/src/twmc/findloc.c000066400000000000000000000223711305746555600213140ustar00rootroot00000000000000/* * Copyright (C) 1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char SccsId[] = "@(#) findloc.c version 3.3 9/5/90" ; #endif #include #include typedef struct flogbox { INT pin ; INT placed ; INT finalx ; INT finaly ; } FBOX , *FBOXPTR ; /* * We have here a little function which * takes as an argument the given UCpin and returns * the best possible location in the site. */ findLoc( pinptr, lArray, nPinLocs, HorV ) PINBOXPTR pinptr ; BOOL HorV ; INT nPinLocs ; FBOXPTR lArray ; { INT bigoX , bigoY , litoX , litoY ; INT aPin, bestPos , meanx , meany , distant , i ; bigoX = INT_MIN ; bigoY = INT_MIN ; litoX = INT_MAX ; litoY = INT_MAX ; aPin = pinptr->pin ; /* same pin */ for( pinptr = netarrayG[pinptr->net]->pins;pinptr;pinptr = pinptr->next ){ if( pinptr->pin != aPin ) { if( pinptr->xpos < litoX ) { litoX = pinptr->xpos ; } if( pinptr->xpos > bigoX ) { bigoX = pinptr->xpos ; } if( pinptr->ypos < litoY ) { litoY = pinptr->ypos ; } if( pinptr->ypos > bigoY ) { bigoY = pinptr->ypos ; } } } if( HorV ) { if( lArray[ nPinLocs ].finaly > lArray[1].finaly ) { if( litoY >= lArray[ nPinLocs ].finaly ) { bestPos = nPinLocs ; } else if( bigoY <= lArray[1].finaly ) { bestPos = 1 ; } else if( bigoY <= lArray[ nPinLocs ].finaly && litoY >= lArray[1].finaly ) { /* * bounding box of net (sans aPin) is * within span of site. Find nearest loc * (in the site) to the center of b.b. */ meany = (bigoY + litoY) / 2 ; distant = ABS( meany - lArray[1].finaly ) ; for( i = 2 ; i <= nPinLocs ; i++ ) { if( ABS( meany - lArray[i].finaly ) < distant ) { distant = ABS(meany - lArray[i].finaly); } else { break ; } } bestPos = i - 1 ; } else if( bigoY >= lArray[ nPinLocs ].finaly && litoY <= lArray[1].finaly ) { /* * Site is spanned (contained) by the b.b. * Select middle loc. */ bestPos = (nPinLocs + 1) / 2 ; } else { /* only some overlapping exists */ /* * Find edge of b.b. inside site. */ if( litoY < lArray[ nPinLocs ].finaly && litoY > lArray[ 1 ].finaly ) { /* * Find nearest loc to litoY */ distant = ABS( litoY - lArray[1].finaly ) ; for( i = 2 ; i <= nPinLocs ; i++ ) { if( ABS( litoY - lArray[i].finaly ) < distant ){ distant = ABS(litoY - lArray[i].finaly) ; } else { break ; } } bestPos = ( i + nPinLocs ) / 2 ; } else { /* * Find nearest loc to bigoY */ distant = ABS( bigoY - lArray[1].finaly ) ; for( i = 2 ; i <= nPinLocs ; i++ ) { if( ABS( bigoY - lArray[i].finaly ) < distant ){ distant = ABS(bigoY - lArray[i].finaly) ; } else { break ; } } bestPos = i / 2 ; } } } else { if( litoY >= lArray[1].finaly ) { bestPos = 1 ; } else if( bigoY <= lArray[ nPinLocs ].finaly ) { bestPos = nPinLocs ; } else if( bigoY <= lArray[1].finaly && litoY >= lArray[ nPinLocs ].finaly ) { /* * bounding box of net (sans aPin) is * within span of site. Find nearest loc * (in the site) to the center of b.b. */ meany = (bigoY + litoY) / 2 ; distant = ABS( meany - lArray[1].finaly ) ; for( i = 2 ; i <= nPinLocs ; i++ ) { if( ABS( meany - lArray[i].finaly ) < distant ) { distant = ABS(meany - lArray[i].finaly); } else { break ; } } bestPos = i - 1 ; } else if( bigoY >= lArray[1].finaly && litoY <= lArray[ nPinLocs ].finaly ) { /* * Site is spanned (contained) by the b.b. * Select middle loc. */ bestPos = (nPinLocs + 1) / 2 ; } else { /* only some overlapping exists */ /* * Find edge of b.b. inside site. */ if( litoY < lArray[1].finaly && litoY > lArray[ nPinLocs ].finaly ) { /* * Find nearest loc to litoY */ distant = ABS( litoY - lArray[1].finaly ) ; for( i = 2 ; i <= nPinLocs ; i++ ) { if( ABS( litoY - lArray[i].finaly ) < distant ){ distant = ABS(litoY - lArray[i].finaly) ; } else { break ; } } bestPos = i / 2 ; } else { /* * Find nearest loc to bigoY */ distant = ABS( bigoY - lArray[1].finaly ) ; for( i = 2 ; i <= nPinLocs ; i++ ) { if( ABS( bigoY - lArray[i].finaly ) < distant ){ distant = ABS(bigoY - lArray[i].finaly) ; } else { break ; } } bestPos = ( i + nPinLocs ) / 2 ; } } } } else { /* a horizontal site */ if( lArray[ nPinLocs ].finalx > lArray[1].finalx ) { if( litoX >= lArray[ nPinLocs ].finalx ) { bestPos = nPinLocs ; } else if( bigoX <= lArray[1].finalx ) { bestPos = 1 ; } else if( bigoX <= lArray[ nPinLocs ].finalx && litoX >= lArray[1].finalx ) { /* * bounding box of net (sans aPin) is * within span of site. Find nearest loc * (in the site) to the center of b.b. */ meanx = (bigoX + litoX) / 2 ; distant = ABS( meanx - lArray[1].finalx ) ; for( i = 2 ; i <= nPinLocs ; i++ ) { if( ABS( meanx - lArray[i].finalx ) < distant ) { distant = ABS(meanx - lArray[i].finalx); } else { break ; } } bestPos = i - 1 ; } else if( bigoX >= lArray[ nPinLocs ].finalx && litoX <= lArray[1].finalx ) { /* * Site is spanned (contained) by the b.b. * Select middle loc. */ bestPos = (nPinLocs + 1) / 2 ; } else { /* only some overlapping exists */ /* * Find edge of b.b. inside site. */ if( litoX < lArray[ nPinLocs ].finalx && litoX > lArray[ 1 ].finalx ) { /* * Find nearest loc to litoX */ distant = ABS( litoX - lArray[1].finalx ) ; for( i = 2 ; i <= nPinLocs ; i++ ) { if( ABS( litoX - lArray[i].finalx ) < distant ){ distant = ABS(litoX - lArray[i].finalx) ; } else { break ; } } bestPos = ( i + nPinLocs ) / 2 ; } else { /* * Find nearest loc to bigoX */ distant = ABS( bigoX - lArray[1].finalx ) ; for( i = 2 ; i <= nPinLocs ; i++ ) { if( ABS( bigoX - lArray[i].finalx ) < distant ){ distant = ABS(bigoX - lArray[i].finalx) ; } else { break ; } } bestPos = i / 2 ; } } } else { if( litoX >= lArray[1].finalx ) { bestPos = 1 ; } else if( bigoX <= lArray[ nPinLocs ].finalx ) { bestPos = nPinLocs ; } else if( bigoX <= lArray[1].finalx && litoX >= lArray[ nPinLocs ].finalx ) { /* * bounding box of net (sans aPin) is * within span of site. Find nearest loc * (in the site) to the center of b.b. */ meanx = (bigoX + litoX) / 2 ; distant = ABS( meanx - lArray[1].finalx ) ; for( i = 2 ; i <= nPinLocs ; i++ ) { if( ABS( meanx - lArray[i].finalx ) < distant ) { distant = ABS(meanx - lArray[i].finalx); } else { break ; } } bestPos = i - 1 ; } else if( bigoX >= lArray[1].finalx && litoX <= lArray[ nPinLocs ].finalx ) { /* * Site is spanned (contained) by the b.b. * Select middle loc. */ bestPos = (nPinLocs + 1) / 2 ; } else { /* only some overlapping exists */ /* * Find edge of b.b. inside site. */ if( litoX < lArray[1].finalx && litoX > lArray[ nPinLocs ].finalx ) { /* * Find nearest loc to litoX */ distant = ABS( litoX - lArray[1].finalx ) ; for( i = 2 ; i <= nPinLocs ; i++ ) { if( ABS( litoX - lArray[i].finalx ) < distant ){ distant = ABS(litoX - lArray[i].finalx) ; } else { break ; } } bestPos = i / 2 ; } else { /* * Find nearest loc to bigoX */ distant = ABS( bigoX - lArray[1].finalx ) ; for( i = 2 ; i <= nPinLocs ; i++ ) { if( ABS( bigoX - lArray[i].finalx ) < distant ){ distant = ABS(bigoX - lArray[i].finalx) ; } else { break ; } } bestPos = ( i + nPinLocs ) / 2 ; } } } } return( bestPos ) ; } /* end of findLoc */ graywolf-0.1.4+20170307gite1bf319/src/twmc/findside.c000066400000000000000000000171331305746555600214630ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: findside.c DESCRIPTION:This file contains the routines to find what side the pins are located. CONTENTS: INT findside( pSideArray, cellptr , x , y ) PSIDEBOX *pSideArray ; CELLBOXPTR cellptr ; INT x , y ; loadside( pSideArray, side , factor ) PSIDEBOX *pSideArray ; INT side ; DOUBLE factor ; DATE: Aug 7, 1988 REVISIONS: Apr 23, 1990 - added error checking for soft pins and add them correctly to the PSIDE array. Thu Jan 17 00:51:01 PST 1991 - fixed bug in the case of T shaped cells. Now finds correct side. Wed Feb 13 23:35:07 EST 1991 - renamed set routines. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) findside.c version 3.5 2/13/91" ; #endif #include #include #include #include #define HOWMANY 0 /* returns which side a pin is located */ INT findside( pSideArray, cellptr , x , y ) PSIDEBOX *pSideArray ; CELLBOXPTR cellptr ; INT x , y ; { INT k , min , kmin, dist, begin, end ; INT xc, yc, b, e ; INT *yvert, *xvert ; min = INT_MAX ; kmin = 1 ; /* default side */ xc = cellptr->xcenter ; yc = cellptr->ycenter ; xvert = cellptr->vertices->x ; yvert = cellptr->vertices->y ; for( k = 1 ; k <= cellptr->numsides ; k++ ) { if( pSideArray[k].vertical == 1 ) { dist = ABS(x - pSideArray[k].position) ; b = yvert[k] + yc ; if( k == cellptr->numsides ){ e = yvert[1] + yc ; } else { e = yvert[k+1] + yc ; } begin = MIN( b, e ) ; end = MAX( b, e ) ; if( begin <= y && y <= end && dist < min ){ min = ABS(x - pSideArray[k].position) ; kmin = k ; } } else { dist = ABS(y - pSideArray[k].position) ; b = xvert[k] + xc ; if( k == cellptr->numsides ){ e = xvert[1] + xc ; } else { e = xvert[k+1] + xc ; } begin = MIN( b, e ) ; end = MAX( b, e ) ; if( begin <= x && x <= end && dist < min ){ min = ABS(y - pSideArray[k].position) ; kmin = k ; } } } return( kmin ) ; } /* end findside */ /* load the side with a pin count and add factor */ loadside( pSideArray, side , factor ) PSIDEBOX *pSideArray ; INT side ; DOUBLE factor ; { pSideArray[side].pincount += factor ; return ; } /* end loadside */ load_soft_pins( ptr, pSideArray ) CELLBOXPTR ptr ; PSIDEBOX *pSideArray ; { INT i ; /* counter */ INT j ; /* counter */ INT howmany ; /* number of softpins for cell */ INT restrict1 ; /* counter */ INT match ; /* count number of matching restricts*/ INT numsides ; /* number of side restrictions */ INT numrestricts ; /* current # restricts for child */ INT parent_restricts ; /* current # restricts for parent */ BOOL abortPin ; /* abort load if true */ PINBOXPTR pin ; /* current pin */ PINBOXPTR parent ; /* parent to current pin */ SOFTBOXPTR spin ; /* soft information for current pin */ YSETPTR side_set ; /* set of valid sides for pin */ YSETLISTPTR curside ; /* used to enumerate the set */ if(!(ptr->softpins)){ return ; } side_set = Yset_init( 1, ptr->numsides ) ; howmany = (INT) ptr->softpins[HOWMANY] ; for( i = 1 ; i <= howmany; i++ ){ /**** DETERMINE THE VALID SIDES FOR A SOFTPIN ****/ pin = ptr->softpins[i] ; spin = pin->softinfo ; if( pin->type == HARDPINTYPE || pin->type == PINGROUPTYPE ){ continue ; } /* now remove restrictions if present */ numrestricts = spin->restrict1[HOWMANY] ; /* initialize set to the empty set */ Yset_empty( side_set ) ; if( numrestricts == 0 ){ /* everybody is valid */ for( j = 1; j <= ptr->numsides; j++ ){ Yset_add( side_set, j ) ; } } else { /* just validate the given list of sides */ for( restrict1 = 1; restrict1 <= numrestricts; restrict1++ ){ Yset_add( side_set, spin->restrict1[restrict1] ) ; } } /* at this point we have checked the leaf, check parents for */ /* consistency if pin is not a softequiv type */ parent = spin->parent ; abortPin = FALSE ; while( parent && pin->type != SOFTEQUIVTYPE ){ spin = parent->softinfo ; parent_restricts = spin->restrict1[HOWMANY] ; /* check the various cases of number of restrictions */ if( numrestricts != 0 && parent_restricts == 0 ){ /* we have an inconsistency */ sprintf( YmsgG, "Pin:%s has inconsistent restrictions\n", pin->pinname ) ; M( ERRMSG, "load_soft_pins", YmsgG ) ; abortPin = TRUE ; } else if( numrestricts != 0 && parent_restricts != 0 ){ /* need to make sure that parent is more restrictive */ /* than child */ match = 0 ; /* initially no matching restrictions */ for( restrict1 = 1;restrict1<=parent_restricts;restrict1++ ){ if( Yset_member( side_set, spin->restrict1[restrict1] ) ){ match++ ; } else { Yset_add( side_set, spin->restrict1[restrict1] ) ; } } if( match != numrestricts ){ sprintf( YmsgG, "Pin:%s has inconsistent restrictions\n", pin->pinname ) ; M( ERRMSG, "load_soft_pins", YmsgG ) ; abortPin = TRUE ; } } else if( numrestricts == 0 && parent_restricts != 0 ){ Yset_comp( side_set ) ; for( restrict1 = 1;restrict1<=parent_restricts;restrict1++ ){ Yset_add( side_set, spin->restrict1[restrict1] ) ; } } /* else if numrestricts == 0 && parent_restricts == 0 ) */ /* don't have to do anything for this case */ /* now prepare for possible next level of hierarchy */ numrestricts = parent_restricts ; parent = spin->parent ; } if( abortPin ){ continue ; } /* now enumerate the set of valid sides for the pin */ numsides = Yset_size( side_set ) ; if( numsides == 0 ){ sprintf( YmsgG, "Pin:%s has no valid side\n", pin->pinname ) ; M( ERRMSG, "load_soft_pins", YmsgG ) ; continue ; } for(curside=Yset_enumerate(side_set);curside;curside=curside->next ){ loadside( pSideArray, curside->node, 1.0 / numsides ) ; } } Yset_free( side_set ) ; } /* end load_soft_pins */ graywolf-0.1.4+20170307gite1bf319/src/twmc/fixcell.c000066400000000000000000000401251305746555600213210ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: fixcell.c DESCRIPTION:places fixed cells in the correct position during a configuration. CONTENTS: updateFixedCells( initializeFlag ) BOOL initializeFlag ; update_fixed_record( fptr ) FIXEDBOXPTR fptr ; build_active_array() build_soft_array() determine_origin( x, y, left_not_right, bottom_not_top ) INT *x, *y ; BOOL *left_non_right, *bottom_not_top ; DATE: Sept 28, 1988 REVISIONS: Oct 27, 1988 - modified update fixed cells so that it could handle the following cases: fixed at a point, cell fixed in a neighborhood, group neighborhood fixed at a point, group neighborhood free. Added build_active_array which holds all active core cell including supercells and groupcells to make uloop more efficient. Jan 20, 1989 - added build_soft_array() to make soft pin moves more efficient. Feb 26, 1989 - added determine_origin for graphics interface. Mar 13, 1989 - split updateFixedCells to update_fixed_record to anticipate group cell moves. Apr 27, 1989 - added stdcell to list of active cells. May 10, 1989 - now use the HOWMANYORIENT field for valid orientation calculation. Apr 17, 1990 - added error checking. May 4, 1990 - fixed for standard cell case. Mon Feb 4 02:06:08 EST 1991 - updated determine origin since arguments changed from BOOL to char *. Sun May 5 14:25:12 EDT 1991 - added prototypes. Fixed missing argument to update_fix_record. Fixed error checking. Wed Jul 24 20:43:22 CDT 1991 - added delete function for fixing cells. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) fixcell.c version 3.9 11/23/91" ; #endif #include #include #include #include /* defined routes for error checking */ VOID updateFixedCells( P1(BOOL initializeFlag) ) ; static VOID update_fixed_record( P3(CELLBOXPTR ptr,FIXEDBOXPTR fptr, BOOL initFlag ) ) ; VOID init_fixcell( P4(INT left, INT bottom, INT right, INT top ) ) ; VOID build_active_array() ; VOID build_soft_array() ; VOID determine_origin( P4(INT *x, INT *y, char *left_not_right, char *bottom_not_top ) ) ; static INT initialS = FALSE ; static INT newxspanS ; static INT newyspanS ; static INT oldxspanS ; static INT oldyspanS ; VOID updateFixedCells( initializeFlag ) BOOL initializeFlag ; { INT i ; CELLBOXPTR ptr ; FIXEDBOXPTR fptr ; /* calculate new span of the core region */ newxspanS = blockrG - blocklG ; newyspanS = blocktG - blockbG ; /* update positions of fixed cells */ for( i=1;i<=endsuperG;i++ ){ ptr = cellarrayG[i] ; /* for core cells check fixed record */ /* for group cells check group record */ if( ptr->celltype == GROUPCELLTYPE ){ ASSERTNCONT( ptr->group, "updateFixedCells", "pointer null"); fptr = ptr->group->fixed ; } else { fptr = ptr->fixed ; } update_fixed_record( ptr, fptr, initializeFlag ) ; if( initializeFlag && ptr->celltype == GROUPCELLTYPE ){ /* now we can add tiles to group */ initializeCorner( i ) ; addCorner( fptr->x1, fptr->y1 ) ; /* lower left */ addCorner( fptr->x1, fptr->y2 ) ; /* upper left */ addCorner( fptr->x2, fptr->y2 ) ; /* upper right */ addCorner( fptr->x2, fptr->y1 ) ; /* lower right */ processCorners( 4 ) ; } } } /* end updateFixCells */ /* update all the variables in the fixed box record - that is the */ /* the neighborhood and/or the center of the cell for a fixed point */ static VOID update_fixed_record( ptr, fptr, initFlag ) CELLBOXPTR ptr ; FIXEDBOXPTR fptr ; BOOL initFlag ; { INT x1, x2, y1, y2 ; BOOL error_flag = FALSE ; DOUBLE temp ; if( fptr ){ D( "update_fixed_record", fprintf( stderr, "cell:%s\n", ptr->cname ) ; fprintf( stderr, "\tinitialS:%d\n", initialS ) ; fprintf( stderr, "\toldxspanS:%d ", oldxspanS ) ; fprintf( stderr, "\toldyspanS:%d\n", oldyspanS ) ; fprintf( stderr, "\tnewxspanS:%d ", newxspanS ) ; fprintf( stderr, "\tnewyspanS:%d\n", newyspanS ) ; fprintf( stderr, "\txc:%d yc:%d x1:%d y1:%d x2:%d y2:%d\n", fptr->xcenter, fptr->ycenter, fptr->xloc1,fptr->yloc1,fptr->xloc2,fptr->yloc2 ) ; fprintf( stderr, "\tx1:%d y1:%d x2:%d y2:%d\n", fptr->leftNotRight,fptr->bottomNotTop, fptr->leftNotRight2,fptr->bottomNotTop2 ) ; ) ; /* end debug macro */ if( fptr->fixedType != POINTFLAG ){ if( initialS ){ /* get two points of neighborhood */ /* POINT ONE */ temp = (DOUBLE) fptr->xloc1 / oldxspanS * newxspanS ; if( fptr->leftNotRight ){ /* from left edge */ x1 = blocklG + (INT) temp ; } else { /* from right edge = blockx */ x1 = blockrG - (INT) temp ; } temp = (DOUBLE) fptr->yloc1 / oldyspanS * newyspanS ; if( fptr->bottomNotTop ){ /* from bottom edge = 0 */ y1 = blockbG + (INT) temp ; } else { /* from top edge = blocky */ y1 = blocktG - (INT) temp ; } /* POINT TWO */ temp = (DOUBLE) fptr->xloc2 / oldxspanS * newxspanS ; if( fptr->leftNotRight2 ){ /* from left edge */ x2 = blocklG + (INT) temp ; } else { /* from right edge = blockx */ x2 = blockrG - (INT) temp ; } temp = (DOUBLE) fptr->yloc2 / oldyspanS * newyspanS ; if( fptr->bottomNotTop2 ){ /* from bottom edge = 0 */ y2 = blockbG + (INT) temp ; } else { /* from top edge = blocky */ y2 = blocktG - (INT) temp ; } } else { /* get two points of neighborhood */ /* POINT ONE */ if( fptr->leftNotRight ){ /* from left edge */ x1 = blocklG + fptr->xloc1 ; } else { /* from right edge = blockx */ x1 = blockrG - fptr->xloc1 ; } if( fptr->bottomNotTop ){ /* from bottom edge = 0 */ y1 = blockbG + fptr->yloc1 ; } else { /* from top edge = blocky */ y1 = blocktG - fptr->yloc1 ; } /* POINT TWO */ if( fptr->leftNotRight2 ){ /* from left edge */ x2 = blocklG + fptr->xloc2 ; } else { /* from right edge = blockx */ x2 = blockrG - fptr->xloc2 ; } if( fptr->bottomNotTop2 ){ /* from bottom edge = 0 */ y2 = blockbG + fptr->yloc2 ; } else { /* from top edge = blocky */ y2 = blocktG - fptr->yloc2 ; } } /* sort points */ fptr->x1 = MIN( x1, x2 ) ; fptr->x2 = MAX( x1, x2 ) ; fptr->y1 = MIN( y1, y2 ) ; fptr->y2 = MAX( y1, y2 ) ; if(!(initFlag)){ /* check to make sure neighborhood is inside core */ if( fptr->x1 < blocklG ){ if( iterationG >= 2 ) fptr->x1 = blocklG ; error_flag = TRUE ; } if( fptr->x1 > blockrG ){ if( iterationG >= 2 ) fptr->x1 = blockrG ; error_flag = TRUE ; } if( fptr->x2 < blocklG ){ if( iterationG >= 2 ) fptr->x2 = blocklG ; error_flag = TRUE ; } if( fptr->x2 > blockrG ){ if( iterationG >= 2 ) fptr->x2 = blockrG ; error_flag = TRUE ; } if( fptr->y1 < blockbG ){ if( iterationG >= 2 ) fptr->y1 = blockbG ; error_flag = TRUE ; } if( fptr->y1 > blocktG ){ if( iterationG >= 2 ) fptr->y1 = blocktG ; error_flag = TRUE ; } if( fptr->y2 < blockbG ){ if( iterationG >= 2 ) fptr->y2 = blockbG ; error_flag = TRUE ; } if( fptr->y2 > blocktG ){ if( iterationG >= 2 ) fptr->y2 = blocktG ; error_flag = TRUE ; } } /* now perform calculations for speed */ fptr->xcenter = (fptr->x1 + fptr->x2) / 2 ; fptr->ycenter = (fptr->y1 + fptr->y2) / 2 ; fptr->xspan = ABS(fptr->x1 - fptr->x2) ; fptr->yspan = ABS(fptr->y1 - fptr->y2) ; if( error_flag ){ sprintf( YmsgG, "cell:%s neighborhood larger than core\n", ptr->cname ) ; M( WARNMSG,"update_fixed_cells", YmsgG ) ; if( iterationG >= 2 ){ /* we can't do anything with this constraint */ /* throw it out */ if( ptr->celltype == GROUPCELLTYPE ){ fptr = ptr->group->fixed ; Ysafe_free( fptr ) ; ptr->group->fixed = NIL(FIXEDBOXPTR) ; } else { fptr = ptr->fixed ; Ysafe_free( fptr ) ; ptr->fixed = NIL(FIXEDBOXPTR) ; } M( WARNMSG,NULL,"\tconstraint ignored...\n" ) ; } } } else { /* cell is fixed at a point */ if( initialS ){ temp = (DOUBLE) fptr->xcenter / oldxspanS * newxspanS ; if( fptr->leftNotRight ){ /* from left edge */ ptr->xcenter = blocklG + (INT) temp ; } else { /* from right edge = blockx */ ptr->xcenter = blockrG - (INT) temp ; } if( fptr->bottomNotTop ){ /* from bottom edge = 0 */ ptr->ycenter = blockbG + fptr->ycenter ; } else { /* from top edge = blocky */ ptr->ycenter = blocktG - fptr->ycenter ; } } else { if( fptr->leftNotRight ){ /* from left edge */ ptr->xcenter = blocklG + fptr->xcenter ; } else { /* from right edge = blockx */ ptr->xcenter = blockrG - fptr->xcenter ; } if( fptr->bottomNotTop ){ /* from bottom edge = 0 */ ptr->ycenter = blockbG + fptr->ycenter ; } else { /* from top edge = blocky */ ptr->ycenter = blocktG - fptr->ycenter ; } } if(!(initFlag)){ /* now perform error checking to make sure inside core */ if( ptr->xcenter < blocklG ){ if( iterationG >= 2 ) ptr->xcenter = blocklG ; error_flag = TRUE ; } if( ptr->xcenter > blockrG ){ if( iterationG >= 2 ) ptr->xcenter = blockrG ; error_flag = TRUE ; } if( ptr->ycenter < blockbG ){ if( iterationG >= 2 ) ptr->ycenter = blockbG ; error_flag = TRUE ; } if( ptr->ycenter > blockrG ){ if( iterationG >= 2 ) ptr->ycenter = blockrG ; error_flag = TRUE ; } } if( error_flag ){ sprintf( YmsgG, "cell:%s fix point larger than core\n", ptr->cname ) ; M( WARNMSG,"update_fixed_cells", YmsgG ) ; if( iterationG >= 2 ){ /* we can't do anything with this constraint */ /* throw it out */ if( ptr->celltype == GROUPCELLTYPE ){ fptr = ptr->group->fixed ; Ysafe_free( fptr ) ; ptr->group->fixed = NIL(FIXEDBOXPTR) ; } else { fptr = ptr->fixed ; Ysafe_free( fptr ) ; ptr->fixed = NIL(FIXEDBOXPTR) ; } M( WARNMSG,NULL,"\tconstraint ignored...\n" ) ; } } } } /* end for loop */ } /* end function update_fixed_record */ VOID init_fixcell( left, bottom, right, top ) INT left, bottom, right, top ; { initialS = TRUE ; oldxspanS = right - left ; oldyspanS = top - bottom ; if( oldxspanS <= 0 ){ M( ERRMSG, "init_fixcell", "initial x core span <= 0\n" ) ; initialS = FALSE ; } if( oldyspanS <= 0 ){ M( ERRMSG, "init_fixcell", "initial y core span <= 0\n" ) ; initialS = FALSE ; } } /* end init_fixcell */ /* build active cell list from cells that aren't fixed */ VOID build_active_array() { INT i, cell ; CELLBOXPTR cptr ; /* first determine number of active cells */ activecellsG = 0 ; for( i=1;i<=totalcellsG;i++ ){ cptr = cellarrayG[i] ; if( cptr->fixed ){ if( cptr->celltype == CUSTOMCELLTYPE || cptr->celltype == SOFTCELLTYPE || cptr->celltype == STDCELLTYPE ){ /* must check to orientations are all fixed also */ if( cptr->orientList[HOWMANYORIENT] >= 2 ){ /* cell is not totally inactive it may rotate */ activecellsG++ ; } } } else if( cptr->celltype == CUSTOMCELLTYPE || cptr->celltype == SOFTCELLTYPE || cptr->celltype == SUPERCELLTYPE || cptr->celltype == STDCELLTYPE || cptr->celltype == GROUPCELLTYPE ){ activecellsG++ ; } } /* now build array */ activeCellarrayG = (CELLBOXPTR *) Ysafe_malloc( (activecellsG+1) * sizeof(CELLBOXPTR) ) ; /* now loop again filling in array */ cell = 0 ; for( i=1;i<=totalcellsG;i++ ){ cptr = cellarrayG[i] ; if( cptr->fixed ){ if( cptr->celltype == CUSTOMCELLTYPE || cptr->celltype == SOFTCELLTYPE || cptr->celltype == STDCELLTYPE ){ if( cptr->orientList[HOWMANYORIENT] >= 2 ){ /* cell is not totally inactive it may rotate */ activeCellarrayG[++cell] = cptr ; } } } else if( cptr->celltype == CUSTOMCELLTYPE || cptr->celltype == SOFTCELLTYPE || cptr->celltype == SUPERCELLTYPE || cptr->celltype == STDCELLTYPE || cptr->celltype == GROUPCELLTYPE ){ activeCellarrayG[++cell] = cptr ; } } ASSERT( cell == activecellsG,"build_active_array", "Problem with count" ) ; } /* end build_active_array */ /* build softPinArrayG so that soft pin moves are more efficient */ /* softPinArray will contain the cellptrs of all softcells which */ /* have pins that can move. The zeroth element will contain howmany */ VOID build_soft_array() { #define HOWMANY 0 /* this tells the size of the array */ INT i, cell ; CELLBOXPTR cptr ; INT softPins ; softPins = 0 ; if( numsoftG > 0 || numstdcellG > 0 ){ /* first determine number of softcell with uncommitted pins */ for( i=1;i<=totalcellsG;i++ ){ cptr = cellarrayG[i] ; if( cptr->celltype == SOFTCELLTYPE || cptr->celltype == STDCELLTYPE ){ if( cptr->numpins > 0 ){ softPins++ ; } } } /* now build array */ softPinArrayG = (CELLBOXPTR *) Ysafe_malloc( (softPins+1) * sizeof(CELLBOXPTR) ) ; /* now loop again filling in array */ cell = 0 ; for( i=1;i<=totalcellsG;i++ ){ cptr = cellarrayG[i] ; if( cptr->celltype == SOFTCELLTYPE || cptr->celltype == STDCELLTYPE ){ if( cptr->numpins > 0 ){ softPinArrayG[++cell] = cptr ; } } } ASSERT( cell == softPins,"build_soft_array", "Problem with count" ) ; softPinArrayG[HOWMANY] = (CELLBOXPTR) softPins ; } else { softPinArrayG = (CELLBOXPTR *) Ysafe_malloc( sizeof(CELLBOXPTR) ) ; softPinArrayG[HOWMANY] = (CELLBOXPTR) softPins ; /* zero */ } } /* end build_soft_array */ /* In fixing a cell, determine which side of the core to reference */ /* cell so that changes to the position of the cell due to core size */ /* changes will be minimized. */ VOID determine_origin( x, y, left_not_right, bottom_not_top ) INT *x, *y ; /* point of reference */ char *left_not_right, *bottom_not_top ; { if( *x <= blockmxG ){ strcpy( left_not_right, "L" ) ; } else { strcpy( left_not_right, "R" ) ; /* reference to right side need to change x coordinate */ *x = blockrG - *x ; } if( *y <= blockmyG ){ strcpy( bottom_not_top, "B" ) ; } else { strcpy( bottom_not_top, "T" ) ; /* reference to top side need to change x coordinate */ *y = blocktG - *y ; } } /* end determine_origin */ delete_fix_constraint( cell ) INT cell ; { CELLBOXPTR ptr ; ptr = cellarrayG[cell] ; if( ptr->fixed != (FIXEDBOXPTR)NULL ){ Ysafe_free(ptr->fixed) ; } ptr->fixed = NIL(FIXEDBOXPTR) ; ptr->class = 0 ; } /* end delete_fix_constraint */ graywolf-0.1.4+20170307gite1bf319/src/twmc/genorient.c000066400000000000000000000313101305746555600216610ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: genorient.c DESCRIPTION:generate all eight orientation for tiles. CONTENTS: genorient( lowerBound, upperBound ) INT lowerBound, upperBound ; trans_bbox( ptr ) CELLBOXPTR ptr ; loadTermArray() adjust_lr( orient, height, width, left, right ) INT orient, height, *left, *right ; adjust_lr( orient, height, width, bottom, top ) INT orient, height, *bottom, *top ; DATE: Feb 8, 1988 REVISIONS: Aug 17,1988 - add upper and lower bounds as parameters to genorient and split out terminal array code to loadTermArray function. Now genorient can be applied to a single cell. Mar 20, 1989 - added adjust_lr and adjust_bt to consolidate code. Mar 30, 1989 - changed tile datastructure. Apr 2, 1989 - added trans_bbox to make code more general. Sep 19, 1989 - trans_bbox now translate everything from the zero orientation. Oct 14, 1990 - Fixed problem with vertices with initial orientation. Oct 22, 1990 - Fixed initial orientation problem for equivalent. Thu Jan 17 00:53:44 PST 1991 - now take care of translating the new numpins field using translate_numpins. Fri Jan 25 18:04:43 PST 1991 - made consistent with Ylib. Wed Jan 30 14:13:36 EST 1991 - now left justify orientation rotations. Sat Feb 23 00:21:10 EST 1991 - updated for new pad placement code. Wed Mar 13 20:15:22 CST 1991 - now allow both orientations for a given pad side. Thu Apr 18 01:32:23 EDT 1991 - now check for valid orientations. Also translate all bounding box since it may become valid later. Sun May 5 14:27:53 EDT 1991 - fixed problem with orienting bounboxes. Had used wrong translation function. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) genorient.c (Yale) version 3.13 5/5/91" ; #endif #include #include #include #include /* genorient works on range [lowerBound..upperBound] inclusive */ genorient(lowerBound, upperBound) INT lowerBound, upperBound ; { INT i ; /* counter */ INT cell ; /* current cell */ INT x, y ; /* used to translate the pins */ INT orient ; /* user specified orientation */ INT saveorient ; /* initial orientation */ INT bhgt, blen ; /* bounding box height, length */ INT inverse ; /* inverse orientation */ INT numinst ; /* number of cell instances */ INT pt ; /* counter */ INT *xvert ; /* xvertices */ INT *yvert ; /* yvertices */ INSTBOXPTR instptr ; /* instance pointer */ BOUNBOXPTR bounptr ; /* bounding box pointer */ PINBOXPTR pin ; /* translate the pins */ TILEBOXPTR tile ; /* translate the tiles */ PADBOXPTR padptr ; /* pad information */ CELLBOXPTR ptr ; EQUIVPTR eqptr ; /* current equivalent pin */ /* need to update for instances */ for( cell = lowerBound ; cell <= upperBound ; cell++ ) { ptr = cellarrayG[cell] ; orient = ptr->orient ; if( orient < 0 ){ /* these are cells which have their initial orientation */ /* specified to nonzero-however vertices given for zero */ ptr->orient = - orient ; orient = 0 ; } /* ************** INITIAL ORIENTATION NOT ZERO ************ */ /* rotate to orientation 0 perform the inverse operation if */ /* necessary */ padptr = ptr->padptr ; if( orient ){ if( padptr ){ switch (padptr->padside) { case L: /* rotate 270 | -90 */ inverse = 6 ; break; case T: /* rotate180 */ inverse = 3 ; break; case R: /* rotate90 */ inverse = 7 ; break; case ALL: /* this is the case of no restriction */ /* and we came from previous floorplanning */ if( orient == 1 || orient == 3 ){ /* this is the top side */ inverse = orient ; break ; } else if( orient == 4 || orient == 6 ){ /* this is the right side */ if( orient == 6 ){ inverse = 7 ; } else { inverse = 4 ; } break ; } else if( orient == 5 || orient == 7 ){ /* this is the left side */ if( orient == 6 ){ inverse = 6 ; } else { inverse = 5 ; } break ; } else if( orient == 2 ){ /* this is the bottom side */ inverse = 2 ; break ; } case B: default: OUT1("\nNON-PADS or PAD w/o valid side rotatation\n"); break; } } else { inverse = Ytrans_inv_orient( orient ) ; } if( instptr = ptr->instptr ){ numinst = instptr->numinstances ; } else { numinst = 1 ; } /* first the bounding box */ bounptr = ptr->bounBox[0] ; /* now init the translation routines using bounding box */ Ytrans_init( bounptr->l,bounptr->b,bounptr->r,bounptr->t, inverse ) ; YtranslateC( &(bounptr->l), &(bounptr->b), &(bounptr->r),&(bounptr->t), inverse ) ; /* next the tiles */ for( tile = ptr->tiles; tile; tile = tile->next ){ YtranslateC( &(tile->left), &(tile->bottom), &(tile->right),&(tile->top), inverse ) ; YtranslateC( &(tile->orig_left), &(tile->orig_bottom), &(tile->orig_right),&(tile->orig_top), inverse ) ; Ytranslatef( &(tile->lweight), &(tile->bweight), &(tile->rweight),&(tile->tweight), inverse ) ; } /* may need to update this for instances */ /* will need to check datastructures */ /* next the vertices */ xvert = ptr->vertices->x ; yvert = ptr->vertices->y ; for( pt = 1; pt <= ptr->numsides; pt++ ){ REL_POST( inverse, x, y, xvert[pt], yvert[pt], 0, 0 ) ; ptr->vertices->x_orig[pt] = xvert[pt] = x ; ptr->vertices->y_orig[pt] = yvert[pt] = y ; } translate_numpins( ptr ) ; /* next the fixed terminals */ for( pin = ptr->pinptr; pin; pin = pin->nextpin ){ REL_POST( inverse, x, y, /* result */ pin->txpos, pin->typos, /* cell relative */ 0, 0 ) ; /* center */ pin->txpos = x ; pin->typos = y ; pin->xpos = x + ptr->xcenter ; pin->ypos = y + ptr->ycenter ; /* do the number of instances */ for( i = 0; i < numinst; i++ ){ REL_POST( inverse, x, y, /* result */ pin->txpos_orig[i], pin->typos_orig[i], /* cell relative */ 0, 0 ) ; /* center */ pin->txpos_orig[i] = x ; pin->typos_orig[i] = y ; } /* end for loop on instances */ /* now do equivalent pins */ for( eqptr=pin->eqptr; eqptr; eqptr=eqptr->next ){ for( i = 0; i < numinst; i++ ){ REL_POST( inverse, x, y, /* result */ eqptr->txpos[i], eqptr->typos[i], /* cell relative */ 0, 0 ) ; /* center */ eqptr->txpos[i] = x ; eqptr->typos[i] = y ; } } } } /* ************** INITIAL ORIENTATION NOT ZERO ************ */ saveorient = ptr->orient ; ptr->orient = 0 ; trans_bbox( ptr ) ; ptr->orient = saveorient ; if( padptr ){ /* now set the height and with of the pads */ bounptr = ptr->bounBox[0] ; padptr->length = bounptr->r - bounptr->l ; padptr->height = bounptr->t - bounptr->b ; } else { (VOID) check_valid_orient( ptr ) ; } } /* end loop on cells */ } /* end genorient */ /* regenorient works on range [lowerBound..upperBound] inclusive */ /* recalculates the bounding boxes and updates all the views */ /* works in an incremental manner */ regenorient(lowerBound, upperBound) INT lowerBound, upperBound ; { INT cell ; INT l, r, b, t ; INT xdev, ydev ; CELLBOXPTR ptr ; TILEBOXPTR tileptr ; BOUNBOXPTR bounptr ; for( cell = lowerBound ; cell <= upperBound ; cell++ ) { ptr = cellarrayG[cell] ; if( ptr->boun_valid ){ continue ; } /* recalculate the bounding box from the tiles */ l = INT_MAX ; b = INT_MAX ; r = INT_MIN ; t = INT_MIN ; for( tileptr=ptr->tiles; tileptr; tileptr=tileptr->next ){ l = MIN( l, tileptr->left ) ; b = MIN( b, tileptr->bottom ) ; r = MAX( r, tileptr->right ) ; t = MAX( t, tileptr->top ) ; } /* at this point we have found bounding box but it may */ /* not be centered correctly due to rounding error */ /* find largest deviation from center point and make */ /* it symmetrical */ l = ABS( l ) ; b = ABS( b ) ; xdev = MAX( l, r ) ;/* find deviation in x */ ydev = MAX( b, t ) ;/* find deviation in y */ bounptr = ptr->bounBox[0] ; bounptr->l = - xdev ; bounptr->r = xdev ; bounptr->b = - ydev ; bounptr->t = ydev ; trans_bbox( ptr ) ; } } /* end regenorient */ /* trans_bbox - translate bounding box into 8 views */ trans_bbox( ptr ) CELLBOXPTR ptr ; { INT orient ; INT bhgt, blen ; BOUNBOXPTR boun0, bounptr ; if( ptr->boun_valid ){ /* correct no need to process */ return ; } /* all orientations are generated relative to zero */ /* ************************************************** */ for( orient = 1 ; orient <= 7 ; orient++ ) { /* move bounding box information over to new orientation */ boun0 = ptr->bounBox[0] ; bounptr = ptr->bounBox[orient] ; bounptr->r = boun0->r ; bounptr->l = boun0->l ; bounptr->t = boun0->t ; bounptr->b = boun0->b ; YtranslateT( &(bounptr->l), &(bounptr->b), &(bounptr->r),&(bounptr->t), orient ) ; } ptr->boun_valid = TRUE ; } /* end trans_bbox() */ /* allocate space for and load termarray */ loadTermArray() { INT net ; PINBOXPTR pinptr ; /* load termarray */ for( net = 1 ; net <= numnetsG ; net++ ) { for( pinptr=netarrayG[net]->pins;pinptr; pinptr = pinptr->next ) { termarrayG[ pinptr->pin ] = pinptr ; } } } /* end loadTermArray */ translate_numpins( ptr ) CELLBOXPTR ptr ; { INT pt ; /* point counter */ INT minx ; /* looking for lowest y pt */ INT miny ; /* looking for lowest y pt */ INT side1 ; /* where the first side is */ INT oldpt ; /* the place in the old array */ INT *xvert ; /* xvertices */ INT *yvert ; /* yvertices */ FLOAT *tmp ; /* array of the numpins per side */ xvert = ptr->vertices->x ; yvert = ptr->vertices->y ; /* find the bottom left so we have side 1 */ miny = INT_MAX ; minx = INT_MAX ; tmp = (FLOAT *) Yvector_alloc( 1, ptr->numsides, sizeof(FLOAT) ); for( pt = 1; pt <= ptr->numsides; pt++ ){ tmp[pt] = ptr->vertices->numpins[pt] ; if( yvert[pt] < miny ){ miny = yvert[pt] ; minx = xvert[pt] ; side1 = pt ; } else if( yvert[pt] == miny ){ if( xvert[pt] < minx ){ minx = xvert[pt] ; side1 = pt ; } } } /* now reload the numpins in the zero view */ for( pt = 1; pt <= ptr->numsides; pt++ ){ oldpt = pt + side1 - 2 ; oldpt = oldpt % ptr->numsides ; /* now in the range 0..numsides-1 */ oldpt++ ; /* now in the range 1..numsides */ ptr->vertices->numpins[pt] = tmp[oldpt] ; } } /* end translate_numpins */ graywolf-0.1.4+20170307gite1bf319/src/twmc/gmain.c000066400000000000000000000200251305746555600207630ustar00rootroot00000000000000/* * Copyright (C) 1990-1991 Yale University * Copyright (C) 2014 Ruben Undheim * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: gmain.c DESCRIPTION:This file now contain calls the channel graph generator program. CONTENTS: DATE: Feb 28, 1990 REVISIONS: Thu Jan 17 00:49:52 PST 1991 - now read side information. Thu Mar 7 01:46:48 EST 1991 - added call to sleep to prevent a SUN race condition. Wed May 1 19:17:23 EDT 1991 - added switchbox keyword so we can ignore these areas during wire estimation. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) gmain.c version 3.8 5/1/91" ; #endif #define DENS_DEFS #include #include #include #include #include #include "config-build.h" #define GENGRAPHPROG "gengraph" #define GENGRAPHPATH "../gengraph" static free_routing_tiles(); /* -------------------------------------------------------------------- There are two ways to call the channel graph generator. 1. updateNotChan == FALSE: call the channel graph generator to build graph and input files for the global router. 2. updateNotChan == TRUE: call the channel graph generator to read the density information from the global router and build the routing tiles. We will update the routing tiles in this file. -------------------------------------------------------------------- */ gmain( updateNotChan ) BOOL updateNotChan ; /* if true update routing tiles otherwise normal */ { char filename[LRECL] ; char *Yrelpath() ; char *pathname ; char *twdir ; /* path of TimberWolf directory */ char *getenv() ; /* used to get TWDIR environment variable */ INT windowId ; /* windowId of current window */ char buffer[LRECL], *bufferptr ; char **tokens ; /* for parsing file */ INT numtokens, line ; INT closegraphics() ; BOOL abort ; /* whether to abort program */ INT cell ; INT xc, yc ; /* xcenter and ycenter of cell */ INT side ; /* side that routing tile is on */ INT xcenter, ycenter ; /* xcenter and ycenter of cell */ INT x1, x2, y1, y2 ; INT ncells ; /* the number of cells in graph */ CELLBOXPTR cptr ; RTILEBOXPTR tmp ; /* current routing tile */ RTILEBOXPTR tile ; /* current routing tile */ FILE *fp ; BOOL stateSaved = FALSE ; /* TRUE when graphics parasite mode */ /* ################### begin gengraph execution ################## */ /* find the path of compactor relative to main program */ pathname = Yrelpath( argv0G, GENGRAPHPATH ) ; if( !(YfileExists(pathname))){ if( twdir = TWFLOWDIR ){ sprintf( filename, "%s/bin/%s", twdir, GENGRAPHPROG ) ; pathname = Ystrclone( filename ) ; } } if( updateNotChan ){ /* never use graphics to update channel graph */ sprintf( YmsgG, "%s -nr %s", pathname, cktNameG ) ; } else { if( doGraphicsG ){ G( windowId = TWsaveState() ) ; stateSaved = TRUE ; sprintf( YmsgG, "%s -w %s %d", pathname,cktNameG,windowId ) ; } else { sprintf( YmsgG, "%s -n %s", pathname, cktNameG ) ; } } M( MSG, NULL, YmsgG ) ; M( MSG, NULL, "\n" ) ; /* Ysystem will kill program if catastrophe occurred */ Ysystem( GENGRAPHPROG, ABORT, YmsgG, closegraphics ) ; if( stateSaved ){ sleep(1) ; /* if we save the graphics state we need to restore it */ G( TWrestoreState() ) ; } Ysafe_free( pathname ) ; /* free name created in Yrelpath */ /* ################### end of gengraph execution ################# */ if( !(updateNotChan) ){ /* no more work to do */ return ; } /* ********************* read routing tiles *********************** */ free_routing_tiles() ; /* number of cells is core cells + 4 pad blocks */ ncells = numcellsG + 4 ; /* allocate list of routing tiles for cells */ routingTilesG = (RTILEBOXPTR *) Ysafe_calloc( ncells + 1, sizeof(RTILEBOXPTR) ); /* add number of cells to routing tile structure */ routingTilesG[0] = (RTILEBOXPTR) ncells ; sprintf( filename, "%s.mtle", cktNameG ) ; fp = TWOPEN( filename, "r", ABORT ) ; /* parse file */ line = 0 ; abort = FALSE ; while( bufferptr=fgets(buffer,LRECL,fp )){ /* parse file */ line ++ ; /* increment line number */ tokens = Ystrparser( bufferptr, " :\t\n", &numtokens ); if( numtokens == 0 ){ /* skip over empty lines */ continue ; } else if( numtokens == 16 || numtokens == 17 ){ cell = atoi( tokens[1] ) ; xc = atoi( tokens[3] ) ; yc = atoi( tokens[5] ) ; x1 = atoi( tokens[7] ) ; y1 = atoi( tokens[9] ) ; x2 = atoi( tokens[11] ) ; y2 = atoi( tokens[13] ) ; side = atoi( tokens[15] ) ; if( tmp = routingTilesG[cell] ){ tile = routingTilesG[cell] = (RTILEBOXPTR) Ysafe_malloc( sizeof(RTILEBOX) ); tile->next = tmp ; } else { tile = routingTilesG[cell] = (RTILEBOXPTR) Ysafe_malloc( sizeof(RTILEBOX) ); tile->next = NULL ; } /* check xcenter of the cells to see if we must adjust tile */ if( cell <= numcellsG ){ cptr = cellarrayG[cell] ; } else { cptr = cellarrayG[endpadgrpsG+cell-numcellsG] ; } xcenter = cptr->xcenter ; ycenter = cptr->ycenter ; tile->x1 = x1 + xc - xcenter ; tile->y1 = y1 + yc - ycenter ; tile->x2 = x2 + xc - xcenter ; tile->y2 = y2 + yc - ycenter ; tile->side = side ; if( numtokens == 17 ){ if( strcmp( tokens[16], "switchbox" ) == STRINGEQ ){ tile->switchbox = TRUE ; } else { tile->switchbox = FALSE ; } } else { tile->switchbox = FALSE ; } } else { sprintf( YmsgG, "Syntax error on line:%d\n", line ) ; M(ERRMSG, "gmain", YmsgG ) ; abort = TRUE ; } } if( abort ){ closegraphics() ; YexitPgm( PGMFAIL ) ; } TWCLOSE( fp ) ; /* ********************** end routing tiles ********************** */ } /* end gmain */ init_routing_tiles() { routingTilesG = NULL ; } /* end init_routing_tiles */ static free_routing_tiles() { INT cell ; /* cell counter */ RTILEBOXPTR freeptr ; /* free tile */ RTILEBOXPTR rptr ; /* traverse tiles */ /* free previous routing tiles if they exist */ if( routingTilesG ){ for( cell = 1 ; cell <= numcellsG; cell++ ){ for( rptr = routingTilesG[cell]; rptr; ){ freeptr = rptr ; rptr = rptr->next ; Ysafe_free( freeptr ) ; } } Ysafe_free( routingTilesG ) ; routingTilesG = NULL ; } } /* end free_routing_tiles */ graywolf-0.1.4+20170307gite1bf319/src/twmc/graphics.c000066400000000000000000001122501305746555600214720ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: graphics.c DESCRIPTION:graphics routines CONTENTS: DATE: Feb 01, 1988 REVISIONS: Feb 26, 1989 - added moveCells so that cell bin structures could be updated. - added determine_origin so that fixcells will be glued to the nearest corner of the bar. - added drawLabel toggle and simple pick color procedure. Mar 02, 1989 - changed argument to exitPgm. - changed call to core adjustment routine. Mar 11, 1989 - removed dummy routines and added graphics conditional compile switch. Mar 16, 1989 - changed to new data structure. Mar 27, 1989 - fixed problem with cell neighborhoods. May 8, 1989 - added fit to data. May 14, 1989 - attempted to add parasite mode for graphics. May 18, 1989 - added drawBlocks code for partitioning. Jun 21, 1989 - fixed problem with fixed cell swap classes. Jun 23, 1989 - added reset cell, reconfig functions. modified setWindowSize to look at data. Sep 25, 1989 - deleted menu items now in genrows. Also now use TWstandard colors. Apr 23, 1990 - added mst function, scaling of pins, and tell point functions. Oct 14, 1990 - rewrote for new graphics routines and added arbitrary figures. Sun Dec 16 00:37:44 EST 1990 - added analog header and fixed for new version of the dialog box. Mon Feb 4 02:08:23 EST 1991 - fixed bug in edit cells and reworked fixCell calls. Also added new wire estimator. Thu Apr 18 01:34:10 EDT 1991 - made valid orientations functional. Sat Apr 27 14:38:12 EDT 1991 - added draw_orient. Sun May 5 14:28:47 EDT 1991 - now draw core at right coordinates. Wed Jul 24 20:44:18 CDT 1991 - fixed problems with fixed cells. Now there is an unfix mechanism. Thu Aug 22 22:10:09 CDT 1991 - fixed problem with fixed cells moving during pairwise flips. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) graphics.c (Yale) version 3.17 10/18/91" ; #endif #ifndef NOGRAPHICS #include #include #include #include #include #include #include #include #include #include #include #define CELLEST 0 #define CELLBORDER 1 #define TRUECELL 2 #define INTRO "Welcome to TimberWolfMC" #define CELLCOLOR TWGREEN #define ORIGCOLOR TWYELLOW #define WIREESTCOLOR TWORANGE #define NETCOLOR TWRED #define PINCOLOR TWBLACK #define BINCOLOR TWBLUE #define BLACK TWBLACK #define NEIGHBORCOLOR TWCYAN #define FCOLOR TWYELLOW #define MODE 2 #define MENUP "mc_menu" /* #define DEVELOPMENU */ /* During development use TWread_menus in place of menuS */ /* to create menu record, ie. TWread_menus(MENUP) */ #ifdef DEVELOPMENU #define MENU (TWMENUPTR ) TWread_menus(MENUP) #else #define MENU menuS #endif /* #define DEVELOPDIALOG */ #ifndef DEVELOPDIALOG #ifdef TI #include #else #include #endif #else /* DEVELOPDIALOG */ static TWDIALOGPTR dialogS ; #endif /* DEVELOPDIALOG */ /* ***************************************************************** DUMP CURRENT MC CONFIGURATION. USER INTERFACE */ static BOOL avoidDump = FALSE ; static BOOL drawPinS = FALSE ; /* whether or not to draw pins */ static BOOL drawBinS = FALSE ; /* whether or not to draw bins */ static BOOL drawLabelS = FALSE ; /* whether to draw labels or not */ static BOOL ignoreStdMacroS=FALSE;/* normally draw the standard cell macros */ static INT selectCellS ; /* the current selected cell */ static BOOL auto_drawS = TRUE ;/* whether to draw immediately after exp.*/ static BOOL drawNeighborS = TRUE; /* whether to draw neighborhoods */ static BOOL cleanFileS = FALSE ; /* whether we need to delete old files */ static INT drawNetS = 0 ; /* draw nets 0:none 1...n:net >numnets:all */ static BOOL drawBorderS = TRUE ; /* normal option - draw border otherwise cell tiles */ static BOOL drawGlobeS = TRUE ; /* turn off global routing tiles */ static BOOL drawGridS = TRUE ; /* draw the grid reference lines */ static BOOL drawWireEstS ; /* whether to draw wire estimation */ static INT pinsizeS ; /* size of the pin */ static BOOL movedCellS ; /* lets us know whether we have to update cellbins */ static BOOL single_cell_moveS = FALSE ; static BOOL drawFS = FALSE ; /* Forward references */ INT draw_the_data() ; static draw_fs(); static edit_cell(); static edit_field_string(); static edit_field_case(); static fix_the_cell(); static fix_the_cell2(); initMCGraphics( argc, argv, windowId ) INT argc, windowId ; char *argv[] ; { char *host ; #ifndef DEVELOPMENU set_graphics_wait_menu( MENU ) ; #endif if( !(doGraphicsG) ){ TWinitGraphics(argc,argv,TWnumcolors(),TWstdcolors(),TRUE,MENU, draw_the_data ) ; return ; } /* we need to find host for display */ if(!(host = Ygetenv("DISPLAY"))) { M(WARNMSG,"initMCGraphics","Can't get environment variable "); M(MSG,NULL, "for display. Aborting graphics...\n\n" ) ; avoidDump = TRUE ; doGraphicsG = FALSE ; return ; } if( windowId ){ /* init windows as a parasite */ if( !( TWinitParasite(argc,argv,TWnumcolors(),TWstdcolors(), FALSE, MENU, draw_the_data, windowId ))){ M(ERRMSG,"initMCGraphics","Aborting graphics."); doGraphicsG = FALSE ; avoidDump = TRUE ; return ; } } else { /* init window as a master */ if(!(TWinitGraphics(argc,argv,TWnumcolors(),TWstdcolors(),FALSE,MENU, draw_the_data ))){ M(ERRMSG,"initMCGraphics","Aborting graphics."); doGraphicsG = FALSE ; avoidDump = TRUE ; return ; } } TWsetwindow( 0, 0, 10, 10 ) ; TWsetFrame(0) ; TWdrawCell( 0, 0,0,11,11, BINCOLOR, INTRO ) ; TWmessage("To interupt program click on top menu window") ; TWflushFrame() ; selectCellS = 0 ; /* initialize to no selected cells */ /* use TWinterupt to turn off window enter/leave lights */ TWinterupt() ; /* set the default pin size */ pinsizeS = (track_spacingXG + track_spacingYG) / 4 - 1 ; pinsizeS = MAX( 1, pinsizeS ) ; } /* end initMCGraphics */ setGraphicWindow() { INT expand ; INT minx ; INT maxx ; INT miny ; INT maxy ; INT xc, yc ; /* cell center */ INT i ; /* counter */ CELLBOXPTR cptr ; /* cell record pointer */ regenorient( 1, endsuperG ) ; /* update bounding boxes if necessary */ minx = blocklG ; miny = blockbG ; maxx = blockrG ; maxy = blocktG ; /* look thru cells to find overall bounding box */ for( i = 1; i <= endpadsG ; i++ ){ cptr = cellarrayG[i] ; xc = cptr->xcenter ; yc = cptr->ycenter ; minx = MIN( minx, cptr->bounBox[cptr->orient]->l + xc ) ; miny = MIN( miny, cptr->bounBox[cptr->orient]->b + yc ) ; maxx = MAX( maxx, cptr->bounBox[cptr->orient]->r + xc ) ; maxy = MAX( maxy, cptr->bounBox[cptr->orient]->t + yc ) ; } expand = MAX( maxy - miny, maxx - minx ) ; expand = (INT) (0.1 * (DOUBLE) expand ) ; TWsetwindow( minx - expand, miny - expand, maxx + expand, maxy + expand ) ; } /* end setGraphicWindow */ /* set what we are going to draw on a dump to the screen */ /* placement data, compaction data , etc. are valid */ set_graphic_context( context ) INT context ; { if( context == PARTITION_PLACEMENT ){ /* after placement ignore drawing the standard macros */ ignoreStdMacroS = TRUE ; } setGraphicWindow() ; } /* end set_graphic_context */ /* heart of the graphic system processes user input */ process_graphics() { INT x1, y1, x2, y2 ; /* coordinates for fixing cells and neighhds */ INT x, y ; /* coordinates from pointer */ INT i ; /* temp variable */ INT selection ; /* the users pick */ INT pick_cell() ; /* get cell from user */ char *reply ; /* user reply to a querry */ BOOL ok ; /* loop until this value is true */ char leftNotRight[2] ; /* reference to left or right side of core */ char bottomNotTop[2] ; /* reference to bottom or top of core */ char leftNotRight2[2]; /* reference to left or right side of core */ char bottomNotTop2[2]; /* reference to bottom or top of core */ DOUBLE scale ; /* scale wireestimation */ DOUBLE eval_ratio() ;/* returns a double */ DOUBLE calc_core_factor() ; /* calculate new core */ if(!(doGraphicsG)){ return ; } /* data might have changed so show user current config */ /* any function other that the draw controls need to worry about */ /* this concurrency problem - show user current config */ setGraphicWindow() ; draw_the_data() ; /* use TWcheckExposure to flush exposure events since we just */ /* drew the data */ TWcheckExposure() ; TWmessage( "TimberWolfMC is waiting for your response..." ) ; regenorient( 1, endsuperG ) ; /* update bounding boxes if necessary */ selection = CANCEL ; movedCellS = FALSE ; while( selection != CONTINUE_PROGRAM ){ /* loop until exit */ selection = TWcheckMouse() ; switch( selection ){ case CANCEL: /* do nothing */ break ; case AUTO_REDRAW_ON: auto_drawS = TRUE ; break ; case AUTO_REDRAW_OFF: auto_drawS = FALSE ; break ; case CLOSE_GRAPHICS: TWcloseGraphics() ; /* update all costs and reload cells */ funccostG = findcost() ; doGraphicsG = FALSE ; return ; case COLORS: TWtoggleColors() ; break ; case CONTINUE_PROGRAM: break ; case DUMP_GRAPHICS: graphics_dump() ; break ; case FULLVIEW: TWfullView() ; break ; case GRAPHICS_UPDATE_ON: set_dump_ratio( 1 ) ; break ; case GRAPHICS_UPDATE_OFF: set_dump_ratio( 155 ) ; /* break the loop */ selection = CONTINUE_PROGRAM ; break ; case REDRAW: draw_the_data() ; /* use TWcheckExposure to flush exposure events since */ /* we just drew the data */ TWcheckExposure() ; break ; case TELL_POINT: TWmessage( "Pick a point" ) ; TWgetPt( &x, &y ) ; sprintf( YmsgG,"The point is (%d,%d)",x,y ) ; TWmessage( YmsgG ) ; break ; case TRANSLATE: TWtranslate() ; break ; case ZOOM: TWzoom() ; break ; /* ********* end menu1 ************ */ case CELL_NEIGHBORHOOD: if(!(selectCellS = pick_cell() )){ break ; } /* fix cell in a neighborhood */ /* use initialize corner to set statics in initialize.c */ initializeCorner( selectCellS ) ; TWmessage( "[FIX_CELL_IN_NEIGHBORHOOD]:Pick or enter first point for neighborhood:") ; TWgetPt2( &x1, &y1 ) ; TWmessage( "Pick or enter second point for neighborhood:"); TWgetPt2( &x2, &y2 ) ; determine_origin( &x1, &y1, leftNotRight, bottomNotTop ) ; determine_origin( &x2, &y2, leftNotRight2, bottomNotTop2 ) ; /* cell is fixed within a fixed neighborhood */ fixCell( NEIGHBORHOODFLAG, x1, leftNotRight, y1, bottomNotTop, x2, leftNotRight2, y2, bottomNotTop2 ) ; updateFixedCells( FALSE ) ; /* fix swap classes - put cell in unique cell class */ addClass( --unique_classG ) ; TWmessage( NIL(char *) ) ; selectCellS = 0 ; TWforceRedraw() ; break ; case EDIT_CELL: if( selectCellS = pick_cell() ){ edit_cell( selectCellS ) ; TWforceRedraw() ; selectCellS = 0 ; } break ; case FIX_CELL: if(!(selectCellS = pick_cell() )){ break ; } fix_the_cell( selectCellS ) ; /* in addition do below */ case FIX_CELL_BUT_ROT: if(!(selectCellS)){ if(!(selectCellS = pick_cell() )){ break ; } } fix_the_cell2( selectCellS ) ; TWforceRedraw() ; break ; case GROUP_CELLS: TWmessage( "Not implemented yet" ) ; break ; case MOVE_CELL: if(!(selectCellS = pick_cell() )){ break ; } if( cellarrayG[selectCellS]->fixed ){ TWmessage("ERROR:cannot move fixed cell" ) ; (void) sleep( (unsigned) 2 ) ; TWmessage("Use EDIT_CELL to free cell" ) ; (void) sleep( (unsigned) 2 ) ; break ; } TWmessage( "Pick or enter a reference point relative to cell center:" ) ; if( TWgetPt2( &x, &y ) ){ /* we know from keyboard */ TWmessage( "Enter new position x, y:" ) ; TWgetPt( &x1, &y1 ) ; cellarrayG[selectCellS]->xcenter = x1 - x ; cellarrayG[selectCellS]->ycenter = y1 - y ; } else { /* from mouse */ TWmessage( "Pick new position with mouse" ) ; /* get old position of cell */ get_global_pos( selectCellS, &x1, &y1, &x2, &y2 ) ; TWmoveRect( &x1, &y1, &x2, &y2, x, y ) ; /* calculate new position for cell */ cellarrayG[selectCellS]->xcenter = (x1+x2)/2 ; cellarrayG[selectCellS]->ycenter = (y1+y2)/2 ; } movedCellS = TRUE ; funccostG = findcost() ; selectCellS = 0 ; draw_the_data() ; TWcheckExposure() ; break ; /* ********* end menu2 ************ */ case DRAW_BINS: drawBinS = TRUE ; TWmessage( "Area bins will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_BINS: drawBinS = FALSE ; TWmessage( "Area bins will be omitted from drawing" ) ; TWforceRedraw() ; break ; case DRAW_BORDER: drawBorderS = TRUE ; TWmessage( "Cell border will be drawn") ; TWforceRedraw() ; break ; case DRAW_TILES: drawBorderS = FALSE ; TWmessage( "The cells tiles will be draw" ) ; TWforceRedraw() ; break ; case DRAW_LABELS: drawLabelS = TRUE ; TWmessage( "Labels will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_LABELS: drawLabelS = FALSE ; TWmessage( "Labels will be omitted from drawing" ) ; TWforceRedraw() ; break ; case DRAW_NEIGHBORHD: drawNeighborS = TRUE ; TWmessage( "Cell neighborhoods will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_NEIGHBORHOOD: drawNeighborS = TRUE ; TWmessage( "Cell neighborhoods will be omitted from drawing"); TWforceRedraw() ; break ; case DRAW_NETS: drawNetS = numnetsG + 1 ; TWmessage( "Nets will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_NETS: drawNetS = FALSE ; TWmessage( "Nets will be omitted from drawing" ) ; TWforceRedraw() ; break ; case DRAW_ORIENT: drawFS = TRUE ; TWmessage( "Orientation symbol will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_ORIENT: drawFS = FALSE ; TWmessage( "Orientation symbol will be omitted" ) ; TWforceRedraw() ; break ; case DRAW_PINS: drawPinS = TRUE ; TWmessage( "Pins will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_PINS: drawPinS = FALSE ; TWmessage( "Pins will be omitted from drawing" ) ; TWforceRedraw() ; break ; case DRAW_WIRING_EST: drawWireEstS = TRUE ; TWmessage( "Wiring area estimation for cells will be drawn") ; TWforceRedraw() ; break ; case IGNORE_WIRING_EST: drawWireEstS = FALSE ; TWmessage( "Wiring area estimation will be omitted from drawing" ) ; TWforceRedraw() ; break ; case DRAW_GLOBE_AREAS: drawGlobeS = TRUE ; TWforceRedraw() ; break ; case IGNORE_GLOBE_AREAS: drawGlobeS = FALSE ; TWforceRedraw() ; break ; /* ********* end menu3 ************ */ case CHANGE_ASPECT_RATIO: ok = FALSE ; while(!(ok)){ reply = TWgetString( "Enter new aspect ratio:" ) ; chipaspectG = atof( reply ) ; if( chipaspectG >= 0.01 ){ ok = TRUE ; } } /* now change aspect ratio - use eval_ratio to find time */ (void) calc_core_factor( eval_ratio( iterationG ) ) ; /* update graphic window since aspect ratio has changed */ TWforceRedraw() ; setGraphicWindow() ; break ; case DRAW_SINGLE_NET: /* get a net from the user */ ok = FALSE ; do { /* get string from user */ reply = TWgetString( "Enter net number:") ; drawNetS = atoi( reply ) ; if( drawNetS > 0 && drawNetS <= numnetsG ){ TWforceRedraw() ; ok = TRUE ; } else { TWmessage( "ERROR:invalid net number!" ) ; (void) sleep( (unsigned) 2 ) ; } } while ( !(ok) ) ; break ; case GRAPHICS_WAIT: wait_for_userG = TRUE ; TWmessage( "TimberWolfMC will now stop at breakpoints\n" ); break ; case NO_GRAPHICS_WAIT: wait_for_userG = FALSE ; TWmessage( "TimberWolfMC will NOT stop at graphic breakpoints\n" ); break ; case DRAW_SINGLE_CELL_MOVES: single_cell_moveS = TRUE ; TWcolorXOR( WIREESTCOLOR, TRUE ) ; TWcolorXOR( CELLCOLOR, TRUE ) ; TWcolorXOR( TWRED, TRUE ) ; break ; case IGNORE_SINGLE_CELL: single_cell_moveS = FALSE ; TWcolorXOR( WIREESTCOLOR, FALSE ) ; TWcolorXOR( CELLCOLOR, FALSE ) ; TWcolorXOR( TWRED, FALSE ) ; break ; } /*********************** end graphics SWITCH *****************/ if( auto_drawS && TWcheckExposure() ){ draw_the_data() ; } if( movedCellS ){ loadbins( CELLEST ) ; /* wire estimation on */ funccostG = findcost() ; movedCellS = FALSE ; } } /* update all costs */ funccostG = findcost() ; TWmessage("Continuing - to interupt program click on top menu window") ; /* use TWinterupt to turn off window enter/leave lights */ TWinterupt() ; } /* end process_graphics */ /* find the cell in question */ INT pick_cell() { INT i ; INT match_count ; /* keep track of all cells that match */ INT x, y ; /* coordinates picked by user */ INT cell ; /* selected cell */ INT l, r, b, t ; /* cell sides */ cell = 0 ; TWmessage("Pick cell by clicking any mouse button at center of cell"); TWgetPt( &x, &y ) ; /* look thru all cells O(numcells) algorithm */ match_count = 0 ; for( i = 1 ; i <= endpadsG; i++ ){ get_global_pos( i, &l, &b, &r, &t ) ; /* see if cell boundary contains this point */ if( x >= l && x <= r ){ if( y >= b && y <= t ){ selectCellS = i ; match_count++ ; } } } /* end loop */ if( match_count == 0 ){ TWmessage( "No cell selected" ) ; if( selectCellS ){ /* user didn't like any options */ selectCellS = 0 ; draw_the_data() ; /* draw the data with highlight off */ TWcheckExposure() ; } return( 0 ) ; } else if( match_count == 1 ){ draw_the_data() ; /* draw the data with highlight on */ TWcheckExposure() ; sprintf( YmsgG, "Selected cell:%d - %s", cell, cellarrayG[selectCellS]->cname ) ; TWmessage( YmsgG ) ; return( selectCellS ) ; } else { /* more than one match */ TWmessage( "More than one match. Choose correct cell" ) ; (void) sleep( (unsigned) 2 ) ; cell = 0 ; while( TRUE ){ for( i = 1 ; i <= endpadsG; i++ ){ get_global_pos( i, &l, &b, &r, &t ) ; /* see if cell boundary contains this point */ if( x >= l && x <= r ){ if( y >= b && y <= t ){ selectCellS = i ; draw_the_data() ; TWcheckExposure() ; /* give directions */ sprintf( YmsgG, "Selected cell:%d - %s", cell, cellarrayG[selectCellS]->cname ) ; TWmessage( YmsgG ) ; (void) sleep( (unsigned) 2 ) ; sprintf( YmsgG,"%s","If correct, enter . Otherwise ") ; strcat( YmsgG, "enter n for next cell:") ; /* look for empty string - means we are satisfied */ if(!(TWgetString(YmsgG))){ return( selectCellS ) ; } } } } /* end loop */ } } } /* end find_cell */ /* the graphics program can draw the results at each desired */ /* timestep. */ INT draw_the_data() { INT i ; INT x ; INT y ; INT pt ; INT max ; INT grid ; INT area ; INT offset ; char *labelptr ; char label[LRECL] ; INT x0, x1, y0, y1 ; PINBOXPTR curPin ; BINBOXPTR bp ; ANALOGPTR aptr ; CELLBOXPTR cellptr ; DOUBLE percent ; if( avoidDump || !(doGraphicsG) ){ return( -1 ) ; } if( cleanFileS == TRUE ){ Yrm_files( "DATA/*" ) ; cleanFileS = FALSE ; } TWstartFrame() ; TWmessage( "Drawing the data...Please wait" ) ; /* draw the cells */ for( i = 1; i <= totalcellsG ; i++ ){ twmc_draw_a_cell( i ) ; } if( selectCellS ){ get_global_pos( selectCellS, &x0, &y0, &x1, &y1 ) ; TWhighLightRect( x0, y0, x1, y1 ) ; } /* now build net file */ /* nets are the interconnections between the cells */ if( drawNetS ){ Ymst_init( get_max_pin() ) ; for( i=1;i<=numnetsG;i++){ /* this is the single net case */ if( drawNetS <= numnetsG && i != drawNetS ){ continue ; } Ymst_clear() ; for(curPin=netarrayG[i]->pins;curPin;curPin=curPin->next){ Ymst_addpt( curPin->xpos, curPin->ypos ) ; } Ymst_draw() ; } Ymst_free() ; } /* draw core region for reference */ TWdrawLine( ++i, blocklG,blockbG,blocklG,blocktG,BLACK,NULL ) ; TWdrawLine( ++i, blocklG,blocktG,blockrG,blocktG, BLACK,NULL ) ; TWdrawLine( ++i, blockrG,blocktG,blockrG,blockbG, BLACK, NULL ) ; TWdrawLine( ++i, blockrG,blockbG,blocklG,blockbG, BLACK, NULL ) ; if( drawBinS ){ /* draw bins for reference */ for( x=1;xleft, bp->bottom, bp->left, bp->top, BINCOLOR, NULL ) ; /* top edge */ TWdrawLine(i, bp->left, bp->top, bp->right, bp->top , BINCOLOR, NULL ) ; /* right edge */ TWdrawLine(i, bp->right, bp->top, bp->right, bp->bottom, BINCOLOR, NULL ) ; /* bottom edge */ TWdrawLine(i, bp->right, bp->bottom, bp->left, bp->bottom, BINCOLOR, NULL ) ; } } for( x = 0 ; x <= maxBinXG ; x++ ) { for( y = 0 ; y <= maxBinYG ; y++ ) { bp = binptrG[x][y] ; if( drawLabelS ){ /* name the cell */ sprintf(label,"%d", bp->penalty ) ; labelptr = label ; } else { labelptr = NULL ; } area = (bp->right - bp->left) * (bp->top - bp->bottom) ; percent = (DOUBLE) bp->penalty / (DOUBLE) area ; if( percent < -0.75 ){ TWdrawRect( x, bp->left, bp->bottom, bp->right, bp->top, TWRED, labelptr ) ; } else if( percent < -0.50 ){ TWdrawRect( x, bp->left, bp->bottom, bp->right, bp->top, TWYELLOW, labelptr ) ; } else if( percent < -0.25 ){ TWdrawRect( x, bp->left, bp->bottom, bp->right, bp->top, TWBLUE, labelptr ) ; } else if( percent < 0.0 ){ TWdrawRect( x, bp->left, bp->bottom, bp->right, bp->top, TWORANGE, labelptr ) ; } else { TWdrawRect( x, bp->left, bp->bottom, bp->right, bp->top, TWCYAN, labelptr ) ; } } } } /* end test of binsOnS */ if( drawGridS && gridGivenG ){ Ygrid_getx( &grid, &offset ) ; /* draw gridding lines for reference */ max = blockrG ; Ygridx ( &max ) ; for( i=1; i <= max; i++ ){ /* vertical edge */ x = i * grid ; Ygridx( &x ) ; TWdrawLine( i, x, 0, x, blockrG, BINCOLOR, NULL ) ; } Ygrid_gety( &grid, &offset ) ; max = blocktG ; Ygridy ( &max ) ; for( i=1; i <= max; i++ ){ /* horizontal edge */ y = i * grid ; Ygridy( &y ) ; TWdrawLine( i, 0, y, blocktG, y, BINCOLOR, NULL ) ; } } /* end test of drawGridS */ /* draw neighborhoods if desired */ if( drawNeighborS ){ for( i=1; i<= endsuperG; i++ ){ draw_neighbors( i ) ; } } /* now output pins */ /* pins are the terminal points on a net */ if( drawPinS ){ for( i = 1 ; i <= numpinsG ; i++ ) { curPin = termarrayG[i] ; if( drawLabelS ){ labelptr = curPin->pinname ; } else { labelptr = NULL ; } if( aptr = curPin->analog ){ TWarb_init() ; cellptr = cellarrayG[curPin->cell] ; ASSERTNCONT( cellptr, "draw_the_data","cellptr NULL\n" ) ; for( pt = 0; pt < aptr->num_corners; pt++ ){ /* rel position is a macro which calculates */ /* absolute pin loc - defined in relpos.h */ REL_POS( cellptr->orient, x, y, /* result */ aptr->x_contour[pt], aptr->y_contour[pt], /* cell relative */ cellptr->xcenter, cellptr->ycenter ) ; /* cell center */ TWarb_addpt( x, y ) ; } TWdrawArb( i, PINCOLOR, labelptr ) ; } else { x = curPin->xpos ; y = curPin->ypos ; TWdrawPin( curPin->net,x-pinsizeS,y-pinsizeS, x+pinsizeS,y+pinsizeS, PINCOLOR, labelptr ) ; } } } /* clear wait message and FLUSH OUTPUT BUFFER */ TWmessage( NULL ) ; TWflushFrame() ; return( 0 ) ; } /* end draw_the_data */ twmc_draw_a_cell( cell ) { INT pt ; INT xc, yc ; INT x, y ; INT type ; INT x0, x1, y0, y1 ; INT l, r, b, t ; INT *xvert ; INT *yvert ; char label[LRECL] ; char *labelptr ; CELLBOXPTR cptr ; TILEBOXPTR tileptr ; MOVEBOXPTR pos ; MOVEBOX pos_buffer ; RTILEBOXPTR rtptr ; pos = &pos_buffer ; cptr = cellarrayG[cell] ; type = cptr->celltype ; if( type != CUSTOMCELLTYPE && type != SOFTCELLTYPE && type != PADCELLTYPE && type != STDCELLTYPE ){ return ; } if( ignoreStdMacroS && type == STDCELLTYPE ){ return ; } xc = cptr->xcenter ; yc = cptr->ycenter ; if( drawLabelS ){ /* name the cell */ sprintf(label,"C%d:%s",cell, cptr->cname ) ; labelptr = label ; } else { labelptr = NULL ; } if( !(drawBorderS) || drawWireEstS ){ for( tileptr = cptr->tiles;tileptr;tileptr=tileptr->next ) { l = tileptr->left ; r = tileptr->right ; b = tileptr->bottom ; t = tileptr->top ; /* first get orientation from orientation */ Ytranslate( &l, &b, &r, &t, cptr->orient ) ; pos->l = l ; pos->r = r ; pos->b = b ; pos->t = t ; l += xc ; r += xc ; b += yc ; t += yc ; /* wire estimation draw */ if( drawWireEstS && cell <= numcellsG ){ pos->lw = tileptr->lweight ; pos->rw = tileptr->rweight ; pos->bw = tileptr->bweight ; pos->tw = tileptr->tweight ; Ytranslatef( &(pos->lw),&(pos->bw),&(pos->rw),&(pos->tw), cptr->orient ) ; if( new_wire_estG ){ wireestxy2( pos,xc,yc ) ; } else { wireestxy( pos,xc,yc ) ; } x0 = pos->l ; x1 = pos->r ; y0 = pos->b ; y1 = pos->t ; TWdrawCell( cell, x0,y0,x1,y1, WIREESTCOLOR, NULL ) ; } if(!(drawBorderS)){ /* normal cell draw */ TWdrawCell( cell,l,b,r,t, CELLCOLOR,labelptr ) ; } } } /* end tile case */ if( cell <= numcellsG && routingTilesG && drawGlobeS ){ for( rtptr = routingTilesG[cell];rtptr;rtptr=rtptr->next ){ TWdrawCell( cell, rtptr->x1 + xc, rtptr->y1 + yc, rtptr->x2 + xc, rtptr->y2 + yc, TWRED,labelptr ) ; } } if( drawBorderS ){ /* normal way to draw the cells */ TWarb_init() ; xvert = cptr->vertices->x ; yvert = cptr->vertices->y ; for( pt = 1; pt <= cptr->numsides; pt++ ){ /* rel position is a macro which calculates */ /* absolute pin loc - defined in relpos.h */ REL_POS( cptr->orient, x, y, /* result */ xvert[pt], yvert[pt], /* cell relative */ xc, yc ) ; /* cell center */ TWarb_addpt( x, y ) ; } TWdrawArb( cell, CELLCOLOR, labelptr ) ; } if( drawFS ){ draw_fs( cptr ) ; } } /* end TWdrawCell */ static draw_fs( cptr ) CELLBOXPTR cptr ; { INT x[10], y[10] ; /* only 10 points to an F */ INT l, b, r, t ; /* bounding box points */ INT xout, yout ; /* rotated points */ INT wid ; /* with of the F */ INT pt ; /* point counter */ BOUNBOXPTR bounptr ; /* cell's boundary */ bounptr = cptr->bounBox[0] ; l = bounptr->l ; b = bounptr->b ; r = bounptr->r ; t = bounptr->t ; wid = (INT) (0.25 * (DOUBLE)( t - b ) ) ; /* now set the points */ x[0] = l ; y[0] = b ; x[1] = l ; y[1] = t ; x[2] = r ; y[2] = t ; x[3] = r ; y[3] = t - wid ; x[4] = l + wid ; y[4] = y[3] ; x[5] = x[4] ; y[5] = y[4] - wid ; x[6] = l + 2*wid ; y[6] = y[5] ; x[7] = x[6] ; y[7] = y[6] - wid ; x[8] = x[5] ; y[8] = y[7] ; x[9] = x[4] ; y[9] = b ; TWarb_init() ; for( pt = 0; pt <= 9; pt++ ){ /* rel position is a macro which calculates */ /* absolute pin loc - defined in relpos.h */ REL_POS( cptr->orient, xout, yout, /* result */ x[pt], y[pt], /* cell relative */ cptr->xcenter, cptr->ycenter ) ; /* cell center */ TWarb_addpt( xout, yout ) ; } TWdrawArb( 0, FCOLOR, NIL(char *) ) ; } /* end draw_fs */ /* draw the neighborhood of a cell if it exists */ draw_neighbors( cell ) INT cell ; { CELLBOXPTR ptr ; FIXEDBOXPTR fptr ; ptr = cellarrayG[cell] ; ASSERTNRETURN( ptr, "draw_neighbor", "cell ptr is null" ) ; /* for core cells check fixed record */ /* for group cells check group record */ if( ptr->celltype == GROUPCELLTYPE ){ ASSERT( ptr->group, "draw_neighbors", "pointer null"); fptr = ptr->group->fixed ; } else { fptr = ptr->fixed ; } if( fptr ){ /* means we have a fixed cell */ if( fptr->fixedType != POINTFLAG ){ /* draw neighborhood */ /* left edge */ TWdrawLine( cell, fptr->x1, fptr->y1, fptr->x1, fptr->y2, NEIGHBORCOLOR, NULL ) ; /* top edge */ TWdrawLine( cell, fptr->x1, fptr->y2, fptr->x2, fptr->y2, NEIGHBORCOLOR, NULL ) ; /* right edge */ TWdrawLine( cell, fptr->x2, fptr->y2, fptr->x2, fptr->y1, NEIGHBORCOLOR, NULL ) ; /* right edge */ TWdrawLine( cell, fptr->x2, fptr->y1, fptr->x1, fptr->y1, NEIGHBORCOLOR, NULL ) ; } } /* end test of fix cell */ } /* end draw_neighbors */ /* avoid dump when we don't want it */ dsetDump( flag ) BOOL flag ; { avoidDump = flag ; } /* end dsetDump */ /* get dump flag */ BOOL dgetDump() { return( avoidDump ) ; } /* dumps the data to a file for future study */ graphics_dump() { /* now change mode to dump to file */ TWsetMode(1) ; /* dump the data to a file now instead of screen */ draw_the_data() ; /* restore the state to previous condition and set draw to screen */ TWsetMode(0) ; } /* end graphics_dump() */ static edit_cell( cell ) INT cell ; { #define NAMEF 3 #define CELLNUMF 4 #define XCENTERF 6 #define YCENTERF 8 #define ORIENTF 9 #define VALIDF 19 #define FIXEDF 43 #define VALIDSPACE 3 #define ORIENTBASE ORIENTF+1 #define DIALOGNAME "editcell" INT i ; /* counter */ INT offset ; /* offset from base */ INT status ; /* status from check_valid_orient */ char name[LRECL]; /* a scratch buffer for cellname */ char cellnum[LRECL]; /* a scratch buffer for cellnum */ char xcenter[LRECL]; /* a scratch buffer for xcenter */ char ycenter[LRECL]; /* a scratch buffer for ycenter */ CELLBOXPTR ptr ; /* current cell record */ TWDRETURNPTR answer ; /* return from user */ TWmessage( "Edit cell" ) ; #ifdef DEVELOPDIALOG dialogS = TWread_dialog( "mc.dialog" ) ; if( !(dialogS) ){ return ; /* avoid crashes */ } #endif ptr = cellarrayG[ cell ] ; /* now set the cell information fields */ /* the cell name */ sprintf( name, "Name: %s", ptr->cname ) ; edit_field_string( dialogS, NAMEF, name ) ; sprintf( cellnum, "Number: %d", ptr->cellnum ) ; edit_field_string( dialogS, CELLNUMF, cellnum ) ; /* now set the x y centers */ sprintf( xcenter, "%d", ptr->xcenter ) ; edit_field_string( dialogS, XCENTERF, xcenter ) ; sprintf( ycenter, "%d", ptr->ycenter ) ; edit_field_string( dialogS, YCENTERF, ycenter ) ; /* set orientation */ #ifdef TI edit_field_case( dialogS, ORIENTF, tw2ice(ptr->orient) + ORIENTBASE -1 ) ; #else edit_field_case( dialogS, ORIENTF, ptr->orient + ORIENTBASE ) ; #endif /* TI */ for( i = 0; i <= 7; i++ ){ offset = VALIDSPACE * i ; if( ptr->orientList[i] ){ dialogS[VALIDF+offset].group = VALIDF + offset + 1 ; } else { dialogS[VALIDF+offset].group = VALIDF + offset + 2 ; } } if( ptr->fixed ){ /* this means fixed is on */ dialogS[FIXEDF].group = FIXEDF + 1 ; } else { dialogS[FIXEDF].group = FIXEDF + 2 ; } /* initialization complete */ if( answer = TWdialog( dialogS, DIALOGNAME, NULL) ) { /* if answer field has changed update position */ if( answer[XCENTERF].bool ){ /* the xcenter has changed */ ptr->xcenter = atoi( answer[XCENTERF].string ) ; movedCellS = TRUE ; } if( answer[YCENTERF].bool ){ /* the ycenter has changed */ ptr->ycenter = atoi( answer[YCENTERF].string ) ; movedCellS = TRUE ; } #ifdef TI /* check orientation fields */ for( i = 0; i <= 7; i++ ){ if( answer[ORIENTBASE+i].bool ){ ptr->orient = ice2tw(i+1) ; break ; } } #else /* check orientation fields */ for( i = 0; i <= 7; i++ ){ if( answer[ORIENTBASE+i].bool ){ ptr->orient = i ; break ; } } #endif /* check for valid orientation fields */ for( i = 0; i <= 7; i++ ){ offset = VALIDSPACE * i ; if( answer[VALIDF+offset+1].bool ){ ptr->orientList[i] = TRUE ; } else { ptr->orientList[i] = FALSE ; } } status = check_valid_orient( ptr ) ; if( status == -1 ){ TWmessage( "ERROR:No valid orientations. Setting 0 valid." ) ; ptr->orientList[0] = TRUE ; ptr->orient = 0 ; movedCellS = TRUE ; (void) sleep( (unsigned) 3 ) ; } else if( status == 1 ){ sprintf( YmsgG, "Orientation set to valid orientation:%d", ptr->orient ) ; TWmessage( YmsgG ) ; (void) sleep( (unsigned) 3 ) ; movedCellS = TRUE ; } if( answer[FIXEDF+1].bool ){ /* this means fixed has been requested */ if(!(ptr->fixed)){ fix_the_cell( cell ) ; fix_the_cell2( cell ) ; } } else if( answer[FIXEDF+2].bool ){ /* this means fixed wants to be off */ if( ptr->fixed ){ /* it is on turn it off */ delete_fix_constraint( cell ) ; } } } } /* end edit_tiles */ static edit_field_string( dialog, field, string ) TWDIALOGPTR dialog; /* dialog record */ INT field ; char *string ; { dialog[field].string = string ; } /* end edit_field_string */ static edit_field_case( dialog, field, initcase ) TWDIALOGPTR dialog; /* dialog record */ INT field ; INT initcase ; { TWDIALOGPTR fptr; /* current dialog record */ dialog[field].group = initcase ; } /* end edit_field_case */ set_graphics_wait_menu( menus ) TWMENUBOX menus[] ; { INT i ; /* counter */ for( i = 0; i < TWNUMMENUS; i++ ){ /* look for the graphics wait menu */ if( strcmp( menus[i].item, "Graphics Wait") == STRINGEQ ){ /* we found the graphics box */ /* change to current state */ if( wait_for_userG ){ menus[i].bool_init = TRUE ; } else { menus[i].bool_init = FALSE ; } break ; } } } static fix_the_cell( cell ) INT cell ; { INT i ; /* counter */ /* turn off all rotational possibibilites */ for( i = 0 ; i < 8 ; i++ ) { if( i != cellarrayG[cell]->orient ){ cellarrayG[cell]->orientList[i] = FALSE ; } else { cellarrayG[cell]->orientList[i] = TRUE ; } } cellarrayG[cell]->orientList[HOWMANYORIENT] = 1 ; } /* end fix_the_cell */ static fix_the_cell2( cell ) INT cell ; { INT x1, y1 ; char leftNotRight[2] ; /* reference to left or right side of core */ char bottomNotTop[2] ; /* reference to bottom or top of core */ /* use initialize corner to set statics in initialize.c */ initializeCorner( cell ) ; /* now fixcell */ x1 = cellarrayG[cell]->xcenter ; y1 = cellarrayG[cell]->ycenter ; sprintf( YmsgG, "Fixing cell:%d - %s @ (%d,%d)", cell, cellarrayG[cell]->cname, x1, y1 ) ; TWmessage( YmsgG ) ; determine_origin( &x1, &y1, leftNotRight, bottomNotTop ) ; /* fix cell at x1, y1 using orign from determine origin */ fixCell( POINTFLAG, x1, leftNotRight, y1, bottomNotTop, 0, "L", 0, "B") ; updateFixedCells( FALSE ) ; /* fix swap classes - put cell in unique cell class */ addClass( --unique_classG ) ; TWmessage( NIL(char *) ) ; selectCellS = 0 ; } /* end fix_the_cell2 */ #endif /* NOGRAPHICS */ graywolf-0.1.4+20170307gite1bf319/src/twmc/initialize.c000066400000000000000000001645441305746555600220500ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: initialize.c DESCRIPTION:This file contains the utility routines called from the parser to set up the TimberWolfMC data structures. CONTENTS: setErrorFlag() DATE: Aug 7, 1988 REVISIONS: Oct 27, 1988 - added add_cell_to_group, initializeCorner and modified fixCell in order to handle group cells. Jan 20, 1989 - added build_soft_array call. Jan 29, 1989 - changed msg to YmsgG and added \n's. Feb 28, 1989 - added initialization to tile weights. Mar 7, 1989 - added cell instances. - added cell hash table for instance names. Apr 5, 1989 - added multiple tiles for softcells and added instance handling. Instances are handled by disturbing routines as little as possible and using pointer swaps to switch in a new instance as much as possible. Apr 9, 1989 - added sortpin to cleanupCells for incremental bounding box scheme. Apr 30, 1989 - changed exchange class for group cells. - fixed problem with pad group children. May 1, 1989 - orient the pads correctly. May 11, 1989 - now use the orientList[HOWMANYORIENT] to specify the number of valid orientations. May 12, 1989 - added layer information. May 25, 1989 - changed tiles list to FIFO from LIFO for cell gridding.. Jul 19, 1989 - added numstdcells to save work for partition case with no hard or soft cells. Sep 29, 1989 - remove max tile limit by making dynamic. Oct 18, 1989 - Added tile to pad macros for density calc. Apr 15, 1990 - Modified cur_inst fields. Added vertices fields to cell box for placing pins. Moved pintype field to PINBOX from SOFTBOX. Made fixed field of GROUPBOX a pointer. Apr 17, 1990 - added load_soft_pins which verifies user input and correctly sets up wire estimator. Apr 23, 1990 - now handle pingroup instances and also fixed wire area estimator for instances by looking at all instances when calculating the perimeter. Apr 26, 1990 - distinguish arbitrarily assigned layer information using negative numbers. May 2, 1990 - Now all pins on softcells have softinfo records to avoid access violations. Added error checking to processCorners to catch points not entered in a CW fashion. Jun 21, 1990 - moved the location of genorient so that the pins will be in the correct orientation before the check. Oct 1, 1990 - updated analog input data structures. Sun Dec 16 00:38:44 EST 1990 - reworked analog data structures and added check for rectilinear pins. Tue Dec 18 01:29:30 EST 1990 - make sure the buster check error messages go to screen properly. Wed Dec 19 23:58:12 EST 1990 - added check_pos. Dec 21, 1990 - added set_pin_pos and rewrote addPin to make pins more general. Thu Jan 17 00:55:28 PST 1991 - added numpins initialization. Wed Jan 23 14:42:30 PST 1991 - added findsidestr in order to make language context free. Fri Jan 25 18:05:56 PST 1991 - now scale data correctly. Wed Jan 30 14:13:36 EST 1991 - now left justify orientation rotations. Mon Feb 4 02:10:28 EST 1991 - made changes to make new pin placement code work and fixed numsides bug. Wed Feb 13 23:52:38 EST 1991 - modified for new pad code. Sat Feb 23 00:21:10 EST 1991 - updated for new pad placement code. Thu Apr 18 01:34:59 EDT 1991 - added more error checking and fixed problem with initial orientation. Sat Apr 27 01:15:05 EDT 1991 - now detect doPartition case automatically. Thu Aug 22 22:10:09 CDT 1991 - fixed problem with fixed cells moving during pairwise flips. Fri Oct 18 00:06:37 EDT 1991 - moved buster code to library and updated for new NIL definition. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) initialize.c version 3.24 10/18/91" ; #endif #include #include #include #include #include #include #include #include #include /* below is what we expect to be a large floorplanning input */ /* user may change parameters if they wish. Subject to change */ #define EXPECTEDNUMCELLS 500 #define EXPECTEDNUMNETS 1000 #define EXPECTEDNUMUNCON 100 #define EXPECTEDNUMPADS 10 #define EXPECTEDCORNERS 8 #define EXPECTEDINSTANCES 1 #define EXPECTEDPINGRP 1 #define PIN (BOOL) TRUE /* for pinFlag below */ #define EQUIV (BOOL) FALSE #define NUMPADMACROS 4 /* there are always 4 pad macros */ #define INITIALIZE (BOOL) TRUE /* for updateFixedCells */ /* ERRORABORT is a macro which forces routines not to do any work */ /* when we find a syntax error in the input routine. */ #define ERRORABORT() \ { \ if( errorFlagS ){ \ return ; /* don't do any work for errors */ \ } \ } \ /* ###################### STATIC definitions ######################### */ static INT curCellTypeS ; /* current cell type - ie, softcell,pad etc.*/ static INT cellinstanceS ; /* number of instances of current cell */ static INT cornerCountS ; /* current number of corners */ static INT tileptAllocS ; /* allocation allotted to tile structures */ static INT xcenterS, ycenterS ;/* current cell center coordinates */ static INT minxS, minyS ; /* bounding box of current cell */ static INT maxxS, maxyS ; /* bounding box of current cell */ static INT totPinS ; /* total number of pins over all instances */ static INT netAllocS ; /* current space in netarray */ static INT cellAllocS ; /* current space in cellarray */ static INT childAllocS ; /* current space in current pptr->children */ static INT instAllocS ; /* current number of instance allocated */ static INT equivpinS ; /* total number of equivs for the current pin */ static INT totxS, totyS ; /* counters for equiv pin postions */ static INT numchildrenS ; /* # of children in current pad or pingroup */ static INT numpingroupS ; /* # of pingroups for this cell */ static INT cur_restrict_objS ; /* set by set_restrict type */ static char *curCellNameS ; /* current cell name */ static char *curPinNameS ; /* current pin name */ static BOOL portFlagS ; /* tells whether port(TRUE) or not(FALSE) */ static BOOL errorFlagS ; /* switch allow us to find multiple errors */ static BOOL analog_errorS ; /* whether an analog error occurs */ static DOUBLE scaleS ; /* how to scale the data */ static CELLBOXPTR ptrS ; /* pointer to current cell box */ static PADBOXPTR pptrS ; /* pointer to current pad box */ static YBUSTBOXPTR cornerArrayS;/* holds array of pts for cell boundary */ static YHASHPTR netTableS ; /* hash table for cross referencing nets */ static YHASHPTR cellTableS ; /* hash table for referencing cells */ static PSIDEBOX *pSideArrayS;/* used to calc the side weighs of cell */ static KBOXPTR kArrayS ; /* used in making sides for softpins */ static GROUPBOXPTR curGroupS ; /* pointer to current group record */ static PINBOXPTR pinS ; /* current active pin of cell */ static PINBOXPTR softpinS ; /* current active softpin of cell */ static PINBOXPTR pingroupS ; /* current pin group record */ static ANALOGPTR analogS ; /* current analog record */ static SOFTBOXPTR spinptrS ; /* current softpin record */ static INSTBOXPTR instS ; /* pointer to current inst record */ PINBOXPTR findTerminal() ; /* ################## END STATIC definitions ########################## */ static check_pos(); /* set processing switch to avoid work when an error is found */ setErrorFlag() { errorFlagS = TRUE ; } /* end setErrorFlag */ /* ***************************************************************** */ /* return the net hash table */ YHASHPTR getNetTable() { return( netTableS ) ; } /* end getNetTable */ /* ***************************************************************** */ /* initialize global and static information */ initCellInfo() { numcellsG = 0 ; numnetsG = 0 ; numsoftG = 0 ; numstdcellG = 0 ; numpadsG = 0 ; numpadgroupsG = 0 ; numsupercellsG = 0 ; numinstancesG = 0 ; numpinsG = 0 ; totalcellsG = 0 ; totalpadsG = 0 ; errorFlagS = FALSE ; analog_errorS = FALSE ; totPinS = 0 ; unique_classG = 0 ; net_cap_matchG = NIL(INT **) ; net_res_matchG = NIL(INT **) ; scaleS = (DOUBLE) scale_dataG ; cornerCountS = 0 ; tileptAllocS = EXPECTEDCORNERS ; cornerArrayS = ( YBUSTBOXPTR ) Ysafe_malloc( tileptAllocS * sizeof( YBUSTBOX ) ); pSideArrayS = (PSIDEBOX *) Ysafe_malloc( tileptAllocS * sizeof( PSIDEBOX ) ) ; kArrayS = (KBOXPTR) Ysafe_calloc( (MAXSITES + 1), sizeof( KBOX )); /* make hash table for nets */ netTableS = Yhash_table_create( EXPECTEDNUMNETS ) ; /* make hash table for cells */ cellTableS = Yhash_table_create( EXPECTEDNUMCELLS ) ; netAllocS = EXPECTEDNUMNETS ; netarrayG = (NETBOXPTR *) Ysafe_malloc( netAllocS * sizeof(NETBOXPTR)); cellAllocS = EXPECTEDNUMCELLS ; cellarrayG = (CELLBOXPTR *)Ysafe_malloc(cellAllocS*sizeof(CELLBOXPTR)); } /* end initCellInfo */ /* ***************************************************************** */ /* cleanup operations at the end of readcells */ cleanupReadCells() { INT cell ; /* cell counter */ PADBOXPTR padptr ; /* current pad */ CELLBOXPTR ptr ; /* current pad cell */ if( errorFlagS || analog_errorS ){ /* we found all our syntax errors so abort */ closegraphics() ; YexitPgm( FAIL ) ; } /* the last cells - create pad macros for channel graph generator */ addCell("pad.macro.l",PADMACROTYPE ) ; /* add a tile for processing borders */ ptrS->tiles = (TILEBOXPTR) Ysafe_calloc( 1, sizeof(TILEBOX) ) ; endCell() ; addCell("pad.macro.t",PADMACROTYPE ) ; /* add a tile for processing borders */ ptrS->tiles = (TILEBOXPTR) Ysafe_calloc( 1, sizeof(TILEBOX) ) ; endCell() ; addCell("pad.macro.r",PADMACROTYPE ) ; /* add a tile for processing borders */ ptrS->tiles = (TILEBOXPTR) Ysafe_calloc( 1, sizeof(TILEBOX) ) ; endCell() ; addCell("pad.macro.b",PADMACROTYPE ) ; /* add a tile for processing borders */ ptrS->tiles = (TILEBOXPTR) Ysafe_calloc( 1, sizeof(TILEBOX) ) ; endCell() ; /* reallocate arrays to correct size */ netarrayG = (NETBOXPTR *) Ysafe_realloc( netarrayG, (numnetsG+1) * sizeof(NETBOXPTR) ) ; /* allocate and initialize terminal array */ termarrayG = (PINBOXPTR *) Ysafe_calloc( (numpinsG + 1), sizeof( PINBOXPTR ) ); /* now trim cellarray to proper size */ endsuperG = numcellsG + numsupercellsG ; endpadsG = endsuperG + numpadsG ; endpadgrpsG = endpadsG + numpadgroupsG ; ASSERT( totalcellsG == endpadgrpsG+NUMPADMACROS,"cleanupReadCells", "cells don't add up" ) ; cellarrayG = (CELLBOXPTR *) Ysafe_realloc( cellarrayG,(totalcellsG+1)* sizeof(CELLBOXPTR) ) ; /* build the pad arrays */ padarrayG = (PADBOXPTR *) Yvector_alloc(1,totalpadsG,sizeof(PADBOXPTR)) ; sortarrayG = (PADBOXPTR *) Yvector_alloc(1,totalpadsG,sizeof(PADBOXPTR)); placearrayG = (PADBOXPTR *) Yvector_alloc( 1,numpadsG,sizeof(PADBOXPTR)) ; for( cell = 1; cell <= totalpadsG; cell++ ){ ptr = cellarrayG[endsuperG + cell] ; padptr = ptr->padptr ; sortarrayG[cell] = padarrayG[cell] = padptr ; if( padptr->padtype == PADCELLTYPE ){ placearrayG[cell] = padptr ; } } /* set loop index range variables for cellarray */ pinsPerLenG = (DOUBLE) totPinS / (DOUBLE) perimG ; setpwates() ; sortpins() ; prnt_netinfo() ; /* tell user net information */ genorient(1,endpadsG ) ; updateFixedCells( INITIALIZE ) ; loadTermArray() ; build_active_array() ; build_soft_array() ; set_up_pinplace() ; /* for soft cell pin placement */ update_pins(TRUE) ; /* initial pin placement */ /* free memory */ Ysafe_free(cornerArrayS) ; Ysafe_free(pSideArrayS) ; Ysafe_cfree(kArrayS) ; Ybuster_free() ; } /* end cleanupReadCells */ /* ***************************************************************** */ /* add another cell to cell list and initialize fields */ addCell( cellName, cellType ) char *cellName ; CELLTYPE cellType ; { INT i ; INT *data ; curCellNameS = cellName ; /* for error messages */ curCellTypeS = cellType ; ERRORABORT() ; /* check memory of cell array */ if( ++totalcellsG >= cellAllocS ){ cellAllocS += EXPECTEDNUMCELLS ; cellarrayG = (CELLBOXPTR *) Ysafe_realloc( cellarrayG, cellAllocS*sizeof(CELLBOXPTR) ); } ptrS = cellarrayG[totalcellsG] = (CELLBOXPTR) Ysafe_malloc( sizeof(CELLBOX) ) ; /* add cell to hash table */ data = (INT *) Ysafe_malloc( sizeof(INT) ) ; *data = totalcellsG ; if( Yhash_search( cellTableS, curCellNameS, (char *) data, ENTER ) ){ sprintf( YmsgG, "Cellnames not unique:%s\n", curCellNameS ) ; M(ERRMSG,"addCell",YmsgG ) ; Ysafe_free( data ) ; errorFlagS = TRUE ; } ptrS->cname = cellName ; /* memory allocation in yylex */ ptrS->celltype = cellType ; ptrS->xcenter = 0 ; ptrS->ycenter = 0 ; ptrS->orient = 0 ; ptrS->numtiles = 0 ; ptrS->numpins = 0 ; ptrS->cur_inst = 0 ; ptrS->fixed = NULL ; ptrS->group_nested = FALSE ; ptrS->paths = NULL ; ptrS->aspect = 1.0 ; ptrS->aspUB = 1.0 ; ptrS->aspLB = 1.0 ; ptrS->pinptr = NULL ; ptrS->softpins = NULL ; ptrS->instptr = NULL ; ptrS->padptr = NULL ; ptrS->group = NULL ; ptrS->tiles = NULL ; ptrS->bounBox = NULL ; ptrS->nets = NULL ; ptrS->orientList[HOWMANYORIENT] = 0 ; if( cellType == SOFTCELLTYPE || cellType == CUSTOMCELLTYPE || cellType == STDCELLTYPE ){ for( i = 0 ; i < 8 ; i++ ) { ptrS->orientList[i] = FALSE ; } } else { /* for pads all orientations are valid */ for( i = 0 ; i < 8 ; i++ ) { ptrS->orientList[i] = TRUE ; } } if( cellType == SOFTCELLTYPE ){ ptrS->padptr = NULL ; ptrS->softflag = TRUE ; /* allocate space for uncommitted pins array */ numcellsG++ ; numsoftG++ ; numpingroupS = 0 ; } else if( cellType == STDCELLTYPE ){ ptrS->padptr = NULL ; ptrS->softflag = TRUE ; /* allocate space for uncommitted pins array */ numcellsG++ ; numstdcellG++ ; doPartitionG = TRUE ; } else if( cellType == CUSTOMCELLTYPE){ ptrS->softflag = FALSE ; ptrS->padptr = NULL ; numcellsG++ ; } else if( cellType == PADCELLTYPE || cellType == PADGROUPTYPE){ ptrS->softflag = FALSE ; pptrS =ptrS->padptr = (PADBOXPTR) Ysafe_malloc( sizeof(PADBOX) ) ; pptrS->fixed = FALSE ; pptrS->padside = ALL ; pptrS->permute = FALSE ; pptrS->ordered = FALSE ; pptrS->lowerbound = 0.0 ; pptrS->upperbound = 1.0 ; pptrS->padtype = cellType ; pptrS->cellnum = totalcellsG ; pptrS->valid_side[0] = TRUE ; pptrS->valid_side[1] = FALSE ; pptrS->valid_side[2] = FALSE ; pptrS->valid_side[3] = FALSE ; pptrS->valid_side[4] = FALSE ; totalpadsG++ ; if( cellType == PADGROUPTYPE ){ numchildrenS = 0 ; childAllocS = EXPECTEDNUMPADS ; pptrS->children = (INT *) Ysafe_malloc((childAllocS)*sizeof(INT)); pptrS->hierarchy = ROOT; numpadgroupsG++ ; } else { /* PADCELLTYPE */ pptrS->children = NULL; pptrS->hierarchy = NONE; numpadsG++ ; } } else if( cellType == SUPERCELLTYPE || cellType == GROUPCELLTYPE ){ numsupercellsG++ ; unique_classG-- ;/* start new exchange class for group cells */ /* allocate group record and set static */ curGroupS =ptrS->group = (GROUPBOXPTR) Ysafe_malloc( sizeof(GROUPBOX) ) ; curGroupS->fixed = (FIXEDBOXPTR) Ysafe_calloc( 1,sizeof(FIXEDBOX) ) ; curGroupS->cells = NULL ; } else if( cellType == PADMACROTYPE ){ /* do nothing right now */ } cellinstanceS = 0 ; /* beginning of possible instancelist */ /* save cellnumber */ ptrS->cellnum = totalcellsG ; /* reset xmin, ymax, etc. counters */ minxS = INT_MAX ; minyS = INT_MAX ; maxxS = INT_MIN ; maxyS = INT_MIN ; cornerCountS = 0 ; portFlagS = FALSE ; } /* end addCell */ /* ***************************************************************** */ /* perform cleanup operations on a cell */ endCell() { ERRORABORT() ; /* set the pSideArray for the softpins */ load_soft_pins( ptrS, pSideArrayS ) ; if( curCellTypeS == CUSTOMCELLTYPE || curCellTypeS == SOFTCELLTYPE || curCellTypeS == STDCELLTYPE ){ watesides( ptrS, pSideArrayS ) ; } if( curCellTypeS == SOFTCELLTYPE || curCellTypeS == STDCELLTYPE ){ } else if( curCellTypeS == PADGROUPTYPE){ /* realloc size of children array to final size */ pptrS->children = (INT *) Ysafe_realloc( pptrS->children,(numchildrenS+1) * sizeof(INT)); pptrS->children[HOWMANY] = numchildrenS ; } if( cellinstanceS ){ /* first save values to instance arrays */ instS->tile_inst[cellinstanceS] = ptrS->tiles ; instS->vert_inst[cellinstanceS] = ptrS->vertices ; instS->numtile_inst[cellinstanceS] = ptrS->numtiles ; instS->name_inst[cellinstanceS] = ptrS->cname ; instS->bounBox[cellinstanceS] = ptrS->bounBox ; instS->numsides[cellinstanceS] = ptrS->numsides ; ptrS->cur_inst = cellinstanceS ; } } /* end function endCell */ /* ***************************************************************** */ static INT findsidestr( side, direction ) char *side ; BOOL direction ; { if( direction == TRUE ){ /* BT case */ if( strcmp( side, "B" ) == STRINGEQ ){ return( TRUE ) ; } else if( strcmp( side, "T" ) == STRINGEQ ){ return( FALSE ) ; } } else { /* LR case */ if( strcmp( side, "L" ) == STRINGEQ ){ return( TRUE ) ; } else if( strcmp( side, "R" ) == STRINGEQ ){ return( FALSE ) ; } } sprintf( YmsgG, "Unknown side:%s\n", side ) ; M(ERRMSG,"findside", YmsgG ) ; setErrorFlag() ; return( FALSE ) ; } /* end findsidestr */ /* ***************************************************************** */ fixCell( fixedType, xloc, lorR, yloc, borT, xloc2, lorR2, yloc2, borT2 ) INT fixedType ; /* valid types - neighborhood. point, group */ INT xloc, yloc, xloc2, yloc2 ; char *lorR, *borT, *lorR2, *borT2 ; { INT leftOrRight, bottomOrTop ; INT leftOrRight2, bottomOrTop2 ; FIXEDBOXPTR fixptr ; if( scale_dataG ){ xloc = (INT) ( (DOUBLE) xloc / scaleS ) ; yloc = (INT) ( (DOUBLE) yloc / scaleS ) ; xloc2 = (INT) ( (DOUBLE) xloc2 / scaleS ) ; yloc2 = (INT) ( (DOUBLE) yloc2 / scaleS ) ; } leftOrRight = findsidestr( lorR, FALSE ) ; /* left right */ bottomOrTop = findsidestr( borT, TRUE ) ; /* bottom top */ leftOrRight2 = findsidestr( lorR2, FALSE ) ; /* left right */ bottomOrTop2 = findsidestr( borT2, TRUE ) ; /* bottom top */ if( fixedType == GROUPFLAG || fixedType == FIXEDGROUPFLAG ){ fixptr = ptrS->group->fixed ; if( fixedType == FIXEDGROUPFLAG ){ /* note that this cell has been fixed */ ptrS->fixed = (FIXEDBOXPTR) TRUE ; } } else { fixptr =ptrS->fixed = (FIXEDBOXPTR) Ysafe_malloc( sizeof(FIXEDBOX) ) ; } fixptr->fixedType = fixedType ; fixptr->xcenter = xloc ; fixptr->ycenter = yloc ; if( leftOrRight == TRUE ){ fixptr->leftNotRight = TRUE ; } else if( leftOrRight == FALSE ){ fixptr->leftNotRight = FALSE ; } else { M(ERRMSG,"fixCell", "Problem passing arguments to function\n" ) ; setErrorFlag() ; } if( bottomOrTop == TRUE ){ fixptr->bottomNotTop = TRUE ; } else if( bottomOrTop == FALSE ){ fixptr->bottomNotTop = FALSE ; } else { M(ERRMSG,"fixCell", "Problem passing arguments to function\n" ) ; setErrorFlag() ; } if( fixedType != POINTFLAG ){ fixptr->xloc1 = xloc ; fixptr->yloc1 = yloc ; fixptr->xloc2 = xloc2 ; fixptr->yloc2 = yloc2 ; if( leftOrRight2 == TRUE ){ fixptr->leftNotRight2 = TRUE ; } else if( leftOrRight2 == FALSE ){ fixptr->leftNotRight2 = FALSE ; } else { M(ERRMSG,"fixCell","Problem passing arguments to function\n"); setErrorFlag() ; } if( bottomOrTop2 == TRUE ){ fixptr->bottomNotTop2 = TRUE ; } else if( bottomOrTop2 == FALSE ){ fixptr->bottomNotTop2 = FALSE ; } else { M(ERRMSG,"fixCell","Problem passing arguments to function\n"); setErrorFlag() ; } } } /* end fixCell */ processCorners( numcorners ) INT numcorners ; { char *buster_msg ; /* message string to used by buster */ INT xx1, yy1, xx2, yy2 ; /* temp points */ INT k ; /* point counter */ INT xsum, ysum ; /* used to truncate cell correctly */ TILEBOXPTR tile ; YBUSTBOXPTR busterptr ; /* return record for busting routine */ VERTBOXPTR vert ; /* ptr to record of vertices of cell */ BOUNBOXPTR bounptr, /* ptr to bounBox[0] */ bounptr_orig ; /* ptr to bounBox[8] - original bbox */ /* +++++++++++++++++++ perform error checking +++++++++++++++++++ */ ERRORABORT() ; if( cornerCountS != numcorners ){ sprintf( YmsgG, "Incorrect number of corners for cell:%s\n", curCellNameS ) ; M(ERRMSG,"processCorners", YmsgG ) ; setErrorFlag() ; } if( scale_dataG ){ if( maxxS - minxS <= 1 || maxyS - minyS <= 1 ){ sprintf( YmsgG, "Cell:%s smaller than given scale data - resized to portsize.\n", curCellNameS ) ; M( WARNMSG, "processCorners", YmsgG ) ; /* make into a port instead of a possible 0 width object */ numcorners = cornerCountS = 4 ; cornerArrayS[1].x = -1 ; cornerArrayS[1].y = -1 ; cornerArrayS[2].x = -1 ; cornerArrayS[2].y = 1 ; cornerArrayS[3].x = 1 ; cornerArrayS[3].y = 1 ; cornerArrayS[4].x = 1 ; cornerArrayS[4].y = -1 ; minxS = -1 ; maxxS = 1; minyS = -1 ; maxyS = 1; /* set portFlag to true so we can move pins to boundary */ portFlagS = TRUE ; } } xsum = minxS + maxxS ; ysum = minyS + maxyS ; xcenterS = xsum / 2 ; ycenterS = ysum / 2 ; if( xsum < 0 && xsum % 2 ){ /* cell is asymmetrical and negative */ xcenterS-- ; } if( ysum < 0 && ysum % 2 ){ /* cell is asymmetrical and negative */ ycenterS-- ; } /* save the number of sides */ ptrS->numsides = numcorners ; Ybuster_init() ; sprintf( YmsgG, " (cell:%s) ", curCellNameS ) ; buster_msg = Ystrclone( YmsgG ) ; for( k = 1 ; k <= numcorners ; k++ ) { xx1 = cornerArrayS[k].x ; yy1 = cornerArrayS[k].y ; Ybuster_addpt( xx1, yy1 ) ; if( k == numcorners ) { xx2 = cornerArrayS[1].x ; yy2 = cornerArrayS[1].y ; } else { xx2 = cornerArrayS[ k + 1 ].x ; yy2 = cornerArrayS[ k + 1 ].y ; } } if(!(Ybuster_verify( buster_msg ))){ setErrorFlag() ; return ; } Ysafe_free( buster_msg ) ; /* +++++++++++++++++++ end perform error checking +++++++++++++++++++ */ /* This data structure allow quick change between x and x_new */ /* since placepin always uses the x fields and not x_new */ vert = ptrS->vertices = (VERTBOXPTR) Ysafe_malloc( sizeof(VERTBOX) ) ; /* the members of the structure */ vert->x = (INT *) Ysafe_malloc( (numcorners+1)*sizeof(INT) ) ; vert->x_orig = (INT *) Ysafe_malloc( (numcorners+1)*sizeof(INT) ) ; vert->x_new = (INT *) Ysafe_malloc( (numcorners+1)*sizeof(INT) ) ; vert->y = (INT *) Ysafe_malloc( (numcorners+1)*sizeof(INT) ) ; vert->y_orig = (INT *) Ysafe_malloc( (numcorners+1)*sizeof(INT) ) ; vert->y_new = (INT *) Ysafe_malloc( (numcorners+1)*sizeof(INT) ) ; vert->numpins = (FLOAT *) Yvector_alloc( 1,numcorners,sizeof(FLOAT) ) ; for( k = 1 ; k <= numcorners ; k++ ) { vert->x[k] = vert->x_orig[k] = cornerArrayS[k].x - xcenterS ; vert->y[k] = vert->y_orig[k] = cornerArrayS[k].y - ycenterS ; } if( curCellTypeS == SOFTCELLTYPE || curCellTypeS == CUSTOMCELLTYPE || curCellTypeS == STDCELLTYPE ){ /* calculate total cell perimeter before bust operation */ /* calculate over all instances */ perimG += perimeter( cornerArrayS, numcorners ) ; /* load pSideArray for weighing cells in dynamic wiring estimator */ for( k = 1 ; k <= numcorners ; k++ ) { if( k < numcorners ) { if( k % 2 == 1 ) { pSideArrayS[k].length = ABS(cornerArrayS[k + 1].y - cornerArrayS[k].y) ; pSideArrayS[k].vertical = 1 ; pSideArrayS[k].pincount = 0 ; pSideArrayS[k].position = cornerArrayS[k].x ; } else { pSideArrayS[k].length = ABS(cornerArrayS[k + 1].x - cornerArrayS[k].x) ; pSideArrayS[k].vertical = 0 ; pSideArrayS[k].pincount = 0 ; pSideArrayS[k].position = cornerArrayS[k].y ; } } else { pSideArrayS[k].length = ABS(cornerArrayS[1].x - cornerArrayS[k].x) ; pSideArrayS[k].vertical = 0 ; pSideArrayS[k].pincount = 0 ; pSideArrayS[k].position = cornerArrayS[k].y ; } } /* end for loop */ } /* -----------------now build tiles for cell---------------------- */ /* create bounding box of cell bounding box has 8 view for all cells*/ /* plus 9 field for original view of the bounding box */ ptrS->bounBox = (BOUNBOXPTR *) Ysafe_malloc( 9 * sizeof( BOUNBOXPTR ) ) ; for( k=0;k<=8;k++){ ptrS->bounBox[k] = (BOUNBOXPTR) Ysafe_malloc(sizeof( BOUNBOX ) ) ; } ptrS->boun_valid = FALSE ; /* now save the original bounding box for uaspect in 8 */ bounptr = ptrS->bounBox[0] ; bounptr_orig = ptrS->bounBox[8] ; bounptr_orig->l = bounptr->l = minxS - xcenterS ; bounptr_orig->r = bounptr->r = maxxS - xcenterS ; bounptr_orig->b = bounptr->b = minyS - ycenterS ; bounptr_orig->t = bounptr->t = maxyS - ycenterS ; ptrS->xcenter = xcenterS ; ptrS->ycenter = ycenterS ; tile = NIL(TILEBOXPTR) ; while( busterptr = Ybuster() ){ /* l = busterptr[1].x */ /* r = busterptr[4].x */ /* b = busterptr[1].y */ /* t = busterptr[2].y */ if( tile ){ tile->next = (TILEBOXPTR) Ysafe_malloc( sizeof( TILEBOX )); tile = tile->next ; } else { tile = ptrS->tiles = (TILEBOXPTR) Ysafe_malloc( sizeof( TILEBOX )); } tile->next = NULL ; ptrS->numtiles++ ; tile->left = tile->orig_left = busterptr[1].x - xcenterS ; tile->right = tile->orig_right = busterptr[4].x - xcenterS ; tile->bottom = tile->orig_bottom = busterptr[1].y - ycenterS ; tile->top = tile->orig_top = busterptr[2].y - ycenterS ; tile->lweight = 0.0 ; tile->rweight = 0.0 ; tile->bweight = 0.0 ; tile->tweight = 0.0 ; } /* add aspect ratio to design */ ptrS->orig_aspect = ptrS->aspect = (DOUBLE)(maxyS - minyS) / (DOUBLE)(maxxS - minxS); /* -----------------end build tiles for cell---------------------- */ } /* end processCorners */ /* ***************************************************************** */ addCorner( xpos, ypos ) INT xpos, ypos ; { if( ++cornerCountS >= tileptAllocS ){ tileptAllocS = cornerCountS + 1 ; cornerArrayS = ( YBUSTBOXPTR ) Ysafe_realloc( cornerArrayS, tileptAllocS * sizeof( YBUSTBOX ) ); pSideArrayS = (PSIDEBOX *) Ysafe_realloc( pSideArrayS, tileptAllocS * sizeof( PSIDEBOX ) ) ; } if( scale_dataG ){ if( portFlagS ){ /* port pins need to be on boundary for global router */ xpos = 0 ; ypos = 1 ; } else { xpos = (INT) ( (DOUBLE) xpos / scaleS ) ; ypos = (INT) ( (DOUBLE) ypos / scaleS ) ; } } cornerArrayS[cornerCountS].x = xpos ; cornerArrayS[cornerCountS].y = ypos ; minxS = MIN( minxS, xpos ) ; maxxS = MAX( maxxS, xpos ) ; minyS = MIN( minyS, ypos ) ; maxyS = MAX( maxyS, ypos ) ; } /* end addCorner */ /* ***************************************************************** */ initializeCorner( cell ) INT cell ; { ptrS = cellarrayG[cell] ; curCellTypeS = ptrS->celltype ; cornerCountS = 0 ; } /* end initializeCorner */ /* ***************************************************************** */ addClass( class ) INT class ; { ERRORABORT() ; if( ptrS->class >= 0 ){ /* this test is necessary since fix neighborhood may set it negative */ /* and we will not want to touch the value of it */ ptrS->class = class ; } } /* end addClass */ /* ***************************************************************** */ /* first in the list is the initial orientation */ initOrient( orient ) INT orient ; { ERRORABORT() ; ptrS->orient = - orient ; addOrient( orient ) ; } /* end initOrient */ /* ***************************************************************** */ /* addOrient sets orientation valid for this cell */ addOrient( orient ) INT orient ; { ERRORABORT() ; ptrS->orientList[orient] = TRUE ; /* allow this orientation */ ptrS->orientList[HOWMANYORIENT]++ ; } /* end addOrient */ /* ***************************************************************** */ /* if this routine is called it means we are reading the input of a previous TimberWolf run. */ set_cur_orient( orient ) INT orient ; { ERRORABORT() ; ptrS->orient = orient ; } /* end set_cur_orient */ /* ***************************************************************** */ /* load aspect ratios */ addAspectBounds( lowerBound, upperBound ) DOUBLE lowerBound, upperBound ; { ERRORABORT() ; ptrS->aspLB = lowerBound ; ptrS->aspUB = upperBound ; } /* end addAspectBounds */ /* ***************************************************************** */ PINBOXPTR addPinAndNet( pinName, signal ) char *pinName, *signal ; { static PINBOXPTR botpinS ; /* keep track of end of list */ INT *data, netx ; BOOL notInTable ; PINBOXPTR pinptr ; NETBOXPTR netptr ; notInTable = TRUE ; totPinS++ ; /* count the pins over all instances */ if( data = (INT *) Yhash_search( netTableS, signal, NULL, FIND ) ){ netx = *data ; notInTable = FALSE ; } else { /* else a new net load data holder */ data = (INT *) Ysafe_malloc( sizeof(INT) ) ; *data = netx = ++numnetsG ; if( Yhash_search( netTableS, signal, (char*) data, ENTER )){ sprintf( YmsgG, "Trouble adding signal:%s to hash table\n", signal ) ; M(ERRMSG,"addPinAndNet",YmsgG ) ; errorFlagS = TRUE ; } } if( cellinstanceS ){ if( notInTable ){ sprintf(YmsgG,"No match for net:%s in primary instance:%s\n", pinName, *ptrS->cname ) ; M( ERRMSG, "addPinAndNet", YmsgG ) ; errorFlagS = TRUE ; } /* at this point we are done */ return( NULL ) ; } /* increment number of pins */ numpinsG++ ; /* check memory of netarray */ if( numnetsG >= netAllocS ){ netAllocS += EXPECTEDNUMNETS ; netarrayG = (NETBOXPTR *) Ysafe_realloc( netarrayG, netAllocS * sizeof(NETBOXPTR) ) ; } /* see if this is the first time for this signal */ if( notInTable ){ netptr = netarrayG[netx] = (NETBOXPTR) Ysafe_malloc( sizeof(NETBOX) ) ; netptr->nname = signal ; /* allocated by yylex */ netptr->pins = NULL ; /* initialize list */ netptr->paths = NULL ; /* initialize list */ netptr->skip = 0 ; /* initialize list */ netptr->driveFactor = (FLOAT) 0.0 ; /* initialize timing */ netptr->max_driver = (FLOAT) 1.0 ; /* initialize timing */ netptr->min_driver = (FLOAT) 1.0 ; /* initialize timing */ netptr->analog_info = NIL(ANETPTR) ; } else { Ysafe_free( signal ) ; /* no need to keep this copy */ netptr = netarrayG[netx] ; } /* create list of pins on the net */ pinptr = (PINBOXPTR) Ysafe_malloc( sizeof(PINBOX) ); pinptr->next = netptr->pins ; netptr->pins = pinptr ; /* create a list of pins for this cell in order as given */ if( ptrS->pinptr ){ /* list has already been started */ botpinS->nextpin = pinptr ; } else { /* start new list */ ptrS->pinptr = pinptr ; } pinptr->nextpin = NULL ; botpinS = pinptr ; /* now initialize data */ pinptr->pinname = pinName ; /* allocated by yylex */ pinptr->pin = numpinsG ; pinptr->net = netx ; pinptr->cell = totalcellsG ; pinptr->xpos = 0 ; pinptr->ypos = 0 ; pinptr->instance = cellinstanceS ; /* allocate only size for one instance by default */ pinptr->txpos = 0 ; pinptr->typos = 0 ; pinptr->txpos_orig = (INT *) Ysafe_malloc( sizeof(INT) ) ; pinptr->typos_orig = (INT *) Ysafe_malloc( sizeof(INT) ) ; pinptr->newx = 0 ; pinptr->newy = 0 ; pinptr->flag = 0 ; pinptr->skip = 0 ; pinptr->eqptr = NULL ; pinptr->analog = NIL(ANALOGPTR) ; return( pinptr ) ; } /* add pin and net */ /* ***************************************************************** */ addPin( pinName, signal, layer, pinType ) char *pinName ; char *signal ; INT layer ; INT pinType ; { INT side ; INT howmany ; /* number of children - equivs */ SOFTBOXPTR sptr ; /* current soft information */ curPinNameS = pinName ; analogS = NIL(ANALOGPTR) ; ERRORABORT() ; if( pinType == SOFTEQUIVTYPE ){ /* get signal name from soft pin */ signal = Ystrclone( netarrayG[softpinS->net]->nname ) ; } pinS = addPinAndNet( pinName, signal ) ; equivpinS = 1 ; /* Note: initial pin positions will be last instance */ if( pinS ){ ptrS->numpins++ ; pinS->type = pinType ; pinS->layer = layer ; } else if( cellinstanceS ){ if(!(pinS = findTerminal( pinName, totalcellsG))){ sprintf(YmsgG,"No match for pin:%s in primary instance:%s\n", pinName, cellarrayG[totalcellsG]->cname ) ; M( ERRMSG, "addHardPin", YmsgG ) ; errorFlagS = TRUE ; return ; } /* reallocate space if necessary */ pinS->txpos_orig = (INT *) Ysafe_realloc( pinS->txpos_orig,(cellinstanceS+1)*sizeof(INT)); pinS->typos_orig = (INT *) Ysafe_realloc( pinS->typos_orig,(cellinstanceS+1)*sizeof(INT)); pinS->txpos = pinS->txpos_orig[cellinstanceS] = 0 ; pinS->typos = pinS->typos_orig[cellinstanceS] = 0 ; } /* now handle soft pin information */ if( ptrS->softflag ){ /* allocate space for array of instances */ if( cellinstanceS == 0 ){ pinS->soft_inst = (SOFTBOXPTR *) Ysafe_malloc( sizeof(SOFTBOXPTR) ); pinS->layer = layer ; } else { pinS->soft_inst = (SOFTBOXPTR *) Ysafe_realloc( pinS->soft_inst,instAllocS * sizeof(SOFTBOXPTR) ); } /* now allocate space for this instance */ spinptrS = pinS->soft_inst[cellinstanceS] = pinS->softinfo = (SOFTBOXPTR) Ysafe_malloc(sizeof(SOFTBOX)) ; spinptrS->children = NULL ; spinptrS->hierarchy = NONE ; spinptrS->parent = NULL ; /* build the restrict field and initialize HOWMANY [0] to 0 */ spinptrS->restrict1 = (INT *) Ysafe_calloc( 1, sizeof(INT) ) ; spinptrS->permute = FALSE ; spinptrS->fixed = FALSE ; spinptrS->ordered = FALSE ; spinptrS->lowerbound = 0.0 ; spinptrS->upperbound = 1.0 ; } if( pinType == SOFTPINTYPE ){ /* save the main softpin for future equiv use */ softpinS = pinS ; } else if( pinType == SOFTEQUIVTYPE ){ /* add to this pin's children */ sptr = softpinS->softinfo ; if( sptr->children ){ howmany = (INT) sptr->children[HOWMANY] ; sptr->children = (PINBOXPTR *) Ysafe_realloc( sptr->children, (++howmany+1) * sizeof(PINBOXPTR) ) ; } else { howmany = 1 ; sptr->children = (PINBOXPTR *) Ysafe_malloc( (howmany+1) * sizeof(PINBOXPTR) ) ; } sptr->children[HOWMANY] = (PINBOXPTR) howmany ; sptr->children[howmany] = pinS ; spinptrS->parent = softpinS ; } else if( !(ptrS->softflag) ){ pinS->softinfo = NULL ; } } /* end addPin */ /* ***************************************************************** */ set_pin_pos( xpos, ypos ) INT xpos, ypos ; { INT side ; INT howmany ; /* number of children - equivs */ ERRORABORT() ; if( scale_dataG ){ if( portFlagS ){ xpos = 0 ; ypos = 1 ; } else { xpos = (INT) ( (DOUBLE) xpos / scaleS ) ; ypos = (INT) ( (DOUBLE) ypos / scaleS ) ; } } check_pos( curPinNameS, xpos, ypos ) ; side = findside( pSideArrayS, ptrS , xpos , ypos ) ; loadside( pSideArrayS, side , 1.0 ) ; totxS = xpos ; totyS = ypos ; /* set global coordinates */ pinS->xpos = xpos ; pinS->ypos = ypos ; xpos -= xcenterS ; ypos -= ycenterS ; /* Note: initial pin positions will be last instance */ pinS->txpos = pinS->txpos_orig[cellinstanceS] = xpos ; pinS->typos = pinS->typos_orig[cellinstanceS] = ypos ; } /* end set_pin_pos */ /* ***************************************************************** */ static check_pos( pinname, xpos, ypos ) char *pinname ; INT xpos, ypos ; { if( xpos < minxS || xpos > maxxS || ypos < minyS || ypos > maxyS ){ sprintf( YmsgG, "Pin:%s cell:%s @(%d,%d) is outside cell boundary\n", pinname, curCellNameS, xpos, ypos ) ; M( ERRMSG, "check_pos", YmsgG ) ; setErrorFlag() ; } } /* end check_pos */ /* add an equivalent pin-updates the pin position to effective position */ addEquivPin( pinName, layer, xpos, ypos, pinType ) char *pinName ; INT layer ; INT xpos, ypos ; INT pinType ; { INT side ; EQUIVPTR temp, eqptr ; curPinNameS = pinName ; ERRORABORT() ; ASSERTNRETURN( pinS, "addEquivPin", "pinS is NULL" ) ; if( pinType != ADDEQUIVTYPE ){ if( scale_dataG ){ if( portFlagS ){ xpos = 0 ; ypos = 1 ; } else { xpos = (INT) ( (DOUBLE) xpos / scaleS ) ; ypos = (INT) ( (DOUBLE) ypos / scaleS ) ; } } if( curCellTypeS == SOFTCELLTYPE || curCellTypeS == CUSTOMCELLTYPE || curCellTypeS == STDCELLTYPE ){ check_pos( pinName, xpos, ypos ) ; side = findside( pSideArrayS, ptrS , xpos , ypos ) ; loadside( pSideArrayS, side , 1.0 ) ; } equivpinS++ ; totPinS++ ; totxS += xpos ; totyS += ypos ; /* average pin positions - note we leave _orig fields untouched */ pinS->txpos = (totxS / equivpinS ) - xcenterS; pinS->typos = (totyS / equivpinS ) - ycenterS; } else { /* get pinname from main soft pin */ pinName = softpinS->pinname ; } /* now save locations of equivalent pins for later output */ if( temp = pinS->eqptr ){ eqptr = pinS->eqptr = (EQUIVPTR) Ysafe_malloc(sizeof(EQUIVBOX)) ; eqptr->next = temp ; } else { eqptr = pinS->eqptr = (EQUIVPTR) Ysafe_malloc(sizeof(EQUIVBOX)) ; eqptr->next = NULL ; } if( cellinstanceS ){ /* more than one instance */ eqptr->txpos = (INT *) Ysafe_realloc( eqptr->txpos,(cellinstanceS+1) * sizeof(INT) ) ; eqptr->typos = (INT *) Ysafe_realloc( eqptr->typos,(cellinstanceS+1) * sizeof(INT) ) ; } else { /* by default only expect one instance */ eqptr->txpos = (INT *) Ysafe_malloc( sizeof(INT) ) ; eqptr->typos = (INT *) Ysafe_malloc( sizeof(INT) ) ; } /* now load the data */ eqptr->txpos[cellinstanceS] = xpos - xcenterS; eqptr->typos[cellinstanceS] = ypos - ycenterS; eqptr->pinname = pinName ; /* if the user didn't give us any layer set to 2 for now */ if( layer == 0 ){ layer = -2 ; } eqptr->layer = layer ; if( pinType == ADDEQUIVTYPE ){ /* build the restrict field and initialize HOWMANY [0] to 0 */ eqptr->restrict1 = (INT *) Ysafe_calloc( 1, sizeof(INT) ) ; } else { eqptr->restrict1 = NULL ; } } /* end addEquivPin */ /* ***************************************************************** */ set_restrict_type( object ) INT object ; { cur_restrict_objS = object ; } /* ***************************************************************** */ addSideRestriction( side ) INT side ; { INT howmany ; SOFTBOXPTR spin ; EQUIVPTR eqptr ; ERRORABORT() ; if( side < 0 || side > cornerCountS ) { M(ERRMSG,"addSideRestriction","value of side out of range"); sprintf(YmsgG,"\n\tside:%d range:1 to %d ", side, cornerCountS ) ; M(MSG,NULL,YmsgG); sprintf(YmsgG, "current cell is:%d\n", totalcellsG ) ; M(MSG,NULL,YmsgG); setErrorFlag() ; } /* this variable set by set_restrict type */ switch( cur_restrict_objS ){ case PINGROUPTYPE: spin = pingroupS->softinfo ; howmany = ++(spin->restrict1[HOWMANY]) ; spin->restrict1 = (INT *) Ysafe_realloc( spin->restrict1, (howmany+1)*sizeof(INT) ) ; spin->restrict1[howmany] = side ; break ; case SOFTPINTYPE: case SOFTEQUIVTYPE: spin = pinS->softinfo ; howmany = ++(spin->restrict1[HOWMANY]) ; spin->restrict1 = (INT *) Ysafe_realloc( spin->restrict1, (howmany+1)*sizeof(INT) ) ; spin->restrict1[howmany] = side ; break ; case ADDEQUIVTYPE: eqptr = softpinS->eqptr ; howmany = ++(eqptr->restrict1[HOWMANY]) ; eqptr->restrict1 = (INT *) Ysafe_realloc( eqptr->restrict1, (howmany+1)*sizeof(INT) ) ; eqptr->restrict1[howmany] = side ; break ; } /* end switch on current object */ } /* end addSideRestriction * /* ***************************************************************** */ add_pinspace( lower, upper ) DOUBLE lower ; DOUBLE upper ; { char *name ; /* name of current object */ SOFTBOXPTR spin ; /* soft pin information of current pin or pg */ ERRORABORT() ; switch( cur_restrict_objS ){ case PINGROUPTYPE: spin = pingroupS->softinfo ; name = pingroupS->pinname ; break ; case SOFTPINTYPE: case SOFTEQUIVTYPE: spin = pinS->softinfo ; name = pinS->pinname ; break ; case ADDEQUIVTYPE: return ; } /* end switch on current object */ spin->fixed = TRUE ; if( lower > 1.0 || upper > 1.0 ){ sprintf(YmsgG, "side space must be less or equal to 1.0 for pin: %s\n", name ) ; M(ERRMSG,"add_pinspace",YmsgG ) ; setErrorFlag() ; } if( lower < 0.0 || upper < 0.0 ){ sprintf(YmsgG, "side space must be greater or equal to 0.0 for pin: %s\n",name ) ; M(ERRMSG,"add_pinspace",YmsgG ) ; setErrorFlag() ; } if( lower > upper ){ sprintf(YmsgG, "side space upper bound must be greater or equal to lower bound for pin: %s\n", name ) ; M(ERRMSG,"add_pinspace",YmsgG ) ; setErrorFlag() ; } spin->lowerbound = lower ; spin->upperbound = upper ; } /* end add_pinspace */ /* ***************************************************************** */ add_soft_array() { INT i ; PINBOXPTR *sarray ; PINBOXPTR pin ; if( cellinstanceS != 0 ){ return ; } sarray = ptrS->softpins = (PINBOXPTR *) Ysafe_malloc( (ptrS->numpins+1) * sizeof(PINBOXPTR) ) ; i = 0 ; for( pin = ptrS->pinptr; pin ; pin = pin->nextpin ){ sarray[++i] = pin ; } sarray[HOWMANY] = (PINBOXPTR) i ; } /* end add_soft_array */ start_pin_group( pingroup, permute ) char *pingroup ; BOOL permute ; { INT i ; INT curpingroup ; INT howmany ; PINBOXPTR *sarray ; SOFTBOXPTR spin ; ERRORABORT() ; numchildrenS = 0 ; childAllocS = 1 ; /* allocate space for array of instances */ if( cellinstanceS == 0 ){ /* pins in array go 1 ... numpins, pingroup1, pingroup2 ... */ curpingroup = ptrS->numpins + ++numpingroupS ; sarray = ptrS->softpins = (PINBOXPTR *) Ysafe_realloc( ptrS->softpins, (curpingroup+1) * sizeof(PINBOXPTR) ) ; sarray[HOWMANY] = (PINBOXPTR) curpingroup ; /* allocate space for pingroup */ pingroupS = sarray[curpingroup] = (PINBOXPTR) Ysafe_calloc( 1, sizeof(PINBOX) ); /* now initialize data */ pingroupS->pinname = pingroup ; /* allocated by yylex */ pingroupS->txpos_orig = (INT *) Ysafe_malloc( sizeof(INT) ) ; pingroupS->typos_orig = (INT *) Ysafe_malloc( sizeof(INT) ) ; pingroupS->type = PINGROUPTYPE ; pingroupS->soft_inst = (SOFTBOXPTR *) Ysafe_malloc( sizeof(SOFTBOXPTR) ); } else { /* first find pingroup in softpin array */ sarray = ptrS->softpins ; howmany = (INT) sarray[HOWMANY] ; pingroupS = NIL(PINBOXPTR) ; for( i = 1; i <= howmany; i++ ){ if( strcmp( pingroup, sarray[i]->pinname ) == STRINGEQ ){ pingroupS = sarray[i] ; break ; } } if( pingroupS ){ pingroupS->soft_inst = (SOFTBOXPTR *) Ysafe_realloc( pingroupS->soft_inst,instAllocS * sizeof(SOFTBOXPTR) ); } else { sprintf(YmsgG,"No match for pingroup:%s in primary instance:%s\n", pingroup, cellarrayG[totalcellsG]->cname ) ; M( ERRMSG, "start_pin_group", YmsgG ) ; errorFlagS = TRUE ; return ; } } /* now allocate space for this instance */ pingroupS->soft_inst[cellinstanceS] = pingroupS->softinfo = (SOFTBOXPTR) Ysafe_calloc( 1, sizeof(SOFTBOX)) ; spin = pingroupS->softinfo ; spin->permute = permute ; spin->fixed = FALSE ; spin->ordered = FALSE ; spin->hierarchy = ROOT ; spin->lowerbound = 0.0 ; spin->upperbound = 1.0 ; spin->children = (PINBOXPTR *) Ysafe_malloc( sizeof(PINBOXPTR) ) ; spin->restrict1 = (INT *) Ysafe_calloc( 1, sizeof(INT) ) ; spin->parent = NULL ; } /* end start_pin_group */ /* ***************************************************************** */ /* add this pad to the current pad group */ add2pingroup( pinName, ordered ) char *pinName ; BOOL ordered ; /* ordered flag is true if padgroup is fixed */ { INT i ; INT howmany ; PINBOXPTR pin ; PINBOXPTR cpin ; SOFTBOXPTR spin ; SOFTBOXPTR pingroup_spin ; INT curpingroup ; ERRORABORT() ; /* check pads for correctness */ for( pin = ptrS->pinptr ; pin ; pin = pin->nextpin ){ spin = pin->softinfo ; if( strcmp(pinName, pin->pinname) == STRINGEQ ){ if( spin->hierarchy == LEAF ){ sprintf(YmsgG, "pin %s was included in more than 1 pin group\n", pin->pinname); M(ERRMSG,"add2pingroup",YmsgG ) ; setErrorFlag() ; return ; } /* check memory of pin array */ pingroup_spin = pingroupS->softinfo ; if( ++numchildrenS >= childAllocS ){ childAllocS += EXPECTEDPINGRP ; pingroup_spin->children = (PINBOXPTR *) Ysafe_realloc( pingroup_spin->children, childAllocS * sizeof(PINBOXPTR) ) ; } pingroup_spin->children[numchildrenS] = pin ; pingroup_spin->children[HOWMANY] = (PINBOXPTR) numchildrenS ; spin->parent = pingroupS ; /* now update any equivalent subpins to leaves */ if( spin->hierarchy == NONE && spin->children ){ howmany = (INT) spin->children[HOWMANY] ; for( i = 1; i <= howmany; i++ ){ cpin = spin->children[i] ; if( cpin->type == SOFTEQUIVTYPE ){ cpin->softinfo->hierarchy = LEAF ; cpin->softinfo->ordered = ordered ; } } } spin->hierarchy = LEAF ; spin->ordered = ordered ; return; } } /* if no match above must be subroot */ curpingroup = ptrS->numpins + numchildrenS ; for( i = ptrS->numpins ; i < curpingroup; i++ ){ pin = ptrS->softpins[i] ; spin = pin->softinfo ; if (strcmp(pinName, pin->pinname) == STRINGEQ) { if (spin->hierarchy == SUBROOT) { sprintf(YmsgG, "pin group %s was included in more than 1 pin group\n", pin->pinname); M(ERRMSG,"add2pingroup",YmsgG ) ; setErrorFlag() ; return ; } pingroup_spin = pingroupS->softinfo ; if( ++numchildrenS >= childAllocS ){ childAllocS += EXPECTEDPINGRP ; pingroup_spin->children = (PINBOXPTR *) Ysafe_realloc( pingroup_spin->children, childAllocS * sizeof(PINBOXPTR) ) ; } pingroup_spin->children[numchildrenS] = pin ; pingroup_spin->children[HOWMANY] = (PINBOXPTR) numchildrenS ; spin->parent = pingroupS ; spin->hierarchy = SUBROOT ; spin->ordered = ordered ; return ; } } sprintf(YmsgG,"cannot find pin <%s> for pin_group <%s>\n", pinName,ptrS->softpins[curpingroup]->pinname ); M(ERRMSG,"add2pingroup",YmsgG ) ; return ; } /* end add2pingroup */ /* ***************************************************************** */ addSideSpace( lower, upper ) DOUBLE lower ; DOUBLE upper ; { ERRORABORT() ; pptrS->fixed = TRUE ; if( lower > 1.0 || upper > 1.0 ){ sprintf(YmsgG, "side space must be less or equal to 1.0 for pad: %s\n",ptrS->cname ) ; M(ERRMSG,"addSideSpace",YmsgG ) ; setErrorFlag() ; } if( lower < 0.0 || upper < 0.0 ){ sprintf(YmsgG, "side space must be greater or equal to 0.0 for pad: %s\n",ptrS->cname ) ; M(ERRMSG,"addSideSpace",YmsgG ) ; setErrorFlag() ; } if( lower > upper ){ sprintf(YmsgG, "side space upper bound must be greater or equal to lower bound for pad: %s\n",ptrS->cname ) ; M(ERRMSG,"addSideSpace",YmsgG ) ; setErrorFlag() ; } pptrS->lowerbound = lower ; pptrS->upperbound = upper ; } /* end addSideSpace */ /* ***************************************************************** */ addPadSide( side ) char *side ; { INT numsides ; /* length of side restriction string */ INT i ; /* counter */ ERRORABORT() ; pptrS->valid_side[ALL] = FALSE ; numsides = strlen( side ) ; for( i = 0 ; i < numsides; i++ ){ switch( side[i] ){ case 'B' : pptrS->valid_side[B] = TRUE ; break ; case 'L' : pptrS->valid_side[L] = TRUE ; break ; case 'R' : pptrS->valid_side[R] = TRUE ; break ; case 'T' : pptrS->valid_side[T] = TRUE ; break ; default: sprintf( YmsgG, "side restriction not specified properly for pad:%s\n", ptrS->cname ); M(ERRMSG,"addPadSide",YmsgG ) ; setErrorFlag() ; } /* end switch */ } } /* end addPadSide */ /* ***************************************************************** */ /* set whether a pad group can be permuted */ setPermutation( permuteFlag ) { ERRORABORT() ; pptrS->permute = permuteFlag ; } /* end setPermutation */ /* ***************************************************************** */ /* add this pad to the current pad group */ add2padgroup( padName, ordered ) char *padName ; BOOL ordered ; /* ordered flag is true if pad is ordered in padgroup */ { INT i, endofpads, endofgroups, endofcells ; ERRORABORT() ; endofpads = numcellsG + numpadsG ; endofcells = numcellsG + numsupercellsG ; /* check pads for correctness */ for (i = numcellsG + 1; i <= endofpads; ++i) { if (strcmp(padName, cellarrayG[i]->cname) == STRINGEQ) { if (cellarrayG[i]->padptr->hierarchy == LEAF) { sprintf(YmsgG, "pad %s was included in more than 1 pad group\n", cellarrayG[i]->cname); M(ERRMSG,"add2padgroup",YmsgG ) ; setErrorFlag() ; return ; } /* check memory of pin array */ if( ++numchildrenS >= childAllocS ){ childAllocS += EXPECTEDNUMPADS ; pptrS->children = (INT *) Ysafe_realloc( pptrS->children, childAllocS * sizeof(INT) ) ; } pptrS->children[numchildrenS] = i - endofcells ; cellarrayG[i]->padptr->hierarchy = LEAF ; cellarrayG[i]->padptr->ordered = ordered ; /* total pins of the leaves */ ptrS->numpins += cellarrayG[i]->numpins; return; } } /* if no match above must be subroot */ endofgroups = numcellsG + numpadsG + numpadgroupsG ; for (i = endofpads; i <= endofgroups; ++i) { if (strcmp(padName, cellarrayG[i]->cname) == STRINGEQ) { if (cellarrayG[i]->padptr->hierarchy == SUBROOT) { sprintf(YmsgG,"pad group %s was included in more than 1 pad group\n", cellarrayG[i]->cname); M(ERRMSG,"add2padgroup",YmsgG ) ; setErrorFlag() ; return ; } /* check memory of pin array */ if( ++numchildrenS >= childAllocS ){ childAllocS += EXPECTEDNUMPADS ; pptrS->children = (INT *) Ysafe_realloc( pptrS->children, childAllocS * sizeof(INT) ) ; } pptrS->children[numchildrenS] = i - endofcells ; cellarrayG[i]->padptr->hierarchy = SUBROOT ; cellarrayG[i]->padptr->ordered = ordered ; /* total pins of the leaves */ ptrS->numpins += cellarrayG[i]->numpins; return ; } } sprintf(YmsgG,"cannot find pad <%s> for pad_group <%s>\n", padName,ptrS->cname); M(ERRMSG,"add2padgroup",YmsgG ) ; return ; } /* end add2PadGroup */ /* ***************************************************************** */ add_cell_to_group( cellName ) char *cellName ; { GLISTPTR tempCell ; INT cell, *data ; CELLBOXPTR cptr ; if(!(data = (INT *) Yhash_search( cellTableS, cellName, NULL, FIND ))){ sprintf( YmsgG, "Couldn't find cellname:%s for group\n",cellName ); M(ERRMSG,"add_cell_to_group",YmsgG ) ; errorFlagS = TRUE ; return ; } cell = *data ; if( tempCell = curGroupS->cells ){ curGroupS->cells = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; curGroupS->cells->next = tempCell ; } else { /* start list */ curGroupS->cells = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; curGroupS->cells->next = NULL ; } cptr = cellarrayG[cell] ; if( cptr->group_nested ){ /* group_nest field should be NULL if cell is not nested */ sprintf( YmsgG, "cell %d:%s appears in more than one group\n", cell, cptr->cname ) ; M(ERRMSG,"add_cell_to_group",YmsgG ) ; errorFlagS = TRUE ; } else { cptr->group = curGroupS ; /* save cell in generic list */ curGroupS->cells->p.cell = cell ; cptr->group_nested = TRUE ; } /* set exchange class so cells can't leave group thru pairwise swap */ cptr->class = unique_classG ; } /* end add_cell_to_group */ /* add a cell to the instance array of the defining cell */ add_instance( instName ) char *instName ; { if( cellinstanceS++ == 0 ){ /* our first instance we now have two instances */ instS = ptrS->instptr = (INSTBOXPTR) Ysafe_malloc( sizeof(INSTBOX) ) ; ptrS->cur_inst = 0 ; instS->numinstances = 1 ; instAllocS = 2 ; /* default is just two instances */ /* allocate arrays for instances */ instS->tile_inst = (TILEBOXPTR *) Ysafe_calloc( instAllocS, sizeof(TILEBOXPTR) ) ; instS->bounBox = (BOUNBOXPTR **) Ysafe_calloc( instAllocS, sizeof(BOUNBOXPTR *) ) ; instS->numtile_inst = (INT *) Ysafe_calloc( instAllocS, sizeof(INT) ) ; instS->vert_inst = (VERTBOXPTR *) Ysafe_malloc( instAllocS*sizeof(VERTBOXPTR) ) ; instS->name_inst = (char **) Ysafe_malloc( instAllocS*sizeof(char *) ) ; /* store main instance in element 0 of arrays */ instS->tile_inst[0] = ptrS->tiles ; instS->bounBox[0] = ptrS->bounBox ; instS->numtile_inst[0] = ptrS->numtiles ; instS->vert_inst[0] = ptrS->vertices ; instS->name_inst[0] = ptrS->cname ; instS->name_inst[1] = instName ; /* now for softcells */ /* allocate arrays for instances */ instS->numsides = (INT *) Ysafe_calloc( instAllocS, sizeof(INT) ) ; /* store main instance in element 0 of arrays */ instS->numsides[0] = ptrS->numsides ; } else { /* realloc space for instances */ /* instances are rare and we are only dealing with pointers so */ /* always realloc, leave code general enough to change */ instAllocS += EXPECTEDINSTANCES ; instS->tile_inst = (TILEBOXPTR *) Ysafe_realloc(instS->tile_inst,instAllocS*sizeof(TILEBOXPTR)); instS->vert_inst = (VERTBOXPTR *) Ysafe_realloc(instS->vert_inst,instAllocS*sizeof(VERTBOXPTR)); instS->numtile_inst = (INT *) Ysafe_realloc( instS->numtile_inst, instAllocS*sizeof(INT) ) ; instS->bounBox = (BOUNBOXPTR **) Ysafe_realloc(instS->bounBox,instAllocS*sizeof(BOUNBOXPTR *)); instS->name_inst = (char **) Ysafe_realloc(instS->name_inst,instAllocS*sizeof(char *) ) ; instS->numsides = (INT *) Ysafe_realloc( instS->numsides,instAllocS*sizeof(INT)); } minxS = INT_MAX ; minyS = INT_MAX ; maxxS = INT_MIN ; maxyS = INT_MIN ; ptrS->numtiles = 0 ; cornerCountS = 0 ; instS->numinstances++ ; numinstancesG++ ; } /* end add_cell_instance */ INT get_tile_count() { return( tileptAllocS / 2 ) ; } /* end get_tile_count() */ add_analog( numcorners ) INT numcorners ; { ERRORABORT() ; /* allocate space for array of instances */ if( cellinstanceS == 0 ){ pinS->ainst = (ANALOGPTR *) Ysafe_malloc( sizeof(ANALOGPTR) ); } else { pinS->ainst = (ANALOGPTR *) Ysafe_realloc( pinS->ainst, instAllocS * sizeof(ANALOGPTR) ); } analogS = pinS->analog = (ANALOGPTR) Ysafe_malloc( sizeof(ANALOGBOX) ) ; pinS->ainst[cellinstanceS] = analogS ; /* now fill in data */ if( numcorners >= 4 ){ analogS->x_contour = (INT *) Ysafe_malloc( numcorners * sizeof(INT)) ; analogS->y_contour = (INT *) Ysafe_malloc( numcorners * sizeof(INT)) ; analogS->num_corners = numcorners ; cornerCountS = 0 ; } else { analogS->x_contour = NIL(INT) ; analogS->y_contour = NIL(INT) ; analogS->num_corners = 0 ; } analogS->current = INIT_CURRENT ; analogS->power = (FLOAT) 0.0 ; analogS->no_layer_change = FALSE ; } /* end add_analog */ add_pin_contour( x, y ) INT x, y ; { if( cornerCountS >= analogS->num_corners ){ sprintf( YmsgG, "Incorrect number of vertices for pin:%s\n", curPinNameS ) ; M(ERRMSG,"add_pin_contour", YmsgG ) ; setErrorFlag() ; cornerCountS = 0 ; /* reset to avoid numerous error msgs */ } ERRORABORT() ; analogS->x_contour[cornerCountS] = x ; analogS->y_contour[cornerCountS++] = y ; } /* end start_pin_contour */ add_current( current ) FLOAT current ; { if(!(analogS)){ add_analog( 0 ) ; } analogS->current = current ; } /* end add_current */ add_power( power ) FLOAT power ; { if(!(analogS)){ add_analog( 0 ) ; } analogS->power = power ; } /* end add_power */ no_layer_change() { if(!(analogS)){ add_analog( 0 ) ; } analogS->no_layer_change = TRUE ; } /* end no_cross_under */ process_pin() { INT i ; /* point counter */ INT side ; /* current side for pin */ INT ptx, pty ; /* current point of interest */ INT xpos, ypos ; /* center of pin */ INT minx, miny, maxx, maxy ; /* bounding box of pin contour */ char *buster_msg ; /* message string to used by buster */ INT xx1, yy1, xx2, yy2 ; /* temp points */ ERRORABORT() ; if(!(analogS) || analogS->num_corners < 4 ){ return ; /* no work to do */ } /* now check the points to make sure they are good */ sprintf( YmsgG, " (cell:%s pin:%s) ", curCellNameS, pinS->pinname ) ; buster_msg = Ystrclone( YmsgG ) ; Ybuster_check_rect_init( buster_msg ) ; minx = INT_MAX ; miny = INT_MAX ; maxx = INT_MIN ; maxy = INT_MIN ; for( i = 0 ; i < analogS->num_corners ; i++ ) { xx1 = analogS->x_contour[i] ; yy1 = analogS->y_contour[i] ; if( i == analogS->num_corners-1 ) { xx2 = analogS->x_contour[0] ; yy2 = analogS->y_contour[0] ; } else { xx2 = analogS->x_contour[ i + 1 ] ; yy2 = analogS->y_contour[ i + 1 ] ; } if( Ybuster_check_rect( xx1, yy1, xx2, yy2 ) ){ analog_errorS = TRUE ; } /* find bounding box of pins */ minx = MIN( minx, xx1 ) ; maxx = MAX( maxx, xx1 ) ; miny = MIN( miny, yy1 ) ; maxy = MAX( maxy, yy1 ) ; } Ysafe_free( buster_msg ) ; /* now set the center of the pin to this location */ xpos = (minx + maxx) / 2 ; ypos = (miny + maxy) / 2 ; /* now subtract off the cell center */ for( i = 0 ; i < analogS->num_corners ; i++ ) { analogS->x_contour[i] -= xcenterS ; analogS->y_contour[i] -= ycenterS ; } set_pin_pos( xpos, ypos ) ; } /* end process_analog_pin */ graywolf-0.1.4+20170307gite1bf319/src/twmc/initialize.h000066400000000000000000000014061305746555600220400ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: initialize.h DESCRIPTION:Header file for initialize.c CONTENTS: DATE: March 15, 1990 REVISIONS: Wed Dec 19 19:38:46 EST 1990 - added analog pin type. ----------------------------------------------------------------- */ /* ***************************************************************** static char SccsId[] = "@(#) initialize.h version 3.4 12/19/90" ; ***************************************************************** */ #ifndef INITIALIZE_H #define INITIALIZE_H #define PINGROUPTYPE 1 #define HARDPINTYPE 2 #define SOFTPINTYPE 3 #define SOFTEQUIVTYPE 4 #define HARDEQUIVTYPE 5 #define ADDEQUIVTYPE 6 #define ANALOGPINTYPE 7 #endif /* INITIALIZE_H */ graywolf-0.1.4+20170307gite1bf319/src/twmc/initnets.c000066400000000000000000000351261305746555600215350ustar00rootroot00000000000000/* * Copyright (C) 1990-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: initnets.c DESCRIPTION:Initialize the net information. Split this from readnets.y. CONTENTS: DATE: Dec 13, 1990 REVISIONS: Thu Dec 20 00:02:54 EST 1990 - made net cap and res. matches work. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) initnets.c version 1.5 10/18/91" ; #endif #include #include #include #include #include /* redefine yacc and lex globals */ #define HOWMANY 0 static YHASHPTR netTableS ; static BOOL abortFlagS = FALSE ; static INT total_num_pathS = 0 ; static GLISTPTR netPtrS ; static PATHPTR pathPtrS = NULL ; /* start of path list */ /* cur bot of path list so list is in order given by user debug easier */ static PATHPTR curPathS ; static INT numcapmatchS = 0 ; /* number of cap matches */ static INT numresmatchS = 0 ; /* number of res matches */ static INT anetS ; /* current analog net */ static ANETPTR aptrS ; /* current analog net information record */ static COMMONPTR commonS ; /* current common point record */ /* initialization before parsing nets */ init_nets() { YHASHPTR getNetTable() ; numpathsG = 0 ; netTableS = getNetTable() ; net_cap_matchG = (INT **) Ysafe_calloc( numnetsG+1,sizeof(INT *) ) ; net_res_matchG = (INT **) Ysafe_calloc( numnetsG+1,sizeof(INT *) ) ; } /* end init_nets */ /* cleanup after parsing nets */ cleanup_nets() { if( abortFlagS ){ closegraphics() ; YexitPgm( FAIL ) ; } build_path_array() ; init_path_set() ; init_net_set() ; add_paths_to_cells() ; } /* end cleanup_nets */ set_net_error() { abortFlagS = TRUE ; } /* end set_net_error */ static INT find_net( netname ) char *netname ; { char *data ; int net ; if(!(data = Yhash_search( netTableS, netname, NULL, FIND))){ OUT2( "The net named: %s in the .net file ", netname ); OUT1( "was not encountered while reading\n"); OUT1( "the .cel file --- FATAL error\n"); Ymessage_error_count() ; abortFlagS = TRUE ; return( 0 ) ; } net = * ( (INT *) data ) ; if( net < 1 || net > numnetsG ){ sprintf( YmsgG, "net:%s - number:%d out of bounds\n", netname, net ) ; M( ERRMSG, "find_net", YmsgG ) ; return( 0 ) ; } else { return( net ) ; } } /* end find_net */ add_path( pathFlag, net ) BOOL pathFlag ; char *net ; { INT net_num ; GLISTPTR tempNetPtr ; /* first make sure that data is good */ if(!(net_num = find_net( net ))){ return ; } if( pathFlag == STARTPATH ){ /* see if pathptr exists */ if( pathPtrS ){ curPathS->next = (PATHPTR) Ysafe_malloc( sizeof(PATHBOX) ) ; curPathS = curPathS->next ; } else { /* first path - start list */ curPathS = pathPtrS = (PATHPTR) Ysafe_malloc( sizeof(PATHBOX) ) ; } curPathS->next = NULL ; netPtrS = curPathS->nets = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; netPtrS->next = NULL ; } else { /* continuing a path */ tempNetPtr = netPtrS ; ASSERT( netPtrS, "add_path", "net pointer should be non-NULL" ) ; netPtrS = curPathS->nets = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; netPtrS->next = tempNetPtr ; } /* get data from field */ netPtrS->p.net = net_num ; /* string bufferS is allocated in lex */ if( net ){ Ysafe_free( net ) ; } } /* end add_path */ end_path(lower_bound, upper_bound, priority ) INT lower_bound, upper_bound, priority ; { GLISTPTR nets, path_ptr, tempPath ; NETBOXPTR dimptr ; INT net_number ; if( abortFlagS ){ /* report as many errors as possible without crashing */ return ; } curPathS->lower_bound = lower_bound ; curPathS->upper_bound = upper_bound ; curPathS->priority = priority ; total_num_pathS++ ; /* total number of paths given */ if( priority ){ numpathsG++ ; /* increment number of active paths */ /* add path to path list in netarray */ for( nets = curPathS->nets; nets ; nets = nets->next ){ net_number = nets->p.net ; dimptr = netarrayG[net_number] ; if( tempPath = dimptr->paths ){ path_ptr = dimptr->paths = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; path_ptr->next = tempPath ; } else { /* start a new list */ path_ptr = dimptr->paths = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; path_ptr->next = NULL ; } /* use total_num_pathS so we can index patharrayG */ path_ptr->p.path = total_num_pathS ; } } } /* end function end_path */ build_path_array() { INT i ; PATHPTR curPtr ; patharrayG = (PATHPTR *) Ysafe_malloc( (total_num_pathS+1)*sizeof(PATHPTR) ) ; i = 1 ; for( curPtr = pathPtrS; curPtr ; curPtr = curPtr->next ){ patharrayG[i++] = curPtr ; } } /* end build_path_array */ PATHPTR get_path_list() { return( pathPtrS ) ; } /* end get_path_list */ INT get_total_paths() { return( total_num_pathS ) ; } /* end get_total_paths */ add_paths_to_cells() { INT i, j ; INT howmany ; INT net_number ; PSETPTR pathlist, enum_path_set() ; CELLBOXPTR ptr ; GLISTPTR path_ptr, tempPath ; NETBOXPTR dimptr ; PINBOXPTR pinptr ; for( i=1;i<=endsuperG; i++ ){ ptr = cellarrayG[i] ; clear_path_set() ; /* look for the UNIQUE paths that connects to this cell */ for( pinptr = ptr->pinptr ; pinptr ; pinptr = pinptr->nextpin ) { net_number = pinptr->net ; /* now go to net array */ dimptr = netarrayG[net_number] ; /* look at all paths that use this net */ for( path_ptr=dimptr->paths;path_ptr;path_ptr=path_ptr->next){ add2path_set( path_ptr->p.path ) ; } } /* now add UNIQUE list of paths to this cell */ for( pathlist=enum_path_set(); pathlist; pathlist=pathlist->next){ if( tempPath = ptr->paths ){ path_ptr = ptr->paths = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; path_ptr->next = tempPath ; } else { /* start a new list */ path_ptr = ptr->paths = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; path_ptr->next = NULL ; } /* copy path to cell list of paths */ path_ptr->p.path = pathlist->path ; } } } /* end add_paths_to_cells */ init_analog( net ) char *net ; { INT anet ; /* first make sure that data is good */ if(!(anetS = find_net( net ) )){ return ; } aptrS = netarrayG[anetS]->analog_info = (ANETPTR) Ysafe_malloc( sizeof(ANETBOX) ) ; aptrS->num_common_points = 0 ; aptrS->net_type = 0 ; aptrS->common_pts = NIL(COMMONPTR *) ; aptrS->max_drop = INIT_DROP ; aptrS->cap_upper_bound = INIT_CAP ; aptrS->res_upper_bound = INIT_RES ; } /* end init_analog */ set_cap_upper_bound( cap ) DOUBLE cap ; { aptrS->cap_upper_bound = cap ; } /* end set_cap_upper_bound */ set_res_upper_bound( res ) DOUBLE res ; { aptrS->res_upper_bound = res ; } /* end set_res_upper_bound */ set_net_type( net_type ) INT net_type ; { switch( net_type ){ case SHIELDING_NET: aptrS->net_type |= SHIELDMASK ; break ; case NOISY_NET: aptrS->net_type |= NOISYMASK ; break ; case SENSITIVE_NET: aptrS->net_type |= SENSITIVEMASK ; break ; } } /* end set_net_type */ set_max_voltage_drop( drop ) DOUBLE drop ; { aptrS->max_drop = drop ; } /* end set_max_voltage_drop */ add_common_pt() { INT pt ; /* current number of common pts */ pt = ++aptrS->num_common_points ; if( aptrS->num_common_points == 1 ){ /* first time */ aptrS->common_pts = (COMMONPTR *) Ysafe_malloc( sizeof(COMMONPTR) ) ; } else { aptrS->common_pts = (COMMONPTR *) Ysafe_realloc( aptrS->common_pts, pt * sizeof(COMMONPTR) ) ; } commonS = aptrS->common_pts[pt-1] = (COMMONPTR) Ysafe_calloc( 1, sizeof(COMMONBOX) ) ; commonS->common_set = NIL(INT) ; commonS->cap_match = NIL(INT) ; commonS->res_match = NIL(INT) ; commonS->num_pins = 0 ; } /* end common_pt */ static INT find_pin( cell, pin ) char *cell ; char *pin ; { PINBOXPTR nptr ; /* traverse pins on a net */ /* cell and pin must match */ for( nptr = netarrayG[anetS]->pins; nptr; nptr = nptr->next ){ if( strcmp( pin, nptr->pinname ) == STRINGEQ && strcmp( cell, cellarrayG[nptr->cell]->cname ) == STRINGEQ ){ return( nptr->pin ) ; } } sprintf( YmsgG, "Pin:%s on cell:%s could not be found in net:%s\n", pin, cell, netarrayG[anetS]->nname ) ; M( ERRMSG, "find_pin", YmsgG ) ; return( 0 ) ; } add2common( cell, pin ) char *cell ; char *pin ; { INT i ; /* counter for pins in common point */ INT pinnum ; /* index in netarray */ INT numpins ; /* number of pins in common point */ if(!(pinnum = find_pin( cell, pin ) )){ return ; } numpins = ++commonS->num_pins ; if( numpins == 1 ){ /* first time */ commonS->common_set = (INT *) Ysafe_malloc( sizeof(INT) ) ; } else { commonS->common_set = (INT *) Ysafe_realloc( commonS->common_set, numpins*sizeof(INT) ) ; /* now store the pin in the common pt */ /* check to see if pin is name more than once */ for( i = 0 ; i < numpins - 1 ; i++ ){ if( commonS->common_set[i] == pinnum ){ sprintf( YmsgG, "Pin:%s include twice in common pt\n", pin ) ; M( ERRMSG, "add2common", YmsgG ) ; return ; } } } commonS->common_set[numpins-1] = pinnum ; } /* add2common */ common_cap( cell, pin ) char *cell ; char *pin ; { INT i ; /* counter for pins in cap match */ INT pinnum ; /* index in termarray */ INT howmany ; /* number of pins in cap match */ if(!(pinnum = find_pin( cell, pin ) )){ return ; } if(!(commonS->cap_match)){ commonS->cap_match = (INT *) Ysafe_malloc( 2 * sizeof(INT) ) ; commonS->cap_match[HOWMANY] = howmany = 1 ; } else { howmany = ++commonS->cap_match[HOWMANY] ; commonS->cap_match = (INT *) Ysafe_realloc( commonS->cap_match, (howmany+1)*sizeof(INT) ) ; /* check to see if pin is name more than once */ for( i = 0 ; i < howmany - 1 ; i++ ){ if( commonS->cap_match[i] == pinnum ){ sprintf( YmsgG, "Pin:%s include twice in common pt cap. match\n", pin ) ; M( ERRMSG, "common_cap", YmsgG ) ; return ; } } } commonS->cap_match[howmany] = pinnum ; } /* end common_cap */ common_res( cell, pin ) char *cell ; char *pin ; { INT i ; /* counter for pins in res match */ INT pinnum ; /* index in termarray */ INT howmany ; /* number of pins in res match */ if(!(pinnum = find_pin( cell, pin ) )){ return ; } if(!(commonS->res_match)){ commonS->res_match = (INT *) Ysafe_malloc( 2 * sizeof(INT) ) ; commonS->res_match[HOWMANY] = howmany = 1 ; } else { howmany = ++commonS->res_match[HOWMANY] ; commonS->res_match = (INT *) Ysafe_realloc( commonS->res_match, (howmany+1)*sizeof(INT) ) ; /* check to see if pin is name more than once */ for( i = 0 ; i < howmany - 1 ; i++ ){ if( commonS->res_match[i] == pinnum ){ sprintf( YmsgG, "Pin:%s include twice in common pt res. match\n", pin ) ; M( ERRMSG, "common_res", YmsgG ) ; return ; } } } commonS->res_match[howmany] = pinnum ; } /* end common_res */ start_net_capmatch( netname ) char *netname ; { INT net ; /* index in netarray */ INT howmany ; /* howmany net cap. matches already */ INT *match ; /* current match array */ /* first make sure that data is good */ if(!(net = find_net( netname ) )){ return ; } howmany = (INT) net_cap_matchG[HOWMANY] ; net_cap_matchG[HOWMANY] = (INT *) ++howmany ; match = net_cap_matchG[++numcapmatchS] = (INT *) Ysafe_malloc( 2 * sizeof(INT) ) ; match[HOWMANY] = 1 ; match[1] = net ; } /* end start_net_capmatch */ add_net_capmatch( netname ) char *netname ; { INT net ; /* index in netarray */ INT howmany ; /* howmany net cap. matches already */ /* first make sure that data is good */ if(!(net = find_net( netname ) )){ return ; } howmany = ++net_cap_matchG[numcapmatchS][HOWMANY] ; net_cap_matchG[numcapmatchS] = (INT *) Ysafe_realloc( net_cap_matchG[numcapmatchS], (howmany+1) * sizeof(INT) ) ; net_cap_matchG[numcapmatchS][howmany] = net ; } /* end add_netcapmatch */ start_net_resmatch( netname ) char *netname ; { INT net ; /* index in netarray */ INT howmany ; /* howmany net res. matches already */ INT *match ; /* current match array */ /* first make sure that data is good */ if(!(net = find_net( netname ) )){ return ; } howmany = (INT) net_res_matchG[HOWMANY] ; net_res_matchG[HOWMANY] = (INT *) ++howmany ; match = net_res_matchG[++numresmatchS] = (INT *) Ysafe_malloc( 2 * sizeof(INT) ) ; match[HOWMANY] = 1 ; match[1] = net ; } /* end start_net_resmatch */ add_net_resmatch( netname ) char *netname ; { INT net ; /* index in netarray */ INT howmany ; /* howmany net res. matches already */ /* first make sure that data is good */ if(!(net = find_net( netname ) )){ return ; } howmany = ++net_res_matchG[numresmatchS][HOWMANY] ; net_res_matchG[numresmatchS] = (INT *) Ysafe_realloc( net_res_matchG[numresmatchS], (howmany+1) * sizeof(INT) ) ; net_res_matchG[numresmatchS][howmany] = net ; } /* end add_netresmatch */ graywolf-0.1.4+20170307gite1bf319/src/twmc/loadbins.c000066400000000000000000000210261305746555600214650ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: loadins.c DESCRIPTION:initializes bins for overlap calculation CONTENTS: loadbins( ) INT calc_cellareas( BOOL ) - returns total cell area. DATE: Feb 13, 1988 REVISIONS: Nov 3, 1988 - added routingFlag override for doPartitionG in calc_cell_areas and turned wire estimator off for cell partitioning case. May 11, 1989 - eliminated routing Flag override. Mon Feb 4 02:11:27 EST 1991 - added new wire estimator function. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) loadbins.c version 3.4 2/4/91" ; #endif #include #include static INT binAreaS ; /* conditional compile for bintest */ /* if defined the binpenalty should always remain equal to cell area */ /* #define BINTEST */ loadbins(wireAreaKnown) BOOL wireAreaKnown ; { CELLBOXPTR ptr ; BINBOXPTR bptr; INT cell ; INT x, y ; INT binX, binY, array_limit ; INT *cellList ; /* belows set up the initial bin-penalty */ /* bins are set up as follows */ /* 0 : border , 1..maxBinXG-1 : cells, maxBinXG : border */ /* bins for chip area are empty to start with */ for( x = 1 ; x < maxBinXG ; x++ ) { for( y = 1 ; y < maxBinYG ; y++ ) { bptr = binptrG[x][y] ; bptr->left = binXOffstG + x * binWidthXG ; bptr->right = bptr->left + binWidthXG ; bptr->bottom = binYOffstG + y * binWidthYG ; bptr->top = bptr->bottom + binWidthYG ; bptr->penalty = -binWidthXG * binWidthYG ; } } /* compensate for coreWidth != to number of bins * binWidth */ for( x = 1 ; x < maxBinXG ; x++ ) { bptr = binptrG[x][maxBinYG-1] ; bptr->penalty += binWidthXG * (bptr->top - 1 - blocktG) ; } for( y = 1 ; y < maxBinYG ; y++ ) { bptr = binptrG[maxBinXG-1][y] ; bptr->penalty += (bptr->right - 1 - blockrG) * binWidthYG ; } /* bins boarders of chip area are filled */ /* Bottom bins */ for( x = 0 ; x <= maxBinXG ; x++ ) { bptr = binptrG[x][0] ; bptr->left = binXOffstG + x * binWidthXG ; bptr->right = bptr->left + binWidthXG ; bptr->bottom = INT_MIN ; bptr->top = binYOffstG + binWidthYG ; bptr->penalty = 0 ; } /* Top bins */ for( x = 0 ; x <= maxBinXG ; x++ ) { bptr = binptrG[x][maxBinYG] ; bptr->left = binXOffstG + x * binWidthXG ; bptr->right = bptr->left + binWidthXG ; bptr->bottom = binYOffstG + maxBinYG * binWidthYG ; bptr->top = INT_MAX ; bptr->penalty = 0 ; } /* Left bins */ for( y = 0 ; y <= maxBinYG ; y++ ) { bptr = binptrG[0][y] ; bptr->left = INT_MIN ; bptr->right = binXOffstG + binWidthXG ; bptr->bottom = binYOffstG + y * binWidthYG ; bptr->top = bptr->bottom + binWidthYG ; bptr->penalty = 0 ; } /* Right bins */ for( y = 0 ; y <= maxBinYG ; y++ ) { bptr = binptrG[maxBinXG][y] ; bptr->left = binXOffstG + maxBinXG * binWidthXG ; bptr->right = INT_MAX ;; bptr->bottom = binYOffstG + y * binWidthYG ; bptr->top = bptr->bottom + binWidthYG ; bptr->penalty = 0 ; } /* fix four corners of bins */ binptrG[0][0]->bottom = INT_MIN ; binptrG[0][maxBinYG]->top = INT_MAX ; binptrG[maxBinXG][0]->bottom = INT_MIN ; binptrG[maxBinXG][maxBinYG]->top = INT_MAX ; /* now calculate the area of the current bins */ /* also reset number of cells in the bins to zero */ binAreaS = 0 ; for( x= 0 ; x <= maxBinXG; x++ ) { for( y = 0 ; y <= maxBinYG; y++ ) { bptr = binptrG[x][y] ; binAreaS += ABS( bptr->penalty ) ; bptr->cells[0] = 0 ; } } #ifdef BINTEST /* ----------------------------------------------------------------- This code test whether overlap code is performing correctly. Initialize all bins to full (0) and overlap penalty should be constant over all calls to overlap functions. */ for( x = 1 ; x <= maxBinXG ; x++ ) { for( y = 1 ; y <= maxBinYG ; y++ ) { bptr = binptrG[x][y] ; bptr->penalty = 0 ; } } #endif /* depending on state turn on wire estimation */ /* this toggles correct bin calculation function */ if( wireAreaKnown ){ turn_wireest_on(FALSE) ; } else { turn_wireest_on(TRUE) ; } #ifdef BINTEST turn_wireest_on(FALSE) ; #endif /* calculate initial overlap by adding cells to bins */ for( cell = 1 ; cell <= numcellsG; cell++ ) { ptr = cellarrayG[cell] ; setup_Bins( ptr, ptr->xcenter, ptr->ycenter, ptr->orient ) ; /* now safe to call add2bin */ /* use new_apos as the move record for initialization */ add2bin( new_aposG ) ; /* add cell to bincell list - only use center of cell */ binX = SETBINX(ptr->xcenter) ; binY = SETBINY(ptr->ycenter) ; bptr = binptrG[binX][binY] ; cellList = bptr->cells ; /* add cell to bin - check space */ array_limit = ++cellList[0] ; if( array_limit >= bptr->space ) { bptr->space += EXPCELLPERBIN ; cellList = bptr->cells = (INT *) Ysafe_realloc( bptr->cells, bptr->space * sizeof(INT) ) ; } cellList[array_limit] = cell ; } /* now calculate the current penalty with cells added */ binpenalG = 0 ; for( x= 0 ; x <= maxBinXG; x++ ) { for( y = 0 ; y <= maxBinYG; y++ ) { bptr = binptrG[x][y] ; binpenalG += ABS( bptr->penalty ) ; } } /* scale penalty */ penaltyG = (INT) ( lapFactorG * sqrt( (DOUBLE) binpenalG ) ) ; return ; } /* end loadbins */ /* ***************************************************************** CALCULATE CELL AREAS */ INT calc_cellareas( routingFlag ) BOOL routingFlag ; { INT totArea, orient, cell, l, r, b, t, xc, yc ; CELLBOXPTR cellptr ; TILEBOXPTR tileptr ; MOVEBOX pos_buf ; MOVEBOXPTR pos ; totArea = 0 ; pos = &pos_buf ; if( routingFlag == TRUE ){ for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = cellarrayG[cell] ; xc = cellptr->xcenter ; yc = cellptr->ycenter ; for( tileptr=cellptr->tiles;tileptr;tileptr=tileptr->next ){ /* need to calculate orientation */ pos->l = tileptr->left ; pos->r = tileptr->right ; pos->b = tileptr->bottom ; pos->t = tileptr->top ; pos->lw = tileptr->lweight ; pos->rw = tileptr->rweight ; pos->bw = tileptr->bweight ; pos->tw = tileptr->tweight ; Ytranslate( &(pos->l),&(pos->b),&(pos->r),&(pos->t), cellptr->orient) ; Ytranslatef( &(pos->lw),&(pos->bw),&(pos->rw),&(pos->tw), cellptr->orient) ; /* then add wire estimation dynamically */ if( new_wire_estG ){ wireestxy2( pos,xc,yc ) ; } else { wireestxy( pos,xc,yc ) ; } totArea += (pos->r - pos->l) * (pos->t - pos->b) ; } } } else { for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = cellarrayG[cell] ; for( tileptr=cellptr->tiles;tileptr;tileptr=tileptr->next ){ l = tileptr->left ; r = tileptr->right ; b = tileptr->bottom ; t = tileptr->top ; totArea += (r - l) * (t - b) ; } } } return( totArea ) ; } /* end calc_cellarea */ /* ***************************************************************** RETURN TOTAL BIN AREA. Note: could make totArea a global but use static to make code more modular. Only called a few times no problem with inefficiency. */ INT get_bin_area() { return( binAreaS ) ; } graywolf-0.1.4+20170307gite1bf319/src/twmc/main.c000066400000000000000000000510111305746555600206130ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * Copyright (C) 2014 Ruben Undheim * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: main.c DESCRIPTION:main routine DATE: Jan 29, 1988 REVISIONS: Sep 7, 1988 - fixed argument mismatch to utemp. Sep 24, 1988 - eliminated testloop.c Nov 25, 1988 - set coreError to 0 for partition case. Dec 3, 1988 - added timing driven calculation. Jan 15, 1989 - modifications for curve-fit controller. Also added lap.history file for debugging overlap. Jan 29, 1989 - changed msg to YmsgG and added \n's. Feb 23, 1989 - added X11 graphics to MC and pass arguments to writeResults which gathers info. Feb 25, 1989 - removed condition compile for MEMORYMAN. - changed iteration numbers to negative. Mar 02, 1989 - moved all negative feedback code to penalties.c Mar 07, 1989 - added compute_attprcel to calculate correct attempts per cell. Mar 11, 1989 - added graphics conditional compile. May 9, 1989 - added command line options. May 17, 1989 - modified graphics - partition code. May 24, 1989 - updated control. Deleted doPlacementG. Jun 21, 1989 - made verbose a global. Sep 25, 1989 - made movebox dynamic and hence needed to move it. Fixed unsigned randvar print statement. Added NOGRAPHICS conditional compile. Apr 23, 1990 - Modified timing constant determination and moved graph routines to the library. May 2, 1990 - Moved print_netinfo to cleanupReadcells in order for verify_pad_pins to work properly. May 4, 1990 - moved print_stats to library. Sun Dec 16 00:29:00 EST 1990 - now look at .net file if .mnet file doesn't exist. Thu Jan 17 00:47:43 PST 1991 - changed silent mode to to verbose mode to make consistent with other progs. Sun Jan 20 21:34:36 PST 1991 - ported to AIX. Thu Jan 24 17:12:04 PST 1991 - now when TWMC is called recursively .mout file will be correct. Fri Jan 25 18:07:09 PST 1991 - started on quickroute. Mon Feb 4 02:12:46 EST 1991 - working quickroute for non partition case. Thu Feb 7 00:17:32 EST 1991 - moved placement of .mest calculation. Thu Mar 7 01:47:38 EST 1991 - added Xdebug statement. Thu Mar 14 16:11:13 CST 1991 - avoid reading .net file during partitioning. Sat Apr 27 01:13:33 EDT 1991 - moved wirest code so now we can use readcells to tell whether we have a partitioning case. Also added initialize_aspect_ratios Wed May 1 19:20:03 EDT 1991 - renamed lap.history. Wed Jun 5 16:28:05 CDT 1991 - added condition for initializing aspect ratios. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) main.c version 3.27 11/23/91" ; #endif #include /* turn on condition compile for globals */ #define MAIN_DEFS #define CUSTOM_DEFS #include #include #include #include #define VERSION "v2.2" #define EXPECTEDMEMORY (1024 * 1024) #define NOREDUCTION -1000000.0 ; DOUBLE saveLapFactorG ; static BOOL parasiteS; /* whether window is a parasite */ static BOOL padsOnlyS; /* whether to place on pads */ static BOOL batchS; /* is TW in batch mode partition case */ static BOOL debugS ; /* whether to enable debug code */ static INT windowIdS ; /* the master window id if given */ static DOUBLE wire_red_ratioS = NOREDUCTION ; /* wire reduction */ /* Forward declarations */ VOID syntax(); INT closegraphics(); main( argc , argv ) INT argc ; char *argv[] ; { FILE *fp ; char filename[LRECL], arguments[LRECL], /* pointer to argument options */ *ptr, /* pointer to argument options */ *Ystrclone() ; INT yaleIntro(), attempts, arg_count ; /* argument counter */ INT rememberWire, /* variables for writing history of run */ rememberPenal, rememberRand ; BOOL get_arg_string( P1(char *arguments) ) ; DOUBLE calc_init_lapFactor() , calc_init_timeFactor() , calc_init_coreFactor() , analyze() , totFunc, totPen, avgdTime, avgdFunc ; /* ********************** start initialization *********************** */ #ifdef DEBUGX extern int _Xdebug ; _Xdebug = TRUE ; #endif /* start up cleanup handler */ YINITCLEANUP( argv[0], NULL, MAYBEDUMP ) ; Yinit_memsize( EXPECTEDMEMORY ) ; if( argc < 2 || argc > 5 ){ syntax() ; } else { debugS = FALSE ; verboseG = FALSE ; parasiteS = FALSE ; quickrouteG = FALSE ; windowIdS = 0 ; scale_dataG = 0 ; batchS = FALSE ; #ifndef NOGRAPHICS doGraphicsG = TRUE ; #else /* NOGRAPHICS case */ doGraphicsG = FALSE ; #endif /* NOGRAPHICS */ arg_count = 1 ; if( *argv[1] == '-' ){ for( ptr = ++argv[1]; *ptr; ptr++ ){ switch( *ptr ){ case 'b': batchS = TRUE ; doGraphicsG = FALSE ; break ; case 'd': debugS = TRUE ; break ; case 'n': doGraphicsG = FALSE ; break ; case 'o': /* overflow */ scale_dataG = atoi( argv[++arg_count] ) ; break ; case 'p': padsOnlyS = TRUE ; break ; case 'q': quickrouteG = TRUE ; break ; case 'v': verboseG = TRUE ; break ; case 'w': parasiteS = TRUE ; break ; default: sprintf( YmsgG,"Unknown option:%c\n", *ptr ) ; M(ERRMSG,"main",YmsgG); syntax() ; } } YdebugMemory( debugS ) ; /* handle I/O requests */ argv0G = Ystrclone( argv[0] ) ; cktNameG = Ystrclone( argv[++arg_count] ); sprintf( filename, "%s.mout" , cktNameG ) ; if( scale_dataG ){ fpoG = TWOPEN( filename, "a", ABORT ) ; } else { fpoG = TWOPEN( filename, "w", ABORT ) ; } Ymessage_init(fpoG) ; Ymessage_mode( verboseG ) ; YinitProgram( "TimberWolfMC", VERSION, yaleIntro ); /* now tell the user what he picked */ M(MSG,NULL,"\n\nTimberWolfMC switches:\n" ) ; if( debugS ){ YsetDebug( TRUE ) ; M(MSG,NULL,"\tdebug on\n" ) ; } if( verboseG ){ M(MSG,NULL,"\tMessages will be redirected to screen\n" ) ; } if( doGraphicsG ){ M(MSG,NULL,"\tGraphics mode on\n" ) ; } else { M(MSG,NULL,"\tGraphics mode off\n" ) ; } if( parasiteS ){ M(MSG,NULL,"\tTimberWolfMC will inherit window\n" ) ; /* look for windowid */ if((scale_dataG && argc != 5) || (!scale_dataG && argc != 4)){ M(ERRMSG,"main","Need to specify windowID\n" ) ; syntax() ; } else { windowIdS = atoi( argv[++arg_count] ) ; } } M(MSG,NULL,"\n" ) ; } else if( argc == 2 ){ /* order is important here */ YdebugMemory( FALSE ) ; cktNameG = Ystrclone( argv[1] ); argv0G = Ystrclone( argv[0] ) ; sprintf( filename, "%s.mout" , cktNameG ) ; fpoG = TWOPEN( filename, "w", ABORT ) ; Ymessage_init(fpoG) ; Ymessage_mode( verboseG ) ; YinitProgram( "TimberWolfMC", VERSION, yaleIntro ); } else { syntax() ; } } /* ********************** end initialization ************************* */ readpar() ; G( initMCGraphics( argc, argv, windowIdS ) ) ; while( TRUE ){ /* initialize annealing exp. table */ init_table() ; init_acceptance_rate() ; /* initialize heuristic annealing schedule */ if( randVarG == -1 ) { randVarG = Yrandom_seed() ; Yset_random_seed( randVarG ) ; } OUT2("\nThe rand generator seed was: %u\n\n\n", (unsigned) randVarG ); rememberRand = randVarG ; FLUSHOUT(); /* assume first that this is a mixed mode case - .mcel otherwise */ /* it is a macro cell only case so look for .cel */ sprintf(filename, "%s.mcel" , cktNameG ) ; if(!(fp = TWOPEN( filename , "r", NOABORT ))){ sprintf(filename, "%s.cel" , cktNameG ) ; fp = TWOPEN( filename , "r", ABORT ) ; } readcells( fp ) ; TWCLOSE(fp); /* now see if we need to perform a quickroute to get */ /* wiring estimate */ sprintf( filename, "%s.mest", cktNameG ) ; if( !(quickrouteG) && !(cost_onlyG) && !(scale_dataG) && !(doPartitionG)){ if(!(YfileExists( filename ))){ /* perform a quickroute if file doesn't exist */ quickrouteG = TRUE ; parasiteS = get_arg_string( arguments ) ; M( MSG, NULL, arguments ) ; M( MSG, NULL, "\n" ) ; Ysystem( "TimberWolfMC",ABORT,arguments,closegraphics ) ; if( parasiteS ){ /* if we save the graphics state we need to restore it */ G( TWrestoreState() ) ; } quickrouteG = FALSE ; } } /* check to see if .mest file was created */ new_wire_estG = FALSE ; if( fp = TWOPEN( filename, "r", NOABORT )){ if( read_wire_est( fp ) ){ new_wire_estG = TRUE ; } TWCLOSE( fp ) ; } /* make move box structure base on the largest number of tiles */ make_movebox() ; /* first check existence of .mnet file, for .net file */ sprintf(filename, "%s.mnet", cktNameG ) ; if(!(fp = TWOPEN( filename , "r", NOABORT ))){ if(!(doPartitionG)){ sprintf(filename, "%s.net", cktNameG ) ; fp = TWOPEN( filename , "r", NOABORT ) ; } } readnets( fp ) ; if( fp ) TWCLOSE( fp ) ; if( doPartitionG && numcellsG == numstdcellG ){ /* no macro cells to be placed - perform cost only from now on */ /* that is just place pads */ cost_onlyG = TRUE ; } /* call config1 to get initial configuration */ config1() ; /* see if we can open save file for writing */ sprintf(filename, "%s.msav", cktNameG ) ; fp = TWOPEN( filename , "w", ABORT ) ; TWCLOSE( fp ) ; /* initialize incremental bounding box data structures */ /* uses count found in prnt_netinfo */ init_unet() ; funccostG = findcost() ; initcheck() ; /* at this point we can initialize the aspect ratios */ if(!(cost_onlyG)){ initialize_aspect_ratios() ; } /* startup graphics */ if( doGraphicsG ){ G( set_graphic_context( PLACEMENT ) ) ; if( !wait_for_userG ){ G( draw_the_data() ) ; } else G( if( TWinterupt() ) ){ G( process_graphics() ) ; } } OUT2("\n\n\nTHE ROUTE COST OF THE CURRENT PLACEMENT: %d",funccostG ); OUT2("\nTHE PENALTY OF THE CURRENT PLACEMENT: %d\n", penaltyG ) ; FLUSHOUT(); if( wire_red_ratioS < -1000.0 ){ /* if wire_red_ratioS is greater that -1000 it was set in readpar */ /* this is only for debug purposes */ if( !(doPartitionG) && numcellsG > 1 ){ wire_red_ratioS = analyze() ; if( wireEstimateOnlyG ) { closegraphics() ; YexitPgm(OK); } } else { /* tmp */ wire_red_ratioS = 2.0 ; } } if( cost_onlyG && !restartG ){ /* done initialization */ break ; } Yplot_init( 0, "graph", "graph_par","graph_stp","graph_lap","graph_T", "graph_prob",NULL ) ; attmaxG = compute_attprcel() ; /* try a restart if requested */ sprintf(filename, "%s.mres", cktNameG ) ; fp = TWOPEN( filename , "r", NOABORT ) ; if( !( restartG && fp) ) { /* ****** NORMAL CASE - NO RESTART ********** */ if( restartG ){ ASSERT( restartG && !fp, "main","restart logic error\n" ) ; sprintf(YmsgG, "restart file:%s wasn't present but restart requested!\n", filename ) ; M(ERRMSG,"main",YmsgG ); M(MSG,NULL,"Must exit...\n\n" ); closegraphics() ; YexitPgm( PGMFAIL ) ; } else if (fp){ ASSERT( !restartG && fp, "main","restart logic error\n" ) ; sprintf(YmsgG, "<%s.mres> present but restart was not requested in par file.\n", cktNameG ) ; M(WARNMSG,"main",YmsgG ) ; } /*** initialization. JL ***/ init_control(TRUE); /*** set move generation controller. ***/ initStatCollection() ; /* init funccost penalty recorder */ OUT1("High temperature randomization and " ) ; OUT1("controller initialization...\n") ; iterationG = -2 ; TG = 1.0e30; /*** set to VERY HIGH temperature. ***/ attempts = (attmaxG > 3 * numcellsG) ? attmaxG : 3 * numcellsG ; /* call all controllers to set factors to initial points */ /* statistics should all be zero */ getStatistics( &totFunc, &totPen, &avgdTime, &avgdFunc ) ; coreFactorG = calc_init_coreFactor() ; lapFactorG = calc_init_lapFactor( totFunc, totPen ) ; timeFactorG = calc_init_timeFactor( avgdFunc, avgdTime ) ; uloop( attempts ) ; /* ----------------------------------------------------------- Call config2 to reconfigure core based on estimated routing area. Take border bins into account. ----------------------------------------------------------- */ config2( maxBinXG-1, maxBinYG-1, wire_red_ratioS ); /* since we now are configured scrap long nets */ scrapnet() ; funccostG = findcost() ; OUT1("\n\n\n"); OUT3("parameter adjust: route:%d penalty:%d\n", funccostG, penaltyG ) ; FLUSHOUT(); /* call controllers a second time to update factors */ /* set negative feedback controllers */ getStatistics( &totFunc, &totPen, &avgdTime, &avgdFunc ) ; lapFactorG = calc_init_lapFactor( totFunc, totPen ) ; timeFactorG = calc_init_timeFactor( avgdFunc, avgdTime ) ; funccostG = findcost() ; /* calc initial costs with factors */ attempts = attmaxG ; iterationG = -1 ; uloop( attempts ) ; /* Tell the user the expected outcome */ OUT2("\n\nThe average random wirelength is: %10.0f\n", avg_funcG ) ; OUT2("The expected optimum wirelength is: %10.0f\n\n", avg_funcG/wire_red_ratioS ) ; funccostG = findcost() ; OUT1("\n\n\nThe New Cost Values after readjustment:\n\n"); OUT3("route:%d penalty:%d\n\n\n", funccostG, penaltyG ) ; FLUSHOUT(); OUT1("Statistic collection...\n") ; attempts = attmaxG ; iterationG = 0 ; uloop( attempts ) ; G( draw_the_data() ) ; } else { /* ****** RESTART CASE ******* */ OUT2("reading data from %s\n", filename ) ; restartG = TW_oldinput( fp ) ; if( !(restartG) ){ M(ERRMSG,"main","Restart aborted because of error\n"); M(MSG,NULL, "Catastrophic error. Must exit...\n"); closegraphics() ; YexitPgm( PGMFAIL ) ; } funccostG = findcost() ; OUT2("\n\n\nTHE ROUTE COST OF THE CURRENT PLACEMENT: %d\n" , funccostG ) ; OUT2("\n\nTHE PENALTY OF THE CURRENT PLACEMENT: %d\n" , penaltyG ) ; FLUSHOUT() ; /* startup graphics */ G( set_graphic_context( PLACEMENT ) ) ; G( draw_the_data() ) ; } /* end RESTART CASE */ if( !cost_onlyG ) { OUT1("\n\nTimberWolf Cell Placement Ready for Action\n\n"); /* allow multi cell moves */ G( set_graphic_context( PLACEMENT ) ) ; utemp( attmaxG, TRUE ) ; } funccostG = findcost() ; rememberWire = funccostG ; rememberPenal = binpenalG ; finalout() ; finalcheck() ; twstats() ; break ; /* avoid a loop-loop only for restart failure */ } /* end doPlacement loop */ if( cost_onlyG && !restartG ){ finalout() ; twstats() ; } if( doGraphicsG ){ if( wait_for_userG && !doPartitionG ){ G( TWmessage( "TimberWolfMC waiting for your response" ) ) ; G( set_graphic_context( PLACEMENT ) ) ; G( process_graphics() ) ; } else { G( graphics_dump() ) ; } closegraphics() ; } OUT1("\n\n************************************ \n\n"); OUT1("TimberWolf has completed its mission\n"); OUT1("\n\n************************************ \n\n"); if( verboseG ){ Yprint_stats( stdout ) ; } Yprint_stats( fpoG ) ; Yplot_close() ; writeResults( rememberWire, rememberPenal, rememberRand ); if( sc_output() ){ create_sc_output() ; } Ymessage_close() ; YexitPgm(OK) ; } /* end main routine */ INT yaleIntro() { fprintf(fpoG,"\n%s\n",YmsgG) ; fprintf(fpoG,"Authors: Carl Sechen, Bill Swartz, Kai-Win Lee\n"); fprintf(fpoG," Dahe Chen, and Jimmy Lam\n"); fprintf(fpoG," Yale University\n"); fprintf(stdout,"\n%s\n",YmsgG) ; fprintf(stdout,"Authors: Carl Sechen, Bill Swartz, Kai-Win Lee\n"); fprintf(stdout," Dahe Chen, and Jimmy Lam\n"); fprintf(stdout," Yale University\n"); } /* end yaleIntro */ /* this routine takes information about run and write to history file */ /* to accumulate data about runs */ writeResults( wire, penal, rand ) INT wire, penal, rand ; { FILE *fpdebug ; INT left_side, right_side, bottom_side, top_side ; char filename[LRECL] ; funccostG = findcost() ; sprintf( filename,"%s.history", cktNameG ) ; fpdebug = TWOPEN( filename, "a", ABORT ) ; /* find core region */ find_core_boundary( &left_side, &right_side, &bottom_side, &top_side); bdxlengthG = right_side - left_side ; bdylengthG = top_side - bottom_side ; fprintf( fpdebug, "%4.2le\t%4.2le\t%4.2le\t%4.2le\t%d\t%d\t%d\t%4.2le\t%34.32le\n", (DOUBLE) wire, (DOUBLE) penal, (DOUBLE) funccostG, (DOUBLE) penaltyG, bdxlengthG, bdylengthG, rand, (DOUBLE) bdxlengthG * bdylengthG, wire_red_ratioS ) ; TWCLOSE( fpdebug ) ; } /* end writeResults */ /* close graphics window on fault */ INT closegraphics( ) { if( doGraphicsG ){ G( TWcloseGraphics() ) ; } } /* end closegraphics */ /* give user correct syntax */ VOID syntax() { M(ERRMSG,NULL,"\n" ) ; M(MSG,NULL,"Incorrect syntax. Correct syntax:\n"); sprintf( YmsgG, "\nTimberWolfMC [-dnpvw] designName [windowId] \n" ) ; M(MSG,NULL,YmsgG ) ; M(MSG,NULL,"\twhose options are zero or more of the following:\n"); M(MSG,NULL,"\t\td - prints debug info and performs extensive\n"); M(MSG,NULL,"\t\t error checking\n"); M(MSG,NULL,"\t\tn - no graphics - the default is to open the\n"); M(MSG,NULL,"\t\t display and output graphics to an Xwindow\n"); M(MSG,NULL,"\t\tp - place pads only - read core placement.\n"); M(MSG,NULL,"\t\tv - verbose mode - writes to screen\n"); M(MSG,NULL,"\t\tw - parasite mode - user must specify windowId\n"); YexitPgm(PGMFAIL); } /* end syntax */ /* used to TimberWolfMC recursively for the overflow case */ /* returns windowid if graphics are on and window is passed */ BOOL get_arg_string( arguments ) char *arguments ; { char temp[LRECL] ; /* used to build strings */ INT window ; /* current window ID */ sprintf( arguments, "%s -", argv0G ) ; if( scale_dataG ){ strcat( arguments, "o" ) ; } if( debugS ){ strcat( arguments, "d" ) ; } if( verboseG ){ strcat( arguments, "v" ) ; } if( quickrouteG ){ strcat( arguments, "q" ) ; } window = 0 ; if( doGraphicsG ){ /* save state of graphics and get window id */ G( window = TWsaveState() ) ; if( window ){ strcat( arguments, "w" ) ; } } else if( batchS ){ strcat( arguments, "b" ) ; } else { strcat( arguments, "n" ) ; } strcat( arguments, " " ) ; /* now build the values */ if( scale_dataG ){ sprintf( temp, "%d ", scale_dataG ) ; strcat( arguments, temp ) ; } /* now the design name */ strcat( arguments, cktNameG ) ; /* now pass graphics window if necessary */ if( window ){ sprintf( temp, " %d", window ) ; strcat( arguments, temp ) ; return(TRUE) ; } else { return(FALSE) ; } } /* end function get_arg_string() */ BOOL get_batch_mode() { return( batchS ) ; } /* end get_batch_mode */ set_wiring_reduction( reduction ) DOUBLE reduction ; { wire_red_ratioS = reduction ; } /* set_wiring_reduction */ graywolf-0.1.4+20170307gite1bf319/src/twmc/main.h000066400000000000000000000104521305746555600206240ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: main.h CONTENTS: definitions for globals structures and variables DATE: Jan 29, 1988 REVISIONS: Aug 7, 1988 - added control flags for pads. Oct 25, 1988 - added flags for neighborhood and groups Oct 27, 1988 - changed RAND to acm minimal standard generator Feb 13, 1989 - added graphics definitions. Feb 25, 1989 - removed redundant macro definitions and added inclusion of yalecad/base.h Feb 26, 1989 - added G suffix to all global variables. Mar 01, 1989 - added wait_for_user global and added compile switch for program exit status. Mar 07, 1989 - added instance type for cells. Mar 11, 1989 - added graphics conditional compile. Apr 1, 1989 - deleted instance type now store with master cell. May 18, 1989 - reorganized globals. May 24, 1989 - removed doPlacementG May 25, 1989 - added graphFilesG Boolean. Jun 21, 1989 - added verboseG global. Sep 27, 1989 - deleted MAXTILES now dynamic. Oct 3, 1989 - added scale_inputG for large designs. Oct 20, 1989 - removed pitch and added track_spacingXG and track_spacingYG ; Fri Jan 25 18:07:47 PST 1991 - added quickroute variable and deleted extraneous variables. Mon Feb 4 02:13:39 EST 1991 - added new_wire_estG global variable. Sat Feb 23 00:22:35 EST 1991 - added defines for TOMUS. Wed May 1 16:42:30 EDT 1991 - removed defines for TOMUS. ----------------------------------------------------------------- */ /* ***************************************************************** static char SccsId[] = "@(#) main.h version 3.7 5/1/91" ; ***************************************************************** */ #ifndef MAIN_H #define MAIN_H #include #include #ifndef MATH_H #define MATH_H #include #endif /* MATH_H */ #ifdef ultrix #undef UNIX #include #define UNIX ultrix #else #endif /* ultrix */ /* program exit status is different in VMS */ #ifdef VMS #define OK 1 #define FAIL 0 #else /* not VMS */ #define OK 0 #define FAIL 1 #endif /* VMS */ /* if not using makefile and debug is wanted add it here */ /* #define DEBUG */ /* remove graphics lines of code if compile switch is on */ #ifdef NOGRAPHICS #define G(x_xz) #else #define G(x_xz) x_xz #endif /* NOGRAPHICS */ /* ***********LEAVE THE BELOW UNCHANGED *************************** */ #include /* BASIC MACRO DEFINITIONS */ #define MAXSITES 50 /* cell types */ typedef INT CELLTYPE ; #define CUSTOMCELLTYPE 1 #define PADCELLTYPE 2 #define SOFTCELLTYPE 3 #define PADGROUPTYPE 4 #define SUPERCELLTYPE 5 /* cell which inherits all prop. of children */ #define MERGEDCELLTYPE 6 /* child of a super cell */ #define GROUPCELLTYPE 7 /* a cell group moves together with the group */ #define PADMACROTYPE 8 /* all pads on a side form pad bbox for changen*/ #define STDCELLTYPE 9 /* cells created by partitioner */ /* fixed type flags */ #define POINTFLAG 0 /* cell fixed at a point */ #define NEIGHBORHOODFLAG 1 /* cell fixed in a neighborhood */ #define GROUPFLAG 2 /* group flag free to move */ #define FIXEDGROUPFLAG 3 /* group fixed at a point */ /* constants for graphic routines */ #define PLACEMENT 1 #define PARTITION_PLACEMENT 2 #define VIOLATION_REMOVAL 3 #define COMPACTION 4 #define CHANNEL_GENERATION 5 /* I/O MACRO DEFINITIONS */ #include /* compile switch for globals */ #ifndef MAIN_DEFS #define EXTERN extern #else #define EXTERN #endif EXTERN char *cktNameG ; EXTERN char *argv0G ; /* the pathname of the program */ EXTERN INT attpercellG ; EXTERN INT scale_dataG ; /* reduce the scale of the input data */ EXTERN INT track_spacingXG ; EXTERN INT track_spacingYG ; EXTERN INT defaultTracksG ; /* booleans for control of program */ EXTERN BOOL cost_onlyG ; EXTERN BOOL doChannelGraphG ; EXTERN BOOL doGlobalRouteG ; EXTERN BOOL doCompactionG ; EXTERN BOOL doPartitionG ; EXTERN BOOL doGraphicsG ; EXTERN BOOL quickrouteG ; EXTERN BOOL new_wire_estG ; /* use new wire estimation alg. */ EXTERN BOOL restartG ; EXTERN BOOL wireEstimateOnlyG ; EXTERN BOOL wait_for_userG ; EXTERN BOOL verboseG ; #undef EXTERN #endif /* MAIN_H */ graywolf-0.1.4+20170307gite1bf319/src/twmc/makebins.c000066400000000000000000000062571305746555600214740ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: makebins.c DESCRIPTION:determines number of bins for overlap calculation CONTENTS: makebins( INT ) DATE: Feb 13, 1988 REVISIONS: Feb 27, 1988 - now called from config1 and calculates numbins based on cell area. In future, use variance. Mar 1, 1988 - added variance. Nov 20, 1988 - fixed aspect ratio. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) makebins.c version 3.3 9/5/90" ; #endif #include #include makebins( numbins ) INT numbins ; { BINBOXPTR bptr ; DOUBLE xbins, ybins ; INT i, j ; ybins = sqrt( chipaspectG * (DOUBLE) numbins ) ; ybins = ceil( ybins ) ; xbins = sqrt( (DOUBLE) numbins / chipaspectG ) ; xbins = ceil( xbins ) ; maxBinXG = (INT) xbins ; maxBinYG = (INT) ybins ; /* take bins for border around chip into account */ /* bins will be labeled [0..maxBinsXG] for a total of maxBinsXG+1 bins */ maxBinXG++ ; maxBinYG++ ; OUT2("maxBinXG automatically set to:%d\n", maxBinXG ); OUT2("maxBinYG automatically set to:%d\n", maxBinYG ); binptrG = (BINBOXPTR **)Ysafe_malloc( (1+maxBinXG)*sizeof(BINBOXPTR *)) ; for( i = 0 ; i <= maxBinXG ; i++ ) { binptrG[i]=(BINBOXPTR*) Ysafe_malloc((1+maxBinYG)*sizeof(BINBOXPTR)); for( j = 0 ; j <= maxBinYG ; j++ ) { bptr = binptrG[i][j] = (BINBOXPTR) Ysafe_malloc( sizeof(BINBOX)); bptr->cells = (INT *) Ysafe_malloc( (EXPCELLPERBIN+1) * sizeof(INT)); /* zero position holds current number cells in bin */ bptr->cells[0] = 0 ; /* space holds current size of array */ bptr->space = EXPCELLPERBIN + 1 ; } } } /* end function make bins */ graywolf-0.1.4+20170307gite1bf319/src/twmc/makesite.c000066400000000000000000000151401305746555600214740ustar00rootroot00000000000000/* * Copyright (C) 1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char SccsId[] = "@(#) makesite.c version 3.3 9/5/90" ; #endif #include #include DOUBLE val1 , val2 ; Vside( kArray, cellptr , x , yy1 , yy2 , flag ) KBOXPTR kArray ; CELLBOXPTR cellptr ; INT x , yy1 , yy2 , flag ; { DOUBLE aspFactor , aspect , aspLB ; INT worstLen , pPinLocs , k , length , base ; INT TotSites ; DOUBLE siteSpace ; length = ABS(yy2 - yy1) ; aspect = cellptr->aspect ; aspLB = cellptr->aspLB ; if( aspLB + 0.01 > cellptr->aspUB ) { aspFactor = 1.0 ; } else { aspFactor = sqrt( aspLB / aspect ) ; } worstLen = (INT) (aspFactor * (DOUBLE) length) ; if( (DOUBLE)(worstLen + 1) / aspFactor - (DOUBLE) length < (DOUBLE) length - (DOUBLE) worstLen / aspFactor ) { worstLen++ ; } pPinLocs = worstLen / track_spacingYG - 1 ; if( flag ) { if( pPinLocs > MAXSITES ) { for( k = 1 ; k <= MAXSITES ; k++ ) { kArray[ k ].cap = 0 ; kArray[ k ].HV = 0 ; kArray[ k ].sp = 0 ; kArray[ k ].x = 0 ; kArray[ k ].y = 0 ; } base = pPinLocs / MAXSITES ; for( k = 1 ; k <= MAXSITES ; k++ ) { kArray[ k ].cap += base ; } for( k = 1 ; k <= pPinLocs % MAXSITES ; k++ ) { kArray[ k ].cap++ ; } } else { /* prepare pPinLocs sites */ for( k = 1 ; k <= pPinLocs ; k++ ) { kArray[ k ].cap = 0 ; kArray[ k ].HV = 0 ; kArray[ k ].sp = 0 ; kArray[ k ].x = 0 ; kArray[ k ].y = 0 ; } for( k = 1 ; k <= pPinLocs ; k++ ) { kArray[ k ].cap = 1 ; } } } /* TotSites = minimum of ( MAXSITES and pPinLocs ) */ if( pPinLocs <= MAXSITES ) { TotSites = pPinLocs ; } else { TotSites = MAXSITES ; } siteSpace = (DOUBLE) length / (DOUBLE) (TotSites + 1) ; /* Suppose we encountered coordinates yy1 and yy2 for a given vertical side, and of course that the x-coordinate is simply x. ( yy1 < yy2 is required ) */ if( flag ) { if( yy2 > yy1 ) { for( k = 1 ; k <= TotSites ; k++ ) { kArray[ k ].x = x ; val1 = (k + 1) * siteSpace ; val2 = k * siteSpace ; kArray[ k ].y = ROUND( val2 ) + yy1 ; kArray[ k ].sp = ROUND( val1 ) - ROUND( val2 ) ; kArray[ k ].HV = 1 ; } } else { for( k = 1 ; k <= TotSites ; k++ ) { kArray[ k ].x = x ; val1 = (k + 1) * siteSpace ; val2 = k * siteSpace ; kArray[ k ].y = yy1 - ROUND( val2 ) ; kArray[ k ].sp = ROUND( val1 ) - ROUND( val2 ) ; kArray[ k ].HV = 1 ; } } } /* * * --- BIG NOTE --- * * Any fixed terminals intersecting a site cause the contents * of that site to be incremented by one. This will inhibit * sequences from passing on thru. ( try to remember to * get the check pointer to reflect this fact ) */ return( TotSites ) ; } Hside( kArray, cellptr , xx1 , xx2 , y , flag ) KBOXPTR kArray ; CELLBOXPTR cellptr ; INT xx1 , xx2 , y , flag ; { DOUBLE aspFactor , aspect , aspUB ; INT worstLen , pPinLocs , k , length , base ; INT TotSites ; DOUBLE siteSpace ; length = ABS(xx2 - xx1) ; aspect = cellptr->aspect ; aspUB = cellptr->aspUB ; if( cellptr->aspLB + 0.01 > aspUB ) { aspFactor = 1.0 ; } else { aspFactor = sqrt( aspect / aspUB ) ; } worstLen = (INT) (aspFactor * (DOUBLE) length) ; if( (DOUBLE)(worstLen + 1) / aspFactor - (DOUBLE) length < (DOUBLE) length - (DOUBLE) worstLen / aspFactor ) { worstLen++ ; } pPinLocs = worstLen / track_spacingXG - 1 ; if( flag ) { if( pPinLocs > MAXSITES ) { for( k = 1 ; k <= MAXSITES ; k++ ) { kArray[ k ].cap = 0 ; kArray[ k ].HV = 0 ; kArray[ k ].sp = 0 ; kArray[ k ].x = 0 ; kArray[ k ].y = 0 ; } base = pPinLocs / MAXSITES ; for( k = 1 ; k <= MAXSITES ; k++ ) { kArray[ k ].cap += base ; } for( k = 1 ; k <= pPinLocs % MAXSITES ; k++ ) { kArray[ k ].cap++ ; } } else { /* prepare pPinLocs sites */ for( k = 1 ; k <= pPinLocs ; k++ ) { kArray[ k ].cap = 0 ; kArray[ k ].HV = 0 ; kArray[ k ].sp = 0 ; kArray[ k ].x = 0 ; kArray[ k ].y = 0 ; } for( k = 1 ; k <= pPinLocs ; k++ ) { kArray[ k ].cap = 1 ; } } } /* TotSites = minimum of ( MAXSITES and pPinLocs ) */ if( pPinLocs <= MAXSITES ) { TotSites = pPinLocs ; } else { TotSites = MAXSITES ; } siteSpace = (DOUBLE) length / (DOUBLE) (TotSites + 1) ; /* Suppose we encountered coordinates xx1 and xx2 for a given horizontal side, and of course that the y-coordinate is simply y. */ if( flag ) { if( xx2 > xx1 ) { for( k = 1 ; k <= TotSites ; k++ ) { kArray[ k ].y = y ; val1 = (k + 1) * siteSpace ; val2 = k * siteSpace ; kArray[ k ].x = ROUND( val2 ) + xx1 ; kArray[ k ].sp = ROUND( val1 ) - ROUND( val2 ) ; kArray[ k ].HV = 0 ; } } else { for( k = 1 ; k <= TotSites ; k++ ) { kArray[ k ].y = y ; val1 = (k + 1) * siteSpace ; val2 = k * siteSpace ; kArray[ k ].x = xx1 - ROUND( val2 ) ; kArray[ k ].sp = ROUND( val1 ) - ROUND( val2 ) ; kArray[ k ].HV = 0 ; } } } /* * * --- BIG NOTE --- * * Any fixed terminals intersecting a site cause the contents * of that site to be incremented by one. This will inhibit * sequences from passing on thru. ( try to remember to * get the check pointer to reflect this fact ) */ return( TotSites ) ; } graywolf-0.1.4+20170307gite1bf319/src/twmc/mc.dialog000066400000000000000000000050171305746555600213100ustar00rootroot00000000000000numfields;52 # Here is how you make a dialog box. # field;fieldnumber;xpos;ypos;init string;field length; # (continued) field type;color;case toggle # Field types are # accept - mandatory # reject - mandatory # label - write only field. # input - read write field # case - a set of case field to follow # the first field in the list is the initial case. # clabel - one of the case fields. # field number must start with 0 field;0;5;1; ACCEPT ;8;accept;red field;1;25;1; CANCEL ;8;reject;black field;2;15;2;Edit Cell;9;label;red field;3;5;3;Name;13;label;blue field;4;5;4;Number;12;label;blue field;5;5;5;Xcenter:;8;label;blue field;6;14;5;10;8;input;blue field;7;5;6;Ycenter:;8;label;blue field;8;14;6;10;8;input;blue field;9;5;7;Orient:;7;case;blue;10,11,12,13,14,15,16,17 field;10;14;7;0 ;2;clabel;blue field;11;16;7;1 ;2;clabel;blue field;12;18;7;2 ;2;clabel;blue field;13;20;7;3 ;2;clabel;blue field;14;22;7;4 ;2;clabel;blue field;15;24;7;5 ;2;clabel;blue field;16;26;7;6 ;2;clabel;blue field;17;28;7;7 ;2;clabel;blue field;18;5;9;Valid orientations;19;label;blue # orientation 0 field;19;7;10;0;1;case;blue;20,21 field;20;14;10;valid;5;clabel;green field;21;25;10;invalid;7;clabel;red # orientation 1 field;22;7;11;1;1;case;blue;23,24 field;23;14;11;valid;5;clabel;green field;24;25;11;invalid;7;clabel;red # orientation 2 field;25;7;12;2;1;case;blue;26,27 field;26;14;12;valid;5;clabel;green field;27;25;12;invalid;7;clabel;red # orientation 3 field;28;7;13;3;1;case;blue;29,30 field;29;14;13;valid;5;clabel;green field;30;25;13;invalid;7;clabel;red # orientation 4 field;31;7;14;4;1;case;blue;32,33 field;32;14;14;valid;5;clabel;green field;33;25;14;invalid;7;clabel;red # orientation 5 field;34;7;15;5;1;case;blue;35,36 field;35;14;15;valid;5;clabel;green field;36;25;15;invalid;7;clabel;red # orientation 6 field;37;7;16;6;1;case;blue;38,39 field;38;14;16;valid;5;clabel;green field;39;25;16;invalid;7;clabel;red # orientation 7 field;40;7;17;7;1;case;blue;41,42 field;41;14;17;valid;5;clabel;green field;42;25;17;invalid;7;clabel;red # fix field field;43;5;19;Fixed;5;case;blue;44,45 field;44;14;19;on ;3;clabel;green field;45;25;19;off;3;clabel;red # field;46;1;21;To change case fields put pointer;35;label;blue field;47;1;22;in window and click. To change;35;label;blue field;48;1;23;input fields put pointer in window;35;label;blue field;49;1;24;and back up over current contents;35;label;blue field;50;1;25;using the delete key. After modifying;35;label;blue field;51;1;26;the field, hit the return key.;35;label;blue graywolf-0.1.4+20170307gite1bf319/src/twmc/mc_menu000066400000000000000000000027371305746555600211040ustar00rootroot00000000000000# TimberWolfMC menu file. # "@(#) mc_menu (Yale) version 3.9 4/27/91" # # Comments start with a sharp # MENU is a keyword must be capitalized. # Everything in this file is case sensitive. # Fields are separated by commas. # Format: # MENU,menuName - followed by list of entries for this menu # - one on each line. # Normal menu entry - MenuEntry,FunctionNumber # Boolean menu entry - # TrueMenuEntry,FunctionNumber1,FalseMenuEntry,FunctionNumber2,Init # where Init is the initial state and is 1 for True and 0 for False. # # Menu are placed on the screen in a left to right order according # to the order in this file. # MENU,CONTROL Auto Redraw On,1,Auto Redraw Off,2,1 Close Graphics,3 Colors,4 Continue Program,5 Dump Graphics,6 FullView,8 Graphics Update On,9,Graphics Update Off,10,1 Redraw,11 Tell Point,12 Translate,13 Zoom,14 Cancel,0 MENU,EDIT Cell Neighborhood,15 Edit Cell,16 Fix Cell,17 Fix Cell but Rot,18 Group Cells,19 Move Cell,20 Cancel,0 MENU,DRAW Draw Bins,21,Ignore Bins,22,0 Draw Border,23,Draw Tiles,24,1 Draw Globe Areas,37,Ignore Globe Areas,38,1 Draw Labels,25,Ignore Labels,26,0 Draw Neighborhd,27,Ignore Neighborhood,28,1 Draw Nets,29,Ignore Nets,30,0 Draw Orient,44,Ignore Orient,45,0 Draw Pins,31,Ignore Pins,32,0 Draw Single Cell Moves,42,Ignore Single Cell,43,0 Draw Single Net,33 Draw Wiring Est,34,Ignore Wiring Est,35,0 Cancel,0 MENU,PARAMETERS Change Aspect Ratio,36 Graphics Wait,40,No Graphics Wait,41,0 Cancel,0 graywolf-0.1.4+20170307gite1bf319/src/twmc/menus.h000066400000000000000000000050731305746555600210320ustar00rootroot00000000000000 /* TWmenu definitions */ #define TWNUMMENUS 38 #define AUTO_REDRAW_ON 1 #define AUTO_REDRAW_OFF 2 #define CLOSE_GRAPHICS 3 #define COLORS 4 #define CONTINUE_PROGRAM 5 #define DUMP_GRAPHICS 6 #define FULLVIEW 8 #define GRAPHICS_UPDATE_ON 9 #define GRAPHICS_UPDATE_OFF 10 #define REDRAW 11 #define TELL_POINT 12 #define TRANSLATE 13 #define ZOOM 14 #define CANCEL 0 #define CELL_NEIGHBORHOOD 15 #define EDIT_CELL 16 #define FIX_CELL 17 #define FIX_CELL_BUT_ROT 18 #define GROUP_CELLS 19 #define MOVE_CELL 20 #define CANCEL 0 #define DRAW_BINS 21 #define IGNORE_BINS 22 #define DRAW_BORDER 23 #define DRAW_TILES 24 #define DRAW_GLOBE_AREAS 37 #define IGNORE_GLOBE_AREAS 38 #define DRAW_LABELS 25 #define IGNORE_LABELS 26 #define DRAW_NEIGHBORHD 27 #define IGNORE_NEIGHBORHOOD 28 #define DRAW_NETS 29 #define IGNORE_NETS 30 #define DRAW_ORIENT 44 #define IGNORE_ORIENT 45 #define DRAW_PINS 31 #define IGNORE_PINS 32 #define DRAW_SINGLE_CELL_MOVES 42 #define IGNORE_SINGLE_CELL 43 #define DRAW_SINGLE_NET 33 #define DRAW_WIRING_EST 34 #define IGNORE_WIRING_EST 35 #define CANCEL 0 #define CHANGE_ASPECT_RATIO 36 #define GRAPHICS_WAIT 40 #define NO_GRAPHICS_WAIT 41 #define CANCEL 0 static TWMENUBOX menuS[39] = { "CONTROL",0,0,1,0,0, "Auto Redraw On","Auto Redraw Off",1,0,1,2, "Close Graphics",0,0,0,3,0, "Colors",0,0,0,4,0, "Continue Program",0,0,0,5,0, "Dump Graphics",0,0,0,6,0, "FullView",0,0,0,8,0, "Graphics Update On","Graphics Update Off",1,0,9,10, "Redraw",0,0,0,11,0, "Tell Point",0,0,0,12,0, "Translate",0,0,0,13,0, "Zoom",0,0,0,14,0, "Cancel",0,0,0,0,0, "EDIT",0,0,1,0,0, "Cell Neighborhood",0,0,0,15,0, "Edit Cell",0,0,0,16,0, "Fix Cell",0,0,0,17,0, "Fix Cell but Rot",0,0,0,18,0, "Group Cells",0,0,0,19,0, "Move Cell",0,0,0,20,0, "Cancel",0,0,0,0,0, "DRAW ",0,0,1,0,0, "Draw Bins","Ignore Bins",0,0,21,22, "Draw Border","Draw Tiles",1,0,23,24, "Draw Globe Areas","Ignore Globe Areas",1,0,37,38, "Draw Labels","Ignore Labels",0,0,25,26, "Draw Neighborhd","Ignore Neighborhood",1,0,27,28, "Draw Nets","Ignore Nets",0,0,29,30, "Draw Orient","Ignore Orient",0,0,44,45, "Draw Pins","Ignore Pins",0,0,31,32, "Draw Single Cell Moves","Ignore Single Cell",0,0,42,43, "Draw Single Net",0,0,0,33,0, "Draw Wiring Est","Ignore Wiring Est",0,0,34,35, "Cancel",0,0,0,0,0, "PARAMETERS ",0,0,1,0,0, "Change Aspect Ratio",0,0,0,36,0, "Graphics Wait","No Graphics Wait",0,0,40,41, "Cancel",0,0,0,0,0, 0,0,0,0,0,0 } ; graywolf-0.1.4+20170307gite1bf319/src/twmc/mergecell.c000066400000000000000000000167071305746555600216430ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: mergecell.c DESCRIPTION:This file contains the utility routines to merge two custom cells or pads into one cell. CONTENTS: DATE: Aug 17, 1988 REVISIONS: Jan 29, 1989 - changed msg to YmsgG and added \n's. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) mergecell.c version 3.3 9/5/90" ; #endif #include #include /* ###################### STATIC definitions ############################# */ /* ################## END STATIC definitions ############################# */ /* mergeCells takes the contents of child and parent and merges them together */ /* to form a new parent */ mergeCells( cptr, pptr ) CELLBOXPTR cptr ; /* pointer to child cell box */ CELLBOXPTR pptr ; /* pointer to parent cell box */ { #ifdef LATER BOUNBOXPTR cbounptr, pbounptr ; PINBOXPTR cterm, pterm, saveterm ; INT pl, pr, pb, pt ; INT cl, cr, cb, ct ; INT xcenter, ycenter ; /* --------------------- perform error checking ------------------- */ if( cptr->softflag ){ sprintf(YmsgG,"softcells can't be merged-cell:%s\n", cptr->cname ) ; M( ERRMSG,"mergeCells",YmsgG ) ; return ; } if( pptr->softflag ){ sprintf(YmsgG,"softcells can't be merged-cell:%s\n", pptr->cname ) ; M( ERRMSG,"mergeCells",YmsgG ) ; return ; } /* make sure cell types match */ if( pptr->celltype == PADCELLTYPE || pptr->celltype == PADGROUPTYPE ){ if( cptr->celltype == SUPERCELLTYPE || cptr->celltype == CUSTOMCELLTYPE ){ sprintf(YmsgG,"pads and custom cells can't be merged-pad:%s cell:%s\n", pptr->cname, cptr->cname ) ; M( ERRMSG,"mergeCells",YmsgG ) ; return ; } } else if( pptr->celltype == CUSTOMCELLTYPE ){ if( cptr->celltype == PADCELLTYPE || cptr->celltype == PADGROUPTYPE ){ sprintf(YmsgG,"pads and custom cells can't be merged-pad:%s cell:%s\n", cptr->cname, pptr->cname ) ; M( ERRMSG,"mergeCells",YmsgG ) ; return ; } } if(!( cptr->tiles) ){ sprintf(YmsgG,"No tile data is present for cell:%s. Aborting merge.\n", cptr->cname ) ; M( ERRMSG,"mergeCells",YmsgG ) ; return ; } if(!( cptr->bounBox) ){ sprintf(YmsgG,"No bounding box data is present for cell:%s. Aborting merge.\n", cptr->cname ) ; M( ERRMSG,"mergeCells",YmsgG ) ; return ; } /* ------------------end perform error checking ------------------- */ /* now begin merge */ pptr->numsides += cptr->numsides ; /* first merge bounding boxes of two cells */ if( pptr->bounBox ){ /* parents data has already been created */ /* avoid memory allocation */ cbounptr=cptr->bounBox[cptr->orient] ; pbounptr=pptr->bounBox[pptr->orient] ; /* get global positions of both cells */ pl = pptr->xcenter + pbounptr->l ; pr = pptr->xcenter + pbounptr->r ; pb = pptr->ycenter + pbounptr->t ; pt = pptr->ycenter + pbounptr->t ; cl = cptr->xcenter + cbounptr->l ; cr = cptr->xcenter + cbounptr->r ; cb = cptr->ycenter + cbounptr->t ; ct = cptr->ycenter + cbounptr->t ; /* determine new x and y center */ pl = MIN( pl, cl ) ; pr = MAX( pr, cr ) ; pb = MIN( pb, cb ) ; pt = MAX( pr, ct ) ; pptr->xcenter = xcenter = ( pl + pr ) / 2 ; pptr->ycenter = ycenter = ( pb + pt ) / 2 ; /* now save new bounding box cell relative */ pbounptr->l = pl - xcenter ; pbounptr->r = pr - xcenter ; pbounptr->b = pb - ycenter ; pbounptr->t = pt - ycenter ; } else { /* parent bounding box has not been allocated */ cbounptr=cptr->bounBox[cptr->orient] ; pptr->bounBox = (BOUNBOXPTR *) Ysafe_malloc( sizeof( BOUNBOXPTR ) ) ; pbounptr = pptr->bounBox[0] = (BOUNBOXPTR) Ysafe_malloc( sizeof( BOUNBOX ) ) ; pbounptr->l = cbounptr->l ; pbounptr->r = cbounptr->r ; pbounptr->b = cbounptr->b ; pbounptr->t = cbounptr->t ; pptr->xcenter = cptr->xcenter ; pptr->ycenter = cptr->ycenter ; } /* end bounding box merge */ /* now merge pins */ for( cterm=cptr->pinptr;cterm;cterm=cterm->nextterm ){ if( saveterm = pptr->pinptr ) { pterm = pptr->pinptr = (TERMBOXPTR) Ysafe_malloc( sizeof( TERMBOX ) ) ; pterm->nextterm = saveterm ; } else { pterm = pptr->termptr = (TERMBOXPTR) Ysafe_malloc( sizeof( TERMBOX ) ) ; pterm->nextterm = NULL ; } pterm->terminal = cterm->terminal ; pterm->xpos = pterm->orig_xpos = cterm->xpos + cptr->xcenter - xcenter ; pterm->ypos = pterm->orig_ypos = cterm->ypos + cptr->ycenter - ycenter; } /* end terminal loop */ pptr->numterms += cptr->numterms ; /* merge the tiles by making copy of the new tiles */ /* this won't work I need to find the minimum containing figure */ /* of the set of tile. Note I need to add xcenter ycenter to get */ /* global position, find all the corners, use buster to break into */ /* tiles and then call weight routines */ for( ctileptr=cptr->config[0];ctileptr;ctileptr=ctileptr->next ){ if( savetile = pptr->config[0] ){ pptr->config[0] = tile = (TILEBOXPTR) Ysafe_malloc( sizeof( TILEBOX ) ) ; tile->next = savetile ; } else { /* first addition to supercell */ pptr->config[0] = tile = (TILEBOXPTR) Ysafe_malloc( sizeof( TILEBOX ) ) ; tile->next = NULL ; } /* copy contents of tile */ tile->lweight = ctileptr->lweight ; tile->rweight = ctileptr->rweight ; tile->bweight = ctileptr->bweight ; tile->tweight = ctileptr->tweight ; tile->lborder = ctileptr->lborder ; tile->rborder = ctileptr->rborder ; tile->bborder = ctileptr->bborder ; tile->tborder = ctileptr->tborder ; tile->left = ctileptr->left ; tile->right = ctileptr->right ; tile->bottom = ctileptr->bottom ; tile->top = ctileptr->top ; tile->orig_left = ctileptr->orig_left ; tile->orig_right = ctileptr->orig_right ; tile->orig_bottom = ctileptr->orig_bottom ; tile->orig_top = ctileptr->orig_top ; } #endif } /* end mergecells */ /* ***************************************************************** */ graywolf-0.1.4+20170307gite1bf319/src/twmc/neworient.c000066400000000000000000000104321305746555600217030ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: neworient.c DESCRIPTION:pick a new orientation. DATE: Jan 29, 1988 REVISIONS: Thu Apr 18 01:37:39 EDT 1991 - added check_valid_orientation. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) neworient.c version 3.4 4/18/91" ; #endif #include #include newOrient( cellptr , range ) CELLBOXPTR cellptr ; INT range ; { INT incidence , count , i , orient ; orient = cellptr->orient ; if( range == 4 ) { if( orient >= 4 ) { count = 0 ; for( i = 0 ; i <= 3 ; i++ ) { if( cellptr->orientList[i] == 1 ) { count++ ; } } if( count == 0 ) { return( -1 ) ; } do { incidence = (INT) ( (DOUBLE) count * ( (DOUBLE) RAND / (DOUBLE) 0x7fffffff ) ) + 1 ; } while( incidence == count + 1 ) ; count = 0 ; for( i = 0 ; i <= 3 ; i++ ) { if( cellptr->orientList[i] == 1 ) { if( ++count == incidence ) { return( i ) ; } } } } else { count = 0 ; for( i = 4 ; i <= 7 ; i++ ) { if( cellptr->orientList[i] == 1 ) { count++ ; } } if( count == 0 ) { return( -1 ) ; } do { incidence = (INT) ( (DOUBLE) count * ( (DOUBLE) RAND / (DOUBLE) 0x7fffffff ) ) + 1 ; } while( incidence == count + 1 ) ; count = 0 ; for( i = 4 ; i <= 7 ; i++ ) { if( cellptr->orientList[i] == 1 ) { if( ++count == incidence ) { return( i ) ; } } } } } else { count = 0 ; for( i = 0 ; i <= 7 ; i++ ) { if( i == orient ) { continue ; } if( cellptr->orientList[i] == 1 ) { count++ ; } } if( count == 0 ) { return( -1 ) ; } do { incidence = (INT) ( (DOUBLE) count * ( (DOUBLE) RAND / (DOUBLE) 0x7fffffff ) ) + 1 ; } while( incidence == count + 1 ) ; count = 0 ; for( i = 0 ; i <= 7 ; i++ ) { if( i == orient ) { continue ; } if( cellptr->orientList[i] == 1 ) { if( ++count == incidence ) { return( i ) ; } } } } return( -1 ) ; } /* returns 0 if orientation is valid returns -1 if no orientation is valid returns +1 if it could find a valid orientation. */ INT check_valid_orient( cptr ) CELLBOXPTR cptr ; { INT i ; /* view counter */ if( cptr->orientList[cptr->orient] ){ /* this is valid no problem */ return( 0 ) ; } /* else move to the first valid one */ if( cptr->orient <= 3 ){ for( i = 0; i <= 7 ; i++ ){ if( cptr->orientList[i] ){ cptr->orient = i ; return( 1 ) ; } } } else { for( i = 7; i >= 0 ; i-- ){ if( cptr->orientList[i] ){ cptr->orient = i ; return( 1 ) ; } } } return( -1 ) ; } /* end check_valid_orient */ graywolf-0.1.4+20170307gite1bf319/src/twmc/newtemp.c000066400000000000000000000122151305746555600213510ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: newtemp.c DESCRIPTION:update temparature of the simulated annealing algorithm. CONTENTS: DOUBLE calc_acceptance_ratio( iteration ) DOUBLE iteration ; init_acceptance_rate() INT compute_attprcel() set_tw_speed( speed ) DOUBLE speed ; DATE: Dec 19, 1988 REVISIONS: Feb 25, 1989 - allow negative iterations by setting iteration to zero. Feb 28, 1989 - updated schedule constants. Mar 02, 1989 - moved schedule constants to temp.h Mar 07, 1989 - added compute_attprcel. Mar 13, 1989 - added set_tw_speed for attempts per cell modification. Mon Feb 4 02:14:30 EST 1991 - reset the number of attempts and added quickroute function. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) newtemp.c version 3.4 2/4/91" ; #endif #include #include #undef DEBUG #include static DOUBLE alphaS ; /* exponential decay constant for high temp */ static DOUBLE betaS ; /* exponential decay constant for low temp */ static DOUBLE speedS ; /* multiply attempts per cell by this factor */ /* calculate static exponential time constants */ init_acceptance_rate() { /* determine alpha */ alphaS = - log( CRITRATIO ) / HIGHTEMP ; /* determine beta */ betaS = - log( ( LOWRATIO/CRITRATIO ) ) / (LOWTEMP - MEDTEMP ) ; } /* end init_acceptance_rate */ /* given an iteration number return desired acceptance rate */ DOUBLE calc_acceptance_ratio( iteration ) DOUBLE iteration ; { DOUBLE desired_ratio ; if( iteration < 0.0 ){ /* allow negative iterations */ iteration = 0.0 ; } if( iteration <= HIGHTEMP ){ /* -------------------------------------------------------- desired_ratio = exp( - alphaS * iteration ) ; -------------------------------------------------------- */ desired_ratio = iteration ; desired_ratio *= - alphaS ; desired_ratio = exp( desired_ratio ) ; } else if( iteration <= MEDTEMP ){ desired_ratio = CRITRATIO ; } else if( iteration > LOWTEMP ){ /* last iterations */ if( iteration < LASTTEMP ) { desired_ratio = LOWRATIO - ( (LOWRATIO / (LASTTEMP - LOWTEMP)) * (iteration - LOWTEMP) ) ; } else { desired_ratio = 0.0 ; } } else { /* low temp */ /* -------------------------------------------------------- desired_ratio = 0.44 * exp( - betaS * ( iteration - MEDTEMP )) -------------------------------------------------------- */ desired_ratio = iteration - MEDTEMP ; desired_ratio *= - betaS ; desired_ratio = CRITRATIO * exp( desired_ratio ) ; } return( desired_ratio ) ; } /* end calc_acceptance ratio */ INT compute_attprcel() { DOUBLE attempts ; /* n to the 4/3 power */ attempts = 25.0 * pow( (DOUBLE) endsuperG, 4.0 / 3.0 ) ; if( quickrouteG ){ attempts /= 10.0 ; } else { /* modify the attempts per cell based on user input */ attempts *= speedS ; } if( attempts < (DOUBLE) MINTUPDATE ){ /* guarantee at least one temperature update */ attempts = (DOUBLE) MINTUPDATE + 2.0 ; } return((INT) attempts) ; } /* end compute_attprcell */ set_tw_speed( speed ) DOUBLE speed ; { speedS = speed ; } /* end set_tw_speed */ /* #define TESTRATIO */ #ifdef TESTRATIO /* test program for desired acceptance rate profile */ main( argc , argv ) INT argc ; char *argv[] ; { DOUBLE d_ratio, calc_acceptance_rate() ; INT i ; init_acceptance_rate() ; for( i= 0; i<= 155; i++ ){ d_ratio = calc_acceptance_ratio( (DOUBLE) i ) ; printf( "%4.2le\n" , d_ratio ) ; } } /* end main */ #endif /* TESTRATIO */ graywolf-0.1.4+20170307gite1bf319/src/twmc/outgeo.c000066400000000000000000000210161305746555600211730ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: outgeo.c DESCRIPTION:Routine dumps the placement of the cells for channel graph program. CONTENTS: DATE: Jan 30, 1988 REVISIONS: Jul 30, 1988 - made compile switch for blocking pads. I need to get cell name for mighty interface. Aug 15, 1988 - decide blocking of pads always needed. eliminated blocking compile switch. Blocking avoids channels between pads . Jan 15, 1988 - modified output so softcells would work correctly for compaction. Jan 17, 1988 - added dummy macro blocks for pads if pads don't exist on a side. This fixes a problem with the channel graph generator program. Mar 03, 1989 - fixed problem with bottom macro. Sep 12, 1989 - added new unbust algorithm. Sep 16, 1989 - fixed problem with unbust. Multiple tile cells should use tile count as argument since tiles need to be seamed together. Sep 19, 1989 - fixed dummy macro block coordinates for the case of no pads. Oct 15, 1989 - now output pad macros are placed at density using store pad location. Sun Dec 16 00:29:59 EST 1990 - now use library version of buster. Wed Jun 5 16:30:30 CDT 1991 - eliminated unbust. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) outgeo.c version 3.6 6/5/91" ; #endif #include #include #include #include #include #include static store_pad_loc(); outgeo() { FILE *fp ; INT cell ; INT l, b, r, t, x , y , xc , yc ; char filename[LRECL] ; CELLBOXPTR cellptr ; BOUNBOXPTR bounptr ; INT padmacroCounter ; INT left_side, right_side, bottom_side, top_side ; sprintf( filename, "%s.mgeo", cktNameG ) ; fp = TWOPEN( filename , "w", ABORT) ; padmacroCounter = numcellsG ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = cellarrayG[cell] ; fprintf(fp,"cell %s \n", cellptr->cname ) ; fprintf(fp,"%d vertices ", cellptr->numsides ) ; output_vertices( fp, cellptr ) ; } /* find core extent in case pads don't exist on a side */ find_core_boundary( &left_side, &right_side, &bottom_side, &top_side ) ; /* block all the pads into the four side cells */ /* first find left pad macro */ l = INT_MAX ; b = INT_MAX ; r = INT_MIN ; t = INT_MIN ; for( cell = endsuperG + 1 ; cell <= numcellsG + numpadsG ; cell++ ) { cellptr = cellarrayG[cell] ; if( cellptr->padptr->padside != L ) { continue ; } xc = cellptr->xcenter ; yc = cellptr->ycenter ; bounptr = cellptr->bounBox[ cellptr->orient ] ; if( xc + bounptr->l < l ) { l = xc + bounptr->l ; } if( xc + bounptr->r > r ) { r = xc + bounptr->r ; } if( yc + bounptr->b < b ) { b = yc + bounptr->b ; } if( yc + bounptr->t > t ) { t = yc + bounptr->t ; } } if( t == INT_MIN ) { /* make dummy pads for left */ /* use coordinates found from find_core_boundary */ l = left_side - 2 * track_spacingXG ; b = bottom_side + 2 * track_spacingYG ; r = left_side - track_spacingXG ; t = top_side - 2 * track_spacingYG ; } fprintf(fp,"cell %s \n", "pad.macro.l" ) ; fprintf(fp,"4 vertices ") ; fprintf(fp," %d %d %d %d %d %d %d %d\n", l, b, l, t, r, t, r, b ) ; setPadMacroNum( L, ++padmacroCounter ) ; cellptr = cellarrayG[endpadgrpsG + L] ; store_pad_loc( cellptr, l, r, b, t ) ; /* find pads on top of core */ l = INT_MAX ; b = INT_MAX ; r = INT_MIN ; t = INT_MIN ; for( cell = endsuperG + 1 ; cell <= numcellsG + numpadsG ; cell++ ) { cellptr = cellarrayG[cell] ; if( cellptr->padptr->padside != T ) { continue ; } xc = cellptr->xcenter ; yc = cellptr->ycenter ; bounptr = cellptr->bounBox[ cellptr->orient ] ; if( xc + bounptr->l < l ) { l = xc + bounptr->l ; } if( xc + bounptr->r > r ) { r = xc + bounptr->r ; } if( yc + bounptr->b < b ) { b = yc + bounptr->b ; } if( yc + bounptr->t > t ) { t = yc + bounptr->t ; } } if( t == INT_MIN ) { /* make dummy pads for top */ l = left_side + 2 * track_spacingXG ; b = top_side + track_spacingYG ; r = right_side - 2 * track_spacingXG ; t = top_side + 2 * track_spacingYG ; } fprintf(fp,"cell %s \n", "pad.macro.t" ) ; fprintf(fp,"4 vertices ") ; fprintf(fp," %d %d %d %d %d %d %d %d\n", l, b, l, t, r, t, r, b ) ; setPadMacroNum( T, ++padmacroCounter ) ; cellptr = cellarrayG[endpadgrpsG + T] ; store_pad_loc( cellptr, l, r, b, t ) ; l = INT_MAX ; b = INT_MAX ; r = INT_MIN ; t = INT_MIN ; for( cell = endsuperG + 1 ; cell <= numcellsG + numpadsG ; cell++ ) { cellptr = cellarrayG[cell] ; if( cellptr->padptr->padside != R ) { continue ; } xc = cellptr->xcenter ; yc = cellptr->ycenter ; bounptr = cellptr->bounBox[ cellptr->orient ] ; if( xc + bounptr->l < l ) { l = xc + bounptr->l ; } if( xc + bounptr->r > r ) { r = xc + bounptr->r ; } if( yc + bounptr->b < b ) { b = yc + bounptr->b ; } if( yc + bounptr->t > t ) { t = yc + bounptr->t ; } } if( t == INT_MIN ) { /* make dummy pads for right */ l = right_side + track_spacingXG ; b = bottom_side + 2 * track_spacingYG ; r = right_side + 2 * track_spacingXG ; t = top_side - 2 * track_spacingYG ; } fprintf(fp,"cell %s \n", "pad.macro.r" ) ; fprintf(fp,"4 vertices ") ; fprintf(fp," %d %d %d %d %d %d %d %d\n", l, b, l, t, r, t, r, b ) ; setPadMacroNum( R, ++padmacroCounter ) ; cellptr = cellarrayG[endpadgrpsG + R] ; store_pad_loc( cellptr, l, r, b, t ) ; l = INT_MAX ; b = INT_MAX ; r = INT_MIN ; t = INT_MIN ; for( cell = endsuperG + 1 ; cell <= numcellsG + numpadsG ; cell++ ) { cellptr = cellarrayG[cell] ; if( cellptr->padptr->padside != B ) { continue ; } xc = cellptr->xcenter ; yc = cellptr->ycenter ; bounptr = cellptr->bounBox[ cellptr->orient ] ; if( xc + bounptr->l < l ) { l = xc + bounptr->l ; } if( xc + bounptr->r > r ) { r = xc + bounptr->r ; } if( yc + bounptr->b < b ) { b = yc + bounptr->b ; } if( yc + bounptr->t > t ) { t = yc + bounptr->t ; } } if( t == INT_MIN ) { /* make dummy pads for bottom */ l = left_side + 2 * track_spacingXG ; b = bottom_side - 2 * track_spacingYG ; r = right_side - 2 * track_spacingXG ; t = bottom_side - track_spacingYG ; } fprintf(fp,"cell %s \n", "pad.macro.b" ) ; fprintf(fp,"4 vertices ") ; fprintf(fp," %d %d %d %d %d %d %d %d\n", l, b, l, t, r, t, r, b ) ; setPadMacroNum( B, ++padmacroCounter ) ; cellptr = cellarrayG[endpadgrpsG + B] ; store_pad_loc( cellptr, l, r, b, t ) ; TWCLOSE( fp ) ; return ; } /* end outgeo */ static store_pad_loc( cellptr, l, r, b, t ) CELLBOXPTR cellptr ; INT l, r, b, t ; { TILEBOXPTR tptr ; tptr = cellptr->tiles ; cellptr->xcenter = (l + r) / 2 ; cellptr->ycenter = (b + t) / 2 ; tptr->orig_left = tptr->left = l - cellptr->xcenter ; tptr->orig_right = tptr->right = r - cellptr->xcenter ; tptr->orig_bottom = tptr->bottom = b - cellptr->ycenter ; tptr->orig_top = tptr->top = t - cellptr->ycenter ; } /* end static store_pad_loc */ graywolf-0.1.4+20170307gite1bf319/src/twmc/outpin.c000066400000000000000000000331031305746555600212070ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: outpin.c DESCRIPTION:Routine outputs the pin positions to the pin file. CONTENTS: outpin() INT getPadMacroNum( side ) INT side ; setPadMacroNum( side, cellnum ) INT side, cellnum ; PINBOXPTR findTerminal( pinName, cell ) char *pinName ; INT cell ; DATE: Mar 16, 1988 - added description block and findTerminal. REVISIONS: Apr 25, 1989 - ignore 1 pin nets - causes global router to crash. Jun 21, 1989 - fixed so only true pins are output - not not averaged equiv pin locations. Sep 19, 1989 - now output equiv pins correctly. Apr 23, 1990 - modified for the new softpin algorithm. Sun Dec 16 00:39:46 EST 1990 - now output the analog nets. Wed Dec 19 23:59:29 EST 1990 - now output cap and res net matches. Dec 21, 1990 - now output the pin layer. Sun Jan 20 21:34:36 PST 1991 - ported to AIX. Wed Jan 30 14:13:36 EST 1991 - now left justify orientation rotations. Sat May 11 22:41:38 EDT 1991 - automatically move pad pins to correct channel. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) outpin.c version 3.11 5/11/91" ; #endif #include #include #include #include #include #include #include #include static BOOL *output_alreadyS ; /* mark the pins as they are output */ static FILE *fpS ; static INT output_typeS ; /* describe the type of circuit */ static output_pin(); static INT find_cell(); static process_analog_net(); static INT find_cell(); static output_matches(); outpin() { INT net ; /* counter */ char filename[LRECL] ; /* open this filename for writing */ NETBOXPTR netptr ; /* current net info */ PINBOXPTR pinptr ; /* current pin info */ sprintf( filename, "%s.mpin", cktNameG ) ; fpS = TWOPEN( filename , "w", ABORT ) ; output_alreadyS = (BOOL *) Ysafe_calloc( numpinsG+1, sizeof(BOOL) ) ; output_typeS = NONE ; for( net = 1 ; net <= numnetsG ; net++ ) { netptr = netarrayG[net] ; if( netptr->numpins <= 1 ){ /* no need to global route 1 pin nets */ continue ; } if( netptr->analog_info ){ process_analog_net( netptr ) ; output_typeS |= ANALOG ; continue ; } fprintf(fpS,"net %s\n", netptr->nname ) ; for( pinptr = netptr->pins ;pinptr;pinptr = pinptr->next ) { output_pin( pinptr ) ; output_typeS |= DIGITAL ; } fprintf( fpS,"\n" ) ; } output_matches() ; TWCLOSE(fpS); return ; } /* end outpins */ static output_pin( pinptr ) PINBOXPTR pinptr ; { INT i ; /* softpin counter */ INT cell ; /* the cell output modified for pad macros */ INT instance ; /* the current instance of the cell */ INT x, y ; /* the output coordinate of the pin */ INT xrel, yrel ; /* the x, y position relative to cell */ INT howmany ; /* howmany equivalent pins */ DOUBLE current ; /* the current specified for the pin */ EQUIVPTR eqptr ; /* current equivalent pointer */ PINBOXPTR child ; /* current child of the softpin */ SOFTBOXPTR spin ; /* current softpin */ CELLBOXPTR cellptr ; /* current cell info */ BOUNBOXPTR bounptr ; /* bounding box pointer */ /*static INT find_cell() ;*/ /* get cell number */ cell = find_cell( pinptr->cell ) ; cellptr = cellarrayG[pinptr->cell] ; instance = cellptr->cur_inst ; /* setup translation of output points */ bounptr = cellptr->bounBox[0] ; /* now init the translation routines using bounding box */ Ytrans_init( bounptr->l,bounptr->b,bounptr->r,bounptr->t, cellptr->orient ) ; if( pinptr->type == SOFTEQUIVTYPE ){ /* delay the equivalent softpins until below */ return ; } else { output_alreadyS[pinptr->pin] = TRUE ; xrel = pinptr->txpos_orig[instance] ; yrel = pinptr->typos_orig[instance] ; if( cell != pinptr->cell ){ /* this only occurs for pads */ if( yrel != bounptr->t ){ D( "twmc/outpin", fprintf( stderr, "Moving pad pin:%s to boundary\n", pinptr->pinname ) ; ) ; yrel = bounptr->t ; } } /* rel position is a macro which calculates */ /* absolute pin loc - defined in relpos.h */ REL_POST( cellptr->orient, x, y, /* result */ xrel, yrel, /* cell relative */ cellptr->xcenter, cellptr->ycenter ) ; /* cell center */ D( "twmc/outpin", if( x % track_spacingXG ){ fprintf( stderr, "Pin %s on cell %d x not on grid\n", pinptr->pinname, cell ) ; } if( y % track_spacingYG ){ fprintf( stderr, "Pin %s on cell %d x not on grid\n", pinptr->pinname, cell ) ; } ) ; fprintf(fpS,"pin %s x %d y %d cell %d layer %d PinOrEquiv 1", pinptr->pinname, x, y , cell, pinptr->layer ) ; if( pinptr->analog ){ current = pinptr->analog->current ; if( current > NO_CURRENT_SPECIFIED ){ fprintf( fpS, " current %4.3le", current ) ; } } fprintf( fpS, "\n" ) ; } /* ******** HARD PIN EQUIVALENT CASE ****** */ if( pinptr->eqptr && !(pinptr->softinfo)){ /* occurs only for hard pins */ /* now process the equivalent pins */ for( eqptr=pinptr->eqptr; eqptr; eqptr=eqptr->next ){ REL_POST( cellptr->orient, x, y, /* result */ eqptr->txpos[instance], eqptr->typos[instance], /* cell relative */ cellptr->xcenter, cellptr->ycenter ) ; /* center */ fprintf(fpS,"pin %s x %d y %d cell %d layer %d PinOrEquiv 0", pinptr->pinname, x, y , cell, pinptr->layer ) ; if( pinptr->analog ){ current = pinptr->analog->current ; if( current > NO_CURRENT_SPECIFIED ){ fprintf( fpS, " current %4.3le", current ) ; } } fprintf( fpS, "\n" ) ; } } /* ******** SOFT PIN EQUIVALENT CASE ****** */ /* now look for equivalent pins are children */ if( pinptr->type == SOFTPINTYPE ){ spin = pinptr->softinfo ; if( spin->children ){ howmany = (INT) spin->children[HOWMANY] ; } else { howmany = 0 ; } for( i = 1; i <= howmany; i++ ){ child = spin->children[i] ; REL_POST( cellptr->orient, x, y, /* result */ child->txpos, child->typos, /* cell relative */ cellptr->xcenter, cellptr->ycenter ) ; /* center */ fprintf(fpS,"pin %s x %d y %d cell %d layer %d PinOrEquiv 0", child->pinname, x, y , cell, child->layer ) ; if( pinptr->analog ){ current = pinptr->analog->current ; if( current > NO_CURRENT_SPECIFIED ){ fprintf( fpS, " current %4.3le", current ) ; } } fprintf( fpS, "\n" ) ; } } } /* end output_pin */ static process_analog_net( netptr ) NETBOXPTR netptr ; { INT i, j ; /* counters */ INT pin ; /* the pin index for the current pin in cpt */ INT len ; /* keep track of the total length output */ INT howmany ; /* howmany pins in the common point */ char *pinname ; /* current pinname output */ ANETPTR aptr ; /* current analog info record */ COMMONPTR cpt ; /* current common point */ PINBOXPTR pinptr ; /* current pins information */ aptr = netptr->analog_info ; fprintf(fpS,"analog_net %s ", netptr->nname ) ; if( aptr->cap_upper_bound > 0.0 ){ fprintf(fpS,"cap %4.3le ", aptr->cap_upper_bound ) ; } if( aptr->res_upper_bound > 0.0 ){ fprintf(fpS,"res %4.3le ", aptr->res_upper_bound ) ; } if( aptr->max_drop > NO_CONSTRAINT_ON_DROP ){ fprintf(fpS, "max_drop %4.3le ", aptr->max_drop ) ; } if( aptr->net_type & SHIELDMASK ){ fprintf(fpS, "shielding " ) ; } if( aptr->net_type & NOISYMASK ){ fprintf(fpS, "noisy " ) ; } if( aptr->net_type & SENSITIVEMASK ){ fprintf(fpS, "sensitive " ) ; } fprintf( fpS, "\n" ) ; /* output any common points first */ for( i = 0; i < aptr->num_common_points; i++ ){ cpt = aptr->common_pts[i] ; fprintf( fpS, "common_point %d\n", cpt->num_pins ) ; len = 0 ; howmany = cpt->num_pins - 1 ; for( j = 0; j <= howmany; j++ ){ pin = cpt->common_set[j] ; output_alreadyS[pin] = TRUE ; ASSERTNCONT( pin > 0 && pin < numpinsG, "outpin", "Trouble with common point\n" ) ; pinptr = termarrayG[pin] ; output_pin( pinptr ) ; } /* now output any cap match if it exists */ if( cpt->cap_match ){ howmany = cpt->cap_match[HOWMANY] ; fprintf( fpS, "cap_match " ) ; for( j = 1; j <= howmany; j++ ){ pin = cpt->cap_match[j] ; ASSERTNCONT( pin > 0 && pin < numpinsG, "outpin", "Trouble with cap_match\n" ) ; pinname = termarrayG[pin]->pinname ; len += strlen( pinname ) ; if( j > 1 ){ fprintf( fpS, ", " ) ; } if( len > LRECL ){ fprintf( fpS, "\n" ) ; } fprintf( fpS, "%s %d", pinname, find_cell( termarrayG[pin]->cell ) ) ; } fprintf( fpS, "\n" ) ; } /* now output any res match if it exists */ if( cpt->res_match ){ howmany = cpt->res_match[HOWMANY] ; fprintf( fpS, "res_match " ) ; for( j = 1; j <= howmany; j++ ){ pin = cpt->res_match[j] ; ASSERTNCONT( pin > 0 && pin < numpinsG, "outpin", "Trouble with res_match\n" ) ; pinname = termarrayG[pin]->pinname ; len += strlen( pinname ) ; if( j > 1 ){ fprintf( fpS, ", " ) ; } if( len > LRECL ){ fprintf( fpS, "\n" ) ; } fprintf( fpS, "%s %d", pinname, find_cell( termarrayG[pin]->cell ) ) ; } fprintf( fpS, "\n" ) ; } } /* now output the regular pins that have no common point */ for( pinptr = netptr->pins;pinptr;pinptr=pinptr->next ) { if( output_alreadyS[pinptr->pin] ){ continue ; } output_pin( pinptr ) ; } fprintf( fpS, "\n" ) ; } /* process_analog_net */ /* since channel graph generator creates many channels for pads */ /* we block pads together and create a new cell called a pad macro */ /* the cell number is numbered in outgeo.c. This number needs to be */ /* matched in outpins. Therefore, we use this simple translation table */ static INT side2cellS[5] = { 0,0,0,0,0 } ; INT getPadMacroNum( side ) INT side ; { return( side2cellS[side] ) ; } /* end getPadMacroNum */ setPadMacroNum( side, cellnum ) INT side ; INT cellnum ; { side2cellS[side] = cellnum ; } /* end getPadMacroNum */ static INT find_cell( cell ) INT cell ; { if( cell > endsuperG ) { if( cellarrayG[cell]->padptr->padside == L ) { cell = getPadMacroNum( L ) ; } else if( cellarrayG[cell]->padptr->padside == T ) { cell = getPadMacroNum( T ) ; } else if( cellarrayG[cell]->padptr->padside == R ) { cell = getPadMacroNum( R ) ; } else if( cellarrayG[cell]->padptr->padside == B ) { cell = getPadMacroNum( B ) ; } } return( cell ) ; } /* end find_cell */ /* given pinName and cell find pin recosrd */ /* return NULL if no terminal is found */ PINBOXPTR findTerminal( pinName, cell ) char *pinName ; INT cell ; { PINBOXPTR pin ; CELLBOXPTR cptr ; cptr = cellarrayG[cell] ; /* first look thru hard pins */ for( pin=cptr->pinptr;pin;pin=pin->nextpin ){ if( strcmp( pinName, pin->pinname ) == STRINGEQ ){ return( pin ) ; } } /* we have failed to find a match return null */ return( NULL ) ; } /* end findTerminal */ INT get_circuit_type() { return( output_typeS ) ; } /* end get_circuit_type */ static output_matches() { INT i, j ; INT net ; INT *match ; INT num_matches ; INT howmany ; howmany = (INT) net_cap_matchG[HOWMANY] ; for( i = 1; i <= howmany; i++ ){ match = net_cap_matchG[i] ; num_matches = match[HOWMANY] ; fprintf( fpS, "net_cap_match " ) ; for( j = 1; j <= num_matches; j++ ){ net = match[j] ; fprintf( fpS, "%s ", netarrayG[net]->nname ) ; } fprintf( fpS, "\n" ) ; } howmany = (INT) net_res_matchG[HOWMANY] ; for( i = 1; i <= howmany; i++ ){ match = net_res_matchG[i] ; num_matches = match[HOWMANY] ; fprintf( fpS, "net_res_match " ) ; for( j = 1; j <= num_matches; j++ ){ net = match[j] ; fprintf( fpS, "%s ", netarrayG[net]->nname ) ; } fprintf( fpS, "\n" ) ; } } /* end output_matches */ graywolf-0.1.4+20170307gite1bf319/src/twmc/output.c000066400000000000000000000514231305746555600212360ustar00rootroot00000000000000/* * Copyright (C) 1988-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: output.c DESCRIPTION:placer output routine CONTENTS: output( fp ) FILE *fp ; DATE: Jan 29, 1988 REVISIONS: Aug 10, 1988 - add compile switch for Dahe. Mar 29, 1989 - added translatef for floating numbers. Apr 27, 1989 - removed Dahe's format by adding new format. Apr 30, 1989 - fixed missing file pointer. May 8, 1989 - added update to stat file. May 11, 1989 - made output same as input format. May 16, 1989 - removed unneccessary code. Jun 21, 1989 - now output only true pin locations not averaged equiv locations. Sep 16, 1989 - fixed problem with unbust. Multiple tile cells should use tile count as argument since tiles need to be seamed together. Oct 5, 1989 - now output equivs correctly. Oct 15, 1989 - need to rotate border so output is in correct orientation. Nov 30, 1989 - fixed bug in inverse orientation. Apr 23, 1990 - modified for the new softpin algorithm. Apr 26, 1990 - take absolute value of layers in order to handle tenatively assigned layers. Jun 21, 1990 - Output the aspect ratio for standard cells. Aug 10, 1990 - moved translation files to library. Sun Dec 16 00:33:09 EST 1990 - Now use the library version of buster. Wed Jan 30 14:13:36 EST 1991 - now left justify orientation rotations. Wed Feb 13 23:53:54 EST 1991 - added outpins function. Sat Feb 23 00:26:42 EST 1991 - fixed problems with outputing padgroups. Tue Mar 12 17:02:16 CST 1991 - now no longer determine side of pad in partitioning case. Tue Mar 19 16:33:23 CST 1991 - fixed typo in output_pad_groups which accessed the wrong array. Thu Apr 18 01:38:21 EDT 1991 - reversed corners. Sat Apr 27 01:12:42 EDT 1991 - no longer need to output number of orientations. Wed Jun 5 16:30:30 CDT 1991 - eliminated unbust. Wed Jun 12 13:43:19 CDT 1991 - fixed problem with ordered pad groups. Mon Aug 12 16:57:04 CDT 1991 - create sc output files. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) output.c version 3.16 3/6/92" ; #endif #include #include #include #include #include #include #include #include static FILE *outS ; /* the output file */ static BOOL determine_sideS = TRUE ; /* normally determine side */ static output_corners(); static output_class_orient(); static output_pins(); static output_side_n_space(); static output_pad_groups(); static output_fixed(); static create_pl1(); static print_four_corners(); static create_pin(); output( fp ) FILE *fp ; { INT cell ; char filename[LRECL] ; CELLBOXPTR cellptr ; if( fp ){ /* partition output case */ outS = fp ; } else { /* normal case */ sprintf( filename, "%s.mdat", cktNameG ) ; outS = TWOPEN( filename, "w", ABORT ) ; } for( cell = 1 ; cell <= totalcellsG ; cell++ ) { cellptr = cellarrayG[cell] ; switch( cellptr->celltype ){ case CUSTOMCELLTYPE : fprintf( outS,"\nhardcell %d name %s\n", cellptr->cellnum, cellptr->cname ) ; output_fixed( cellptr ) ; output_corners( cellptr ) ; output_class_orient( cellptr ) ; output_pins( cellptr ) ; break ; case PADCELLTYPE : fprintf( outS,"\npad %d name %s\n", cellptr->cellnum, cellptr->cname ) ; output_corners( cellptr ) ; fprintf( outS, "orient %d\n", cellptr->orient ) ; output_side_n_space( cellptr ) ; output_pins( cellptr ) ; break ; case SOFTCELLTYPE : fprintf( outS,"\nsoftcell %d name %s\n", cellptr->cellnum, cellptr->cname ) ; output_fixed( cellptr ) ; output_corners( cellptr ) ; fprintf( outS,"asplb %lf aspub %lf\n", cellptr->aspLB, cellptr->aspUB ) ; output_class_orient( cellptr ) ; output_pins( cellptr ) ; break ; case PADGROUPTYPE : if( cellptr->padptr->permute ){ fprintf( outS,"\npadgroup %s permute\n", cellptr->cname ); } else { fprintf( outS,"\npadgroup %s nopermute\n", cellptr->cname); } output_pad_groups( cellptr ) ; output_side_n_space( cellptr ) ; break ; case SUPERCELLTYPE : case MERGEDCELLTYPE : case GROUPCELLTYPE : case PADMACROTYPE : break ; case STDCELLTYPE : if( fp ){ /* partition output file does not need this */ break ; } fprintf( outS,"\nstdcell %d name %s\n", cellptr->cellnum, cellptr->cname ) ; output_corners( cellptr ) ; fprintf( outS,"asplb %lf aspub %lf\n", cellptr->aspLB, cellptr->aspUB ) ; output_class_orient( cellptr ) ; break ; } } TWCLOSE( outS ) ; return ; } /* end output */ output_pads( fp ) FILE *fp ; { INT cell ; BOOL save_state ; BOOL save_orient ; CELLBOXPTR cellptr ; outS = fp ; save_state = determine_sideS ; determine_sideS = FALSE ; /* let placepads pick side */ for( cell = endsuperG ; cell <= totalcellsG ; cell++ ) { cellptr = cellarrayG[cell] ; save_orient = cellptr->orient ; cellptr->orient = 0 ; /* pads should be output in orient 0 */ switch( cellptr->celltype ){ case PADCELLTYPE : fprintf( outS,"\npad %d name %s\n", cellptr->cellnum, cellptr->cname ) ; output_corners( cellptr ) ; output_side_n_space( cellptr ) ; output_pins( cellptr ) ; break ; case PADGROUPTYPE : if( cellptr->padptr->permute ){ fprintf( outS,"\npadgroup %s permute\n", cellptr->cname ); } else { fprintf( outS,"\npadgroup %s nopermute\n", cellptr->cname); } output_pad_groups( cellptr ) ; output_side_n_space( cellptr ) ; break ; } /* now put orientation back */ cellptr->orient = save_orient ; } determine_sideS = save_state ; return ; } /* end output_pads */ static output_corners( cellptr ) CELLBOXPTR cellptr ; { fprintf( outS, "corners %d\n", cellptr->numsides ) ; output_vertices( outS, cellptr ) ; } /* end output_corners */ static output_class_orient( cellptr ) CELLBOXPTR cellptr ; { INT i ; fprintf( outS, "class %d ", cellptr->class ) ; fprintf( outS, "orientations " ) ; for( i = 0; i <= 7 ; i++ ){ if( cellptr->orientList[i] ){ fprintf( outS, "%d ", i ) ; } } fprintf( outS, "\n" ) ; fprintf( outS, "orient %d\n", cellptr->orient ) ; } /* end output_class_orient */ static output_pins( cellptr ) CELLBOXPTR cellptr ; { INT i ; /* counter */ INT x, y ; /* absolute coordinates */ INT instance ; /* current instance */ INT howmany ; /* number of equivalent pins */ PINBOXPTR pinptr ; /* current pin */ PINBOXPTR child ; /* softcell child */ SOFTBOXPTR spin ; /* current softpin information */ EQUIVPTR eqptr ; /* current equiv */ instance = cellptr->cur_inst ; for( pinptr=cellptr->pinptr;pinptr;pinptr = pinptr->nextpin ){ if( pinptr->type == SOFTEQUIVTYPE ){ /* delay the equivalent softpins until below */ continue ; } else { /* rel position is a macro which calculates */ /* absolute pin loc - defined in relpos.h */ REL_POST( cellptr->orient, x, y, /* result */ pinptr->txpos_orig[instance], pinptr->typos_orig[instance], /* cell relative */ cellptr->xcenter, cellptr->ycenter ) ; /* cell center */ fprintf(outS,"pin name %s signal %s layer %d %d %d\n", pinptr->pinname, netarrayG[ pinptr->net ]->nname, ABS(pinptr->layer), x , y ) ; } /* ******** HARD PIN EQUIVALENT CASE ****** */ if( pinptr->eqptr && !(pinptr->softinfo)){ /* occurs only for hard pins */ /* now process the equivalent pins */ for( eqptr=pinptr->eqptr; eqptr; eqptr=eqptr->next ){ REL_POST( cellptr->orient, x, y, /* result */ eqptr->txpos[instance], eqptr->typos[instance], /* cell relative */ cellptr->xcenter, cellptr->ycenter ) ; /* center */ fprintf(outS,"equiv name %s layer %d %d %d\n", pinptr->pinname, ABS(pinptr->layer), x , y ) ; } } /* ******** SOFT PIN EQUIVALENT CASE ****** */ /* now look for equivalent pins are children */ if( pinptr->type == SOFTPINTYPE ){ spin = pinptr->softinfo ; if( spin->children ){ howmany = (INT) spin->children[HOWMANY] ; } else { howmany = 0 ; } for( i = 1; i <= howmany; i++ ){ child = spin->children[i] ; REL_POST( cellptr->orient, x, y, /* result */ child->txpos, child->typos, /* cell relative */ cellptr->xcenter, cellptr->ycenter ) ; /* center */ fprintf(outS,"equiv name %s layer %d %d %d\n", child->pinname, ABS(pinptr->layer), x , y ) ; } } } } /* end output_pins */ static output_side_n_space( cellptr ) CELLBOXPTR cellptr ; { INT i ; /* counter */ PADBOXPTR pad ; pad = cellptr->padptr ; if(!(pad->valid_side[ALL] )){ if( determine_sideS ){ switch( pad->padside ){ case L: fprintf( outS, "restrict side L\n" ) ; break ; case T: fprintf( outS, "restrict side T\n" ) ; break ; case R: fprintf( outS, "restrict side R\n" ) ; break ; case B: fprintf( outS, "restrict side B\n" ) ; break ; } /* end switch */ } else { /* pass constraints to the output file */ fprintf( outS, "restrict side " ) ; if( pad->valid_side[L] ){ fprintf( outS, "L" ) ; } if( pad->valid_side[T] ){ fprintf( outS, "T" ) ; } if( pad->valid_side[R] ){ fprintf( outS, "R" ) ; } if( pad->valid_side[B] ){ fprintf( outS, "B" ) ; } fprintf( outS, "\n" ) ; } } if( pad->fixed ){ fprintf( outS, "sidespace %lf %lf\n", pad->lowerbound, pad->upperbound ) ; } } /* end output_side_n_space */ static output_pad_groups( cellptr ) CELLBOXPTR cellptr ; { INT i, child, padnum ; PADBOXPTR pad ; CELLBOXPTR cptr ; /* temporary pointer to child cell rec */ pad = cellptr->padptr ; for( i = 1; i <= pad->children[HOWMANY]; i++ ){ padnum = pad->children[i] ; child = padarrayG[padnum]->cellnum ; ASSERTNCONT( child > 0 && child <= totalcellsG,"output", "pad child out of bounds\n" ) ; cptr = cellarrayG[child] ; fprintf( outS, "%s ", cellarrayG[child]->cname ) ; if( cptr->padptr->ordered ){ fprintf( outS, "fixed\n" ) ; } else { fprintf( outS, "nonfixed\n" ) ; } } } /* end output_pad_groups */ static output_fixed( cellptr ) CELLBOXPTR cellptr ; { FIXEDBOXPTR fixptr ; if(!(fixptr = cellptr->fixed)){ return ; } if( fixptr->fixedType == POINTFLAG ){ fprintf( outS, "fixed at " ) ; if( fixptr->leftNotRight == TRUE ){ fprintf( outS, "%d from L ", fixptr->xcenter ) ; } else { fprintf( outS, "%d from R ", fixptr->xcenter ) ; } if( fixptr->bottomNotTop == TRUE ){ fprintf( outS, "%d from B ", fixptr->ycenter ) ; } else { fprintf( outS, "%d from T ", fixptr->ycenter ) ; } } else { fprintf( outS, "fixed neighborhood " ) ; if( fixptr->leftNotRight == TRUE ){ fprintf( outS, "%d from L ", fixptr->xloc1 ) ; } else { fprintf( outS, "%d from R ", fixptr->xloc1 ) ; } if( fixptr->bottomNotTop == TRUE ){ fprintf( outS, "%d from B ", fixptr->yloc1 ) ; } else { fprintf( outS, "%d from T ", fixptr->yloc1 ) ; } if( fixptr->leftNotRight2 == TRUE ){ fprintf( outS, "%d from L ", fixptr->xloc2 ) ; } else { fprintf( outS, "%d from R ", fixptr->xloc2 ) ; } if( fixptr->bottomNotTop2 == TRUE ){ fprintf( outS, "%d from B ", fixptr->yloc2 ) ; } else { fprintf( outS, "%d from T ", fixptr->yloc2 ) ; } } } /* end output_fixed */ set_determine_side( flag ) BOOL flag ; { determine_sideS = flag ; } /* end set_determine_side */ output_vertices( fp, cellptr ) FILE *fp ; CELLBOXPTR cellptr ; { INT xc , yc ; TILEBOXPTR tileptr ; BOUNBOXPTR bounptr ; /* bounding box pointer */ INT *xvert ; /* the xvertices of cell */ INT *yvert ; /* the yvertices of cell */ VERTBOXPTR vert ; /* the cells vertices */ INT p ; INT x, y ; INT l, b ; INT this_pt ; INT inverse ; INT old_orient ; INT lowestp ; INT limit ; INT nextpos, nextneg ; INT *temp_x ; INT *temp_y ; INT numpts ; xc = cellptr->xcenter ; yc = cellptr->ycenter ; vert = cellptr->vertices ; xvert = vert->x ; yvert = vert->y ; numpts = cellptr->numsides ; /* setup translation of output points */ bounptr = cellptr->bounBox[0] ; /* now init the translation routines using bounding box */ Ytrans_init( bounptr->l,bounptr->b,bounptr->r,bounptr->t, cellptr->orient ) ; /* allocate the space for reoordering the points of the macro */ temp_x = (INT *) Yvector_alloc( 1, numpts,sizeof(INT) ) ; temp_y = (INT *) Yvector_alloc( 1, numpts,sizeof(INT) ) ; for( p = 1; p <= cellptr->numsides; p++ ){ /* rel position is a macro which calculates */ /* absolute pin loc - defined in relpos.h */ REL_POST( cellptr->orient, temp_x[p], temp_y[p], /* result */ xvert[p], yvert[p], xc, yc ) ; } /* now we need to reorder the vertices */ /* all the points have been rotated into their proper view and */ /* stored in the vertices array. Now find lowest of the left pts. */ l = INT_MAX ; b = INT_MAX ; for( p = 1; p <= numpts; p++ ){ if( temp_x[p] <= l ){ if( temp_y[p] <= b ){ l = temp_x[p] ; b = temp_y[p] ; lowestp = p ; } } } /* output the first points */ fprintf( fp, "%d %d ", l, b ) ; /* now determine CW direction */ nextpos = lowestp + 1 ; if( nextpos > numpts ){ nextpos = 1 ; } if( lowestp == 1 ){ nextneg = numpts ; } else { nextneg = lowestp - 1 ; } if( temp_x[nextpos] == l && temp_y[nextpos] > b ){ /* clockwise is positive */ limit = lowestp + numpts; for( p = lowestp+1; p < limit; p++ ) { if( p > numpts ){ this_pt = p - numpts ; } else { this_pt = p ; } fprintf( fp, "%d %d ", temp_x[this_pt], temp_y[this_pt] ) ; } } else if( temp_x[nextneg] == l && temp_y[nextneg] > b ){ /* clockwise is negative */ limit = lowestp - numpts ; for( p = lowestp-1; p > limit; p-- ) { if( p < 1 ){ this_pt = numpts + p ; } else { this_pt = p ; } fprintf( fp, "%d %d ", temp_x[this_pt], temp_y[this_pt] ) ; } } else { M( ERRMSG, "output_vertices", "couldn't find clockwise direction for boundary\n" ) ; } fprintf( fp, "\n" ) ; Yvector_free( temp_x, 1, sizeof(INT) ) ; Yvector_free( temp_y, 1, sizeof(INT) ) ; } /* end output_vertices */ create_sc_output() { create_pl1() ; create_pin() ; } /* end create_sc_output */ /** by kroy July 1991 **/ /* modified by WPS Aug 6, 1991 */ static create_pl1() { FILE *fpp1 ; CELLBOXPTR cellptr ; PADBOXPTR pad ; INT cell, length, row ; char instance_name[LRECL], tmp_name[LRECL], *tmp_string; char filename[LRECL]; sprintf( filename , "%s.pl1" , cktNameG ) ; fpp1 = TWOPEN( filename , "w", ABORT ) ; for( cell = 1 ; cell <= totalcellsG ; cell++ ) { cellptr = cellarrayG[cell] ; switch( cellptr->celltype ){ case CUSTOMCELLTYPE : case SOFTCELLTYPE : #ifdef NSC strcpy( tmp_name , cellptr->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpp1,"%s ", instance_name); #else fprintf(fpp1,"%s ", cellptr->cname); #endif print_four_corners (fpp1, cellptr ) ; fprintf(fpp1," %d 0\n", cellptr->orient ) ; break ; case PADCELLTYPE : #ifdef NSC strcpy( tmp_name , cellptr->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpp1,"%s ", instance_name); #else fprintf(fpp1,"%s ", cellptr->cname); #endif print_four_corners (fpp1, cellptr ) ; pad = cellptr->padptr ; switch( pad->padside ){ case L: row = - 1 ; break ; case T: row = -4 ; break ; case R: row = - 2 ; break ; case B: row = - 3 ; break ; } /* end switch */ fprintf(fpp1," %d %d\n", cellptr->orient , row ) ; break ; case PADGROUPTYPE : case SUPERCELLTYPE : case MERGEDCELLTYPE : case GROUPCELLTYPE : case PADMACROTYPE : case STDCELLTYPE : break ; } /* end switch( cellptr->celltype... */ } /* end for( cell = 1... */ fflush( fpp1 ); TWCLOSE( fpp1 ) ; } /* create_pl1 */ static print_four_corners( fp, cellptr ) FILE *fp ; CELLBOXPTR cellptr ; { INT xc , yc ; BOUNBOXPTR bounptr ; /* bounding box pointer */ xc = cellptr->xcenter ; yc = cellptr->ycenter ; /* setup translation of output points */ bounptr = cellptr->bounBox[0] ; /* now init the translation routines using bounding box */ Ytrans_init( bounptr->l,bounptr->b,bounptr->r,bounptr->t, cellptr->orient ) ; YtranslateC( &(bounptr->l), &(bounptr->b), &(bounptr->r),&(bounptr->t), cellptr->orient ) ; fprintf( fp, "%d %d ", bounptr->l + xc, bounptr->b + yc ) ; fprintf( fp, "%d %d ", bounptr->r + xc, bounptr->t + yc ) ; fflush ( fp ); } /* end print_four_corners */ /* by WPS Aug 6, 1991 */ static create_pin() { FILE *fpp1 ; CELLBOXPTR cellptr ; PADBOXPTR pad ; char filename[LRECL]; INT net, row ; NETBOXPTR netptr ; PINBOXPTR pinptr ; sprintf( filename , "%s.pin" , cktNameG ) ; fpp1 = TWOPEN( filename , "w", ABORT ) ; for( net = 1 ; net <= numnetsG ; net++ ) { netptr = netarrayG[net] ; if(!(netptr)) { continue ; } if( netptr->numpins <= 1 ) { continue ; } /* output the pins on the net */ for( pinptr = netptr->pins;pinptr; pinptr = pinptr->next ) { cellptr = cellarrayG[pinptr->cell] ; switch( cellptr->celltype ){ case CUSTOMCELLTYPE : case SOFTCELLTYPE : fprintf( fpp1, "%s %d %s %s %d %d 0 0 %d\n", netptr->nname, net, cellptr->cname, pinptr->pinname, pinptr->xpos, pinptr->ypos, pinptr->layer ) ; break ; case PADCELLTYPE : pad = cellptr->padptr ; switch( pad->padside ){ case L: row = - 1 ; break ; case T: row = -4 ; break ; case R: row = - 2 ; break ; case B: row = - 3 ; break ; } /* end switch */ fprintf( fpp1, "%s %d %s %s %d %d %d 0 %d\n", netptr->nname, net, cellptr->cname, pinptr->pinname, pinptr->xpos, pinptr->ypos, row, pinptr->layer ) ; fprintf( fpp1, "%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d 0 %d\n", netptr->nname, net, pinptr->xpos, pinptr->ypos, row, pinptr->layer ) ; fprintf( fpp1, "%s %d PSEUDO_CELL PSEUDO_PIN %d %d 0 0 %d\n", netptr->nname, net, pinptr->xpos, pinptr->ypos, pinptr->layer ) ; break ; case PADGROUPTYPE : case SUPERCELLTYPE : case MERGEDCELLTYPE : case GROUPCELLTYPE : case PADMACROTYPE : case STDCELLTYPE : break ; } /* end switch( cellptr->celltype... */ } } /* end for( cell = 1... */ fflush( fpp1 ); TWCLOSE( fpp1 ) ; } /* create_pin */ graywolf-0.1.4+20170307gite1bf319/src/twmc/overlap.c000066400000000000000000000727641305746555600213610ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: overlap.c DESCRIPTION:This file contains routines for one and two cell overlap calculation. Overlap routines returns newpenalty. This procedure works for hard and soft cells. Hard cells explicitly store their 8 orientation views whereas for softcells their orientation needs to be calculated. CONTENTS: overlap( ) overlap2( ) update_overlap( ) update_overlap2( ) sub_penal( MOVEBOXPTR * ) add_penal( MOVEBOXPTR * ) calc_wBins( MOVEBOXPTR * ) calc_nBins( MOVEBOXPTR * ) turn_wireest_on( INT ) find_orient() setup_Bins( CELLBOXPTR, int, int, INT ) add2bin( MOVEBOXPTR * ) DATE: Feb 2, 1988 REVISIONS: Feb 5, 1988 - changed old_apos, new_apos, old_bpos, new_bpos to global variables. Old method remains commented for easier reading. Feb 8, 1988 - added setup_Bins for loadbins.c Feb 12, 1988 - added add2bin for loadbins.c Oct 21, 1988 - added fastbin to speed overlap calculation Apr 2, 1989 - changed softcells to have multiple tiles Apr 4, 1989 - added instance changes. Sun Jan 20 21:34:36 PST 1991 - ported to AIX. Mon Feb 4 02:15:23 EST 1991 - added new wire estimator. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) overlap.c version 3.6 4/18/91" ; #endif #include #include #include /* ----------------------------------------------------------------- IMPORTANT global definitions - defined in custom.h MOVEBOXPTR *old_aposG, *new_aposG, *old_bposG, *new_bposG ; MOVEBOXPTR old_apos0G, new_apos0G, old_bpos0G, new_bpos0G ; BINPTR **binptrG ; */ #define calcBins(a) ( (*calc_Bins)(a) ) #define WIREESTXY(pos,xc,yc) ( (*wire_est)(pos,xc,yc) ) /* static definitions */ static CELLBOXPTR cellptrS ; static TILEBOXPTR tileptrS ; static MOVEBOXPTR posS ; static BINBOXPTR bptrS ; static xcS, ycS, orientS ; static INT minXS, maxXS, minYS, maxYS ; static INT newbinpenalS ; static INT xcostS, ycostS ; static INT (*calc_Bins)() ;/* remember which bin function */ static INT (*wire_est)() ; /* remember which wire estimation function */ /* global references */ extern INT wireestxy( P3(MOVEBOXPTR pos,INT xc, INT yc) ) ; extern INT wireestxy2( P3(MOVEBOXPTR pos,INT xc, INT yc) ) ; /* ***************************************************************** ONE CELL OVERLAP CALCULATION */ INT overlap( /* old_aposG, new_aposG */ ) /* MOVEBOXPTR *old_aposG, *new_aposG ; */ { register BINBOXPTR *fastbin ; register x, y ; /* ----------------------------------------------------------------- Perform overlap calculation over all tiles. In calculating overlap OLD A and NEW A are a pair. CALCULATE BINS FOR OLD A POSITION */ newbinpenalS = 0 ; cellptrS = cellarrayG[old_apos0G->cell] ; orientS = cellptrS->orient ; xcS = cellptrS->xcenter ; ycS = cellptrS->ycenter ; /* initialize bounding box comparison for each pair */ maxXS = INT_MIN ; maxYS = INT_MIN ; minXS = INT_MAX ; minYS = INT_MAX ; /* ----------------------------------------------------------------- NOTE: turn_wireest_on determines whether we call calc_wBins or calc_nBins */ calcBins( old_aposG ) ; /* ----------------------------------------------------------------- CALCULATE BINS FOR NEW A POSITION */ cellptrS = cellarrayG[new_apos0G->cell] ; orientS = new_apos0G->orient ; xcS = new_apos0G->xcenter ; ycS = new_apos0G->ycenter ; calcBins( new_aposG ) ; /* ----------------------------------------------------------------- Perform overlap initialization for OLD A - NEW A pair minX, minY, maxX, maxY now has bounding box for this pair. Store result in old_apos for latter use in update overlap */ old_apos0G->binR = maxXS ; old_apos0G->binL = minXS ; old_apos0G->binT = maxYS ; old_apos0G->binB = minYS ; for( x = minXS; x <= maxXS ; x++ ){ fastbin = binptrG[x] ; for( y = minYS; y <= maxYS ; y++ ){ bptrS = fastbin[y] ; bptrS->nupenalty = bptrS->penalty ; } } /* ----------------------------------------------------------------- INITIALIZATION COMPLETE. NOW perform calculation. NOW any order will do. Since cellptr is set from previous calculation to a do a cell calculation first. */ /* perform overlap calculation */ sub_penal( old_aposG ) ; add_penal( new_aposG ) ; return( newbinpenalS ) ; } /* end function overlap */ /* ***************************************************************** TWO CELL OVERLAP CALCULATION */ INT overlap2( /* old_aposG, new_aposG, old_bposG, new_bposG */ ) /* MOVEBOXPTR *old_aposG, *new_aposG, *old_bposG, *new_bposG ; */ { register BINBOXPTR *fastbin ; register x, y ; /* ----------------------------------------------------------------- Perform overlap calculation over all tiles. In calculating overlap OLD A and NEW B are a pair and OLD B and NEW A are a pair - calculate overlap in pairs. We will calculate in this order: OLD A, NEW B, OLD B, NEW A CALCULATE BINS FOR OLD A POSITION */ newbinpenalS = 0 ; cellptrS = cellarrayG[old_apos0G->cell] ; orientS = cellptrS->orient ; xcS = cellptrS->xcenter ; ycS = cellptrS->ycenter ; /* initialize bounding box comparison for each pair */ maxXS = INT_MIN ; maxYS = INT_MIN ; minXS = INT_MAX ; minYS = INT_MAX ; calcBins( old_aposG ) ; /* ----------------------------------------------------------------- CALCULATE BINS FOR NEW B POSITION */ cellptrS = cellarrayG[new_bpos0G->cell] ; orientS = new_bpos0G->orient ; xcS = new_bpos0G->xcenter ; ycS = new_bpos0G->ycenter ; calcBins( new_bposG ) ; /* ----------------------------------------------------------------- Perform overlap initialization for OLD A - NEW B pair minX, minY, maxX, maxY now has bounding box for this pair. Store result in old_apos for latter use in update overlap */ old_apos0G->binR = maxXS ; old_apos0G->binL = minXS ; old_apos0G->binT = maxYS ; old_apos0G->binB = minYS ; for( x = minXS; x <= maxXS ; x++ ){ fastbin = binptrG[x] ; for( y = minYS; y <= maxYS ; y++ ){ bptrS = fastbin[y] ; bptrS->nupenalty = bptrS->penalty ; } } /* ----------------------------------------------------------------- Perform overlap calculation over all tiles. CALCULATE BINS FOR OLD B POSITION */ cellptrS = cellarrayG[old_bpos0G->cell] ; orientS = cellptrS->orient ; xcS = cellptrS->xcenter ; ycS = cellptrS->ycenter ; /* initialize bounding box comparison for OLDB-NEWA pair */ maxXS = INT_MIN ; maxYS = INT_MIN ; minXS = INT_MAX ; minYS = INT_MAX ; calcBins( old_bposG ) ; /* ----------------------------------------------------------------- CALCULATE BINS FOR NEW A POSITION */ cellptrS = cellarrayG[new_apos0G->cell] ; orientS = new_apos0G->orient ; xcS = new_apos0G->xcenter ; ycS = new_apos0G->ycenter ; calcBins( new_aposG ) ; /* ----------------------------------------------------------------- Perform overlap initialization for OLD B - NEW A pair minX, minY, maxX, maxY now has bounding box for this pair. Store result in old_bpos for latter use in update overlap */ old_bpos0G->binR = maxXS ; old_bpos0G->binL = minXS ; old_bpos0G->binT = maxYS ; old_bpos0G->binB = minYS ; for( x = minXS; x <= maxXS ; x++ ){ fastbin = binptrG[x] ; for( y = minYS; y <= maxYS ; y++ ){ bptrS = fastbin[y] ; bptrS->nupenalty = bptrS->penalty ; } } /* ----------------------------------------------------------------- INITIALIZATION COMPLETE. NOW perform calculation. NOW any order will do. */ /* perform overlap calculation */ sub_penal( old_aposG ) ; add_penal( new_aposG ) ; sub_penal( old_bposG ) ; add_penal( new_bposG ) ; return( newbinpenalS ) ; } /* end function overlap2 */ /* ***************************************************************** Update one cell move by transferring from nu to penalty fields */ INT update_overlap( /* old_aposG */ ) /* MOVEBOXPTR *old_aposG ; */ { register BINBOXPTR *fastbin ; register x, y ; /* ----------------------------------------------------------------- Perform overlap update for OLD A - NEW A pair Recall information stored in old_apos[0] to get bounding box for this pair. */ maxXS = old_apos0G->binR ; minXS = old_apos0G->binL ; maxYS = old_apos0G->binT ; minYS = old_apos0G->binB ; for( x = minXS; x <= maxXS ; x++ ){ fastbin = binptrG[x] ; for( y = minYS; y <= maxYS ; y++ ){ bptrS = fastbin[y] ; bptrS->penalty = bptrS->nupenalty ; } } } /* end function update_overlap */ /* ***************************************************************** Update two cell move by transferring from nu to penalty fields */ INT update_overlap2( /* old_aposG, old_bposG */ ) /* MOVEBOXPTR *old_apos, *old_bpos ; */ { register BINBOXPTR *fastbin ; register x, y ; /* ----------------------------------------------------------------- Perform overlap update for OLD A - NEW B pair Recall information stored in old_apos[0] to get bounding box for this pair. */ maxXS = old_apos0G->binR ; minXS = old_apos0G->binL ; maxYS = old_apos0G->binT ; minYS = old_apos0G->binB ; for( x = minXS; x <= maxXS ; x++ ){ fastbin = binptrG[x] ; for( y = minYS; y <= maxYS ; y++ ){ bptrS = fastbin[y] ; bptrS->penalty = bptrS->nupenalty ; } } /* ----------------------------------------------------------------- Perform overlap update for OLD B - NEW A pair Recall information stored in old_bpos[0] to get bounding box for this pair. */ maxXS = old_bpos0G->binR ; minXS = old_bpos0G->binL ; maxYS = old_bpos0G->binT ; minYS = old_bpos0G->binB ; for( x = minXS; x <= maxXS ; x++ ){ fastbin = binptrG[x] ; for( y = minYS; y <= maxYS ; y++ ){ bptrS = fastbin[y] ; bptrS->penalty = bptrS->nupenalty ; } } } /* end function update_overlap */ /* ***************************************************************** Subtract penalty from bins. Takes pointer to move box record as an argument */ sub_penal( cellpos ) MOVEBOXPTR *cellpos ; { INT count, maxcount ; INT x, y ; register BINBOXPTR *fastbin ; maxcount = cellpos[0]->numtiles ; /* subtract OLD penalty */ for( count=1 ; count <= maxcount ; count++ ) { posS = cellpos[count] ; /* assign to simple variable for speed */ minXS = posS->binL ; minYS = posS->binB ; maxXS = posS->binR ; maxYS = posS->binT ; /* ----------------------------------------------------------------- Calculate penalty */ if( minXS == maxXS && minYS == maxYS ){ /* entire cell is in bin */ bptrS = binptrG[minXS][minYS] ; xcostS = posS->r - posS->l ; ycostS = posS->t - posS->b ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; } else if( minXS == maxXS ){ /* multiple y bins */ xcostS = posS->r - posS->l ; /* first bottom bin */ fastbin = binptrG[minXS] ; bptrS = fastbin[minYS] ; ycostS = bptrS->top - posS->b ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; /* next middle bins */ for( y = minYS+1; y < maxYS ; y++ ){ bptrS = fastbin[y] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= xcostS * binWidthYG ; newbinpenalS += ABS( bptrS->nupenalty ) ; } /* last top bin */ bptrS = fastbin[maxYS] ; ycostS = posS->t - bptrS->bottom ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; } else if( minYS == maxYS ){ /* multiple x bins */ ycostS = posS->t - posS->b ; /* first left bin */ bptrS = binptrG[minXS][minYS] ; xcostS = bptrS->right - posS->l ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; /* next middle bins */ for( x = minXS+1; x < maxXS ; x++ ){ bptrS = binptrG[x][minYS] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= binWidthXG * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; } /* last right bin */ bptrS = binptrG[maxXS][minYS] ; xcostS = posS->r - bptrS->left ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; } else { /* multiple rows and columns */ /* ----------------------------------------------------------------- 3 | 4 | 5 ----------------------- 2 | 9 | 6 ----------------------- 1 | 8 | 7 above is order which we check overlap in the bins */ /* first lower left bin - 1 */ fastbin = binptrG[minXS] ; bptrS = fastbin[minYS] ; xcostS = bptrS->right - posS->l ; ycostS = bptrS->top - posS->b ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; /* next left middle y bins - 2 */ for( y = minYS+1; y < maxYS ; y++ ){ bptrS = fastbin[y] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= xcostS * binWidthYG ; newbinpenalS += ABS( bptrS->nupenalty ) ; } /* next top left bin - 3 */ bptrS = fastbin[maxYS] ; ycostS = posS->t - bptrS->bottom ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; /* do top y bins - 4 */ for( x = minXS+1; x < maxXS ; x++ ){ bptrS = binptrG[x][maxYS] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= binWidthXG * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; } /* do top right bin - 5 */ fastbin = binptrG[maxXS] ; bptrS = fastbin[maxYS] ; xcostS = posS->r - bptrS->left ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; /* do middle right bins - 6 */ for( y = minYS+1; y < maxYS ; y++ ){ bptrS = fastbin[y] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= xcostS * binWidthYG ; newbinpenalS += ABS( bptrS->nupenalty ) ; } /* do lower right bin - 7 */ bptrS = fastbin[minYS] ; ycostS = bptrS->top - posS->b ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; /* do bottom x bins - 8 */ for( x = minXS+1; x < maxXS ; x++ ){ bptrS = binptrG[x][minYS] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= binWidthXG * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; } /* center middle bins - 9 */ for( x = minXS+1; x < maxXS ; x++ ){ fastbin = binptrG[x] ; for( y = minYS+1; y < maxYS ; y++ ){ bptrS = fastbin[y] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty -= binWidthXG * binWidthYG ; newbinpenalS += ABS( bptrS->nupenalty ) ; } } } } } /* end subtract penalty function */ /* ***************************************************************** Add penalty to bins. Takes pointer to move box record as an argument */ add_penal( cellpos ) MOVEBOXPTR *cellpos ; { INT count, maxcount ; INT x, y ; register BINBOXPTR *fastbin ; maxcount = cellpos[0]->numtiles ; /* add penalty */ for( count=1 ; count <= maxcount ; count++ ) { posS = cellpos[count] ; /* assign to simple variable for speed */ minXS = posS->binL ; minYS = posS->binB ; maxXS = posS->binR ; maxYS = posS->binT ; /* ----------------------------------------------------------------- Calculate penalty */ if( minXS == maxXS && minYS == maxYS ){ /* entire cell is in bin */ bptrS = binptrG[minXS][minYS] ; xcostS = posS->r - posS->l ; ycostS = posS->t - posS->b ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; } else if( minXS == maxXS ){ /* multiple y bins */ xcostS = posS->r - posS->l ; /* minXS stays the same */ fastbin = binptrG[minXS] ; /* first bottom bin */ bptrS = fastbin[minYS] ; ycostS = bptrS->top - posS->b ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; /* next middle bins */ for( y = minYS+1; y < maxYS ; y++ ){ bptrS = fastbin[y] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += xcostS * binWidthYG ; newbinpenalS += ABS( bptrS->nupenalty ) ; } /* last top bin */ bptrS = fastbin[maxYS] ; ycostS = posS->t - bptrS->bottom ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; } else if( minYS == maxYS ){ /* multiple x bins */ ycostS = posS->t - posS->b ; /* first left bin */ bptrS = binptrG[minXS][minYS] ; xcostS = bptrS->right - posS->l ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; /* next middle bins */ for( x = minXS+1; x < maxXS ; x++ ){ bptrS = binptrG[x][minYS] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += binWidthXG * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; } /* last right bin */ bptrS = binptrG[maxXS][minYS] ; xcostS = posS->r - bptrS->left ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; } else { /* multiple rows and columns */ /* ----------------------------------------------------------------- 3 | 4 | 5 ----------------------- 2 | 9 | 6 ----------------------- 1 | 8 | 7 above is order which we check overlap in the bins */ /* first lower left bin - 1 */ fastbin = binptrG[minXS] ; bptrS = fastbin[minYS] ; xcostS = bptrS->right - posS->l ; ycostS = bptrS->top - posS->b ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; /* next left middle y bins - 2 */ for( y = minYS+1; y < maxYS ; y++ ){ bptrS = fastbin[y] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += xcostS * binWidthYG ; newbinpenalS += ABS( bptrS->nupenalty ) ; } /* next top left bin - 3 */ bptrS = fastbin[maxYS] ; ycostS = posS->t - bptrS->bottom ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; /* do top y bins - 4 */ for( x = minXS+1; x < maxXS ; x++ ){ bptrS = binptrG[x][maxYS] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += binWidthXG * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; } /* do top right bin - 5 */ fastbin = binptrG[maxXS] ; bptrS = fastbin[maxYS] ; xcostS = posS->r - bptrS->left ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; /* do middle right bins - 6 */ for( y = minYS+1; y < maxYS ; y++ ){ bptrS = fastbin[y] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += xcostS * binWidthYG ; newbinpenalS += ABS( bptrS->nupenalty ) ; } /* do lower right bin - 7 */ bptrS = fastbin[minYS] ; ycostS = bptrS->top - posS->b ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += xcostS * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; /* do bottom x bins - 8 */ for( x = minXS+1; x < maxXS ; x++ ){ bptrS = binptrG[x][minYS] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += binWidthXG * ycostS ; newbinpenalS += ABS( bptrS->nupenalty ) ; } /* center middle bins - 9 */ for( x = minXS+1; x < maxXS ; x++ ){ fastbin = binptrG[x] ; for( y = minYS+1; y < maxYS ; y++ ){ bptrS = fastbin[y] ; newbinpenalS -= ABS( bptrS->nupenalty ) ; bptrS->nupenalty += binWidthXG * binWidthYG ; newbinpenalS += ABS( bptrS->nupenalty ) ; } } } } } /* end add penalty function */ /* ***************************************************************** Calculate bins for the given cell position. USES wire estimation in the calculation. Takes pointer to move box record as an argument */ INT calc_wBins( cellpos ) MOVEBOXPTR *cellpos ; { INT count ; MOVEBOXPTR pos0 ; count = 0 ; pos0 = cellpos[0] ; for(tileptrS=cellptrS->tiles;tileptrS; ) { posS = cellpos[++count] ; if(!(pos0->loaded_previously)){ /* normal case */ posS->l = tileptrS->left ; posS->r = tileptrS->right ; posS->b = tileptrS->bottom ; posS->t = tileptrS->top ; posS->lw = tileptrS->lweight ; posS->rw = tileptrS->rweight ; posS->bw = tileptrS->bweight ; posS->tw = tileptrS->tweight ; /* need to do this less than obvious update here so */ /* mismatching number of tiles in uinst don't upset code */ tileptrS=tileptrS->next ; } else { /* data for tile has already been loaded in uaspect */ /* or uinst - reset the flag */ /* in this case we don't update tileptr - just check count */ if( count >= pos0->numtiles ){ tileptrS = NULL ; /* use this to stop loop */ } } Ytranslate( &(posS->l), &(posS->b), &(posS->r), &(posS->t), orientS ); Ytranslatef( &(posS->lw),&(posS->bw),&(posS->rw),&(posS->tw),orientS ); /* then add wire estimation dynamically */ WIREESTXY(posS,xcS,ycS ) ; /* hash cell coordinates to overlap bin */ posS->binR = SETBINX( posS->r ) ; posS->binL = SETBINX( posS->l ) ; posS->binB = SETBINY( posS->b ) ; posS->binT = SETBINY( posS->t ) ; /* calculate the bounding box of the entire cell */ if( posS->binR > maxXS ){ maxXS = posS->binR ; } if( posS->binL < minXS ){ minXS = posS->binL ; } if( posS->binT > maxYS ){ maxYS = posS->binT ; } if( posS->binB < minYS ){ minYS = posS->binB ; } } /* end for loop */ /* save number of tiles for add_penal and sub_penal functions */ pos0->numtiles = count ; pos0->loaded_previously = FALSE ; } /* function calculate bins calcBins */ /* ***************************************************************** Calculate bins for the given cell posSition. DOES NOT use wire estimation in the calculation. Takes pointer to move box record as an argument */ INT calc_nBins( cellpos ) MOVEBOXPTR *cellpos ; { INT count ; MOVEBOXPTR pos0 ; count = 0 ; pos0 = cellpos[0] ; for( tileptrS = cellptrS->tiles;tileptrS; ) { posS = cellpos[++count] ; if(!(pos0->loaded_previously)){ /* normal case */ posS->l = tileptrS->left ; posS->r = tileptrS->right ; posS->b = tileptrS->bottom ; posS->t = tileptrS->top ; /* need to do this less than obvious update here so */ /* mismatching number of tiles in uinst don't upset code */ tileptrS=tileptrS->next ; } else { /* data for tile has already been loaded in uaspect */ /* or uinst - reset the flag */ /* in this case we don't update tileptr - just check count */ if( count >= pos0->numtiles ){ tileptrS = NULL ; /* use this to stop loop */ } } /* first get orientation from translate */ Ytranslate( &(posS->l), &(posS->b), &(posS->r), &(posS->t), orientS ); posS->l += xcS ; posS->r += xcS ; posS->b += ycS ; posS->t += ycS ; /* hash cell coordinates to overlap bin */ posS->binR = SETBINX( posS->r ) ; posS->binL = SETBINX( posS->l ) ; posS->binB = SETBINY( posS->b ) ; posS->binT = SETBINY( posS->t ) ; /* calculate the bounding box of the entire cell */ if( posS->binR > maxXS ){ maxXS = posS->binR ; } if( posS->binL < minXS ){ minXS = posS->binL ; } if( posS->binT > maxYS ){ maxYS = posS->binT ; } if( posS->binB < minYS ){ minYS = posS->binB ; } } /* end for loop */ /* save number of tiles for add_penal and sub_penal functions */ pos0->numtiles = count ; pos0->loaded_previously = FALSE ; } /* function calculate bins calcBins */ /* ***************************************************************** Turn wire estimation on. This is a toggle between the calc_wBins routine and calc_nBins routine. In this case, the calc_Bins routine is set to calc_wBins. */ turn_wireest_on( turn_on ) INT turn_on ; { if( turn_on ){ calc_Bins = calc_wBins ; if( new_wire_estG ){ wire_est = wireestxy2 ; } else { wire_est = wireestxy ; } } else { calc_Bins = calc_nBins ; } } /* end funtion turn_wireest_on */ /* ***************************************************************** Set up variables for calculating bins. This routine will avoid the use of many global variables. This routines sets up static variables in this file. */ setup_Bins( s_cellptr, s_xc, s_yc, s_orient ) CELLBOXPTR s_cellptr ; INT s_xc ; INT s_yc ; INT s_orient ; { cellptrS = s_cellptr ; xcS = s_xc ; ycS = s_yc ; orientS = s_orient ; } /* end function setup bins */ /* ***************************************************************** add2bin adds to initialized bins the overlap of the given cell. It is assumed that setup bins was immediately called before call to this routine. */ add2bin( cellpos ) MOVEBOXPTR *cellpos ; { INT count, maxcount ; INT x, y ; register BINBOXPTR *fastbin ; /* first get bin limits for tiles of this cell */ calcBins( cellpos ) ; maxcount = cellptrS->numtiles ; ASSERT( maxcount == cellpos[0]->numtiles, "add2bin", "Tile problem" ) ; /* add penalty */ for( count=1 ; count <= maxcount ; count++ ) { posS = cellpos[count] ; /* assign to simple variable for speed */ minXS = posS->binL ; minYS = posS->binB ; maxXS = posS->binR ; maxYS = posS->binT ; /* ----------------------------------------------------------------- Calculate penalty */ if( minXS == maxXS && minYS == maxYS ){ /* entire cell is in bin */ bptrS = binptrG[minXS][minYS] ; xcostS = posS->r - posS->l ; ycostS = posS->t - posS->b ; bptrS->penalty += xcostS * ycostS ; } else if( minXS == maxXS ){ /* multiple y bins */ xcostS = posS->r - posS->l ; /* first bottom bin */ fastbin = binptrG[minXS] ; bptrS = fastbin[minYS] ; ycostS = bptrS->top - posS->b ; bptrS->penalty += xcostS * ycostS ; /* next middle bins */ for( y = minYS+1; y < maxYS ; y++ ){ bptrS = fastbin[y] ; bptrS->penalty += xcostS * binWidthYG ; } /* last top bin */ bptrS = fastbin[maxYS] ; ycostS = posS->t - bptrS->bottom ; bptrS->penalty += xcostS * ycostS ; } else if( minYS == maxYS ){ /* multiple x bins */ ycostS = posS->t - posS->b ; /* first left bin */ bptrS = binptrG[minXS][minYS] ; xcostS = bptrS->right - posS->l ; bptrS->penalty += xcostS * ycostS ; /* next middle bins */ for( x = minXS+1; x < maxXS ; x++ ){ bptrS = binptrG[x][minYS] ; bptrS->penalty += binWidthXG * ycostS ; } /* last right bin */ bptrS = binptrG[maxXS][minYS] ; xcostS = posS->r - bptrS->left ; bptrS->penalty += xcostS * ycostS ; } else { /* multiple rows and columns */ /* ----------------------------------------------------------------- 3 | 4 | 5 ----------------------- 2 | 9 | 6 ----------------------- 1 | 8 | 7 above is order which we check overlap in the bins */ /* first lower left bin - 1 */ fastbin = binptrG[minXS] ; bptrS = fastbin[minYS] ; xcostS = bptrS->right - posS->l ; ycostS = bptrS->top - posS->b ; bptrS->penalty += xcostS * ycostS ; /* next left middle y bins - 2 */ for( y = minYS+1; y < maxYS ; y++ ){ bptrS = fastbin[y] ; bptrS->penalty += xcostS * binWidthYG ; } /* next top left bin - 3 */ bptrS = fastbin[maxYS] ; ycostS = posS->t - bptrS->bottom ; bptrS->penalty += xcostS * ycostS ; /* do top y bins - 4 */ for( x = minXS+1; x < maxXS ; x++ ){ bptrS = binptrG[x][maxYS] ; bptrS->penalty += binWidthXG * ycostS ; } /* do top right bin - 5 */ fastbin = binptrG[maxXS] ; bptrS = fastbin[maxYS] ; xcostS = posS->r - bptrS->left ; bptrS->penalty += xcostS * ycostS ; /* do middle right bins - 6 */ for( y = minYS+1; y < maxYS ; y++ ){ bptrS = fastbin[y] ; bptrS->penalty += xcostS * binWidthYG ; } /* do lower right bin - 7 */ bptrS = fastbin[minYS] ; ycostS = bptrS->top - posS->b ; bptrS->penalty += xcostS * ycostS ; /* do bottom x bins - 8 */ bptrS = binptrG[minXS][minYS] ; for( x = minXS+1; x < maxXS ; x++ ){ bptrS = binptrG[x][minYS] ; bptrS->penalty += binWidthXG * ycostS ; } /* center middle bins - 9 */ for( x = minXS+1; x < maxXS ; x++ ){ fastbin = binptrG[x] ; for( y = minYS+1; y < maxYS ; y++ ){ bptrS = fastbin[y] ; bptrS->penalty += binWidthXG * binWidthYG ; } } } } /* end for loop */ } /* end add2bin function */ graywolf-0.1.4+20170307gite1bf319/src/twmc/pads.h000066400000000000000000000014301305746555600206230ustar00rootroot00000000000000/* ***************************************************************** static char SccsId[] = "@(#) pads.h version 3.6 2/23/91" ; ***************************************************************** */ #ifndef PADS_H #define PADS_H /* control for pad spacing */ #define UNIFORM_PADS 0 #define VARIABLE_PADS 1 #define ABUT_PADS 2 #define EXACT_PADS 3 /* pad sides */ #define ALL 0 #define L 1 #define T 2 #define R 3 #define B 4 #define MINI 0 #define MAXI 1 #define X 0 #define Y 1 #define HOWMANY 0 #define LARGE 100000 #define PINFINITY INT_MAX / 8 #define PICK_INT(l,u) (((l)<(u)) ? ((RAND % ((u)-(l)+1))+(l)) : (l)) /* pad hierarchy */ #define NONE 0 #define LEAF 1 #define SUBROOT 2 #define ROOT 3 #endif /* PADS_H */ graywolf-0.1.4+20170307gite1bf319/src/twmc/partition.c000066400000000000000000000352571305746555600217160ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * Copyright (C) 2013 Tim Edwards * Copyright (C) 2014 Ruben Undheim * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: partition.c DESCRIPTION:code to support standard cell partitioner. CONTENTS: DATE: Apr 9, 1989 REVISIONS: May 24, 1989 - added stdcell configuration code. Jun 21, 1989 - modified final_conf and output partition to handle equiv pins correctly. Jun 23, 1989 - added reset cell function and added reconfig capability. Aug 20, 1989 - moved standard cell calculation to child program genrows. Sep 16, 1989 - fixed problem with unbust. Multiple tile cells should use tile count as argument since tiles need to be seamed together. Nov 4, 1989 - now read block file created by genrows in order to update the size of the core. Apr 23, 1990 - modified instance record. May 15, 1990 - changed .mstat parser. Sun Dec 16 00:32:16 EST 1990 - use the library version of buster. Fri Jan 18 18:29:54 PST 1991 - now use conservative approach to building .scel. Wed Jan 30 14:13:36 EST 1991 - now left justify orientation rotations. Sat Feb 23 00:28:28 EST 1991 - now handle wildcarding for reading and updated for TOMUS. Thu Apr 18 01:39:27 EDT 1991 - now allow genrows to orient macros. Wed May 1 19:22:03 EDT 1991 - MC now always call genrows during partitioning. Wed Jun 5 16:30:30 CDT 1991 - eliminated unbust. Mon Aug 5 18:06:17 CDT 1991 - eliminated special partitioning case. Fri Oct 18 00:09:45 EDT 1991 - eliminated read_blk_file. Instead, to find core we read it using read_gen_file. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) partition.c version 3.20 4/6/92" ; #endif #include #include #include #include #include #include #include #include #include #include "config-build.h" #define ROWSEP "rowSep" #define GENROWPROG "genrows" #define GENROWPATH "../genrows" #define NUMROWKEYWORD "rows" #define ROWKEYWORD "row" static INT tlengthS ; /* total length of stdcells */ static INT cheightS ; /* height of stdcell */ static INT num_classeS ; /* number of cell classes */ static INT *classS ; /* cell class name */ static INT *lbS ; /* lower bound of cell class length */ static INT *ubS ; /* upper bound of cell class length */ static DOUBLE rowSepS ; /* row separation, relative */ static DOUBLE rowSepAbsS ; /* row separation, absolute */ static BOOL dataValidS = FALSE ; /* used to avoid invalid request */ static INT num_macroS ; /* number of macros output */ /* Forward declaration */ extern INT closegraphics(); config_rows() { DOUBLE read_par_file() ; /* get default from user */ INT left, right, bottom, top;/* core area */ char *Yrelpath() ; char *pathname ; char *twdir ; /* path of TimberWolf directory */ char *getenv() ; /* used to get TWDIR environment variable */ char filename[LRECL] ; BOOL stateSaved = FALSE ; /* whether need to restore state */ BOOL get_batch_mode() ; /* find out whether we are in batch mode */ read_stat_file() ; (void) read_par_file() ; grid_cells() ; /* place the pads to get standard cell core area */ find_core_boundary( &left, &right, &bottom, &top ) ; build_mver_file( left, right, bottom, top ) ; /* now call genrows program */ /* find the path of genrows relative to main program */ pathname = Yrelpath( argv0G, GENROWPATH ) ; if( !(YfileExists(pathname))){ if( twdir = TWFLOWDIR ){ sprintf( filename, "%s/bin/%s", twdir, GENROWPROG ) ; pathname = Ystrclone( filename ) ; } } if( doGraphicsG ){ G( sprintf( YmsgG, "%s -w %s %lu", pathname, cktNameG, (unsigned long)TWsaveState() ) ) ; stateSaved = TRUE ; } else if( get_batch_mode() ){ sprintf( YmsgG, "%s %s", pathname, cktNameG ) ; } else { /* no graphics case */ sprintf( YmsgG, "%s -n %s", pathname, cktNameG ) ; } M( MSG, NULL, YmsgG ) ; M( MSG, NULL, "\n" ) ; /* Ysystem will kill program if catastrophe occurred */ Ysystem( GENROWPROG, ABORT, YmsgG, closegraphics ) ; Ysafe_free( pathname ) ; /* free name created in Yrelpath */ /* ############# end of genrows execution ############# */ if( stateSaved ){ /* if we save the graphics state we need to restore it */ G( TWrestoreState() ) ; } /* read result to update new core */ read_gen_file() ; /* add spacing between pads and core area. */ #ifdef LATER cellarrayG[endpadgrpsG+L]->tiles->rborder = numpadsG*track_spacingXG ; cellarrayG[endpadgrpsG+R]->tiles->lborder = numpadsG*track_spacingXG ; cellarrayG[endpadgrpsG+B]->tiles->tborder = numpadsG*track_spacingYG ; cellarrayG[endpadgrpsG+T]->tiles->bborder = numpadsG*track_spacingYG ; #endif /* read back result */ setVirtualCore( TRUE ) ; placepads() ; } /* end config_rows */ read_stat_file() { char filename[LRECL] ; char input[LRECL] ; char *bufferptr ; char **tokens ; INT class ; INT numtokens ; INT class_count ; FILE *fin ; /*********************************************************** * Read from circuitName.stat file. ***********************************************************/ sprintf( filename, "%s.stat", cktNameG ) ; fin = TWOPEN(filename,"r", ABORT ) ; class_count = 0 ; num_classeS = 0 ; while( bufferptr = fgets( input, LRECL, fin ) ){ tokens = Ystrparser( bufferptr, " :\t\n", &numtokens ) ; if( strcmp( tokens[0], "tot_length" ) == STRINGEQ ){ tlengthS = atoi( tokens[1] ) ; } else if( strcmp( tokens[0], "cell_height" ) == STRINGEQ ){ cheightS = atoi( tokens[1] ) ; } else if( strcmp( tokens[0], "num_classes" ) == STRINGEQ ){ num_classeS = atoi( tokens[1] ) ; classS = YVECTOR_MALLOC( 1, num_classeS, INT ) ; lbS = YVECTOR_MALLOC( 1, num_classeS, INT ) ; ubS = YVECTOR_MALLOC( 1, num_classeS, INT ) ; } else if( strcmp( tokens[0], "class" ) == STRINGEQ ){ class = atoi( tokens[1] ) ; classS[++class_count] = class ; lbS[class_count] = atoi( tokens[3] ) ; ubS[class_count] = atoi( tokens[5] ) ; } } TWCLOSE( fin ) ; } /* end read_stat_file */ DOUBLE read_par_file() { char *bufferptr ; char **tokens ; /* for parsing menu file */ INT numtokens ; INT line ; /* line number of TWmenu file */ BOOL onNotOff ; BOOL wildcard ; Yreadpar_init( cktNameG, USER, TWSC, TRUE ) ; while( tokens = Yreadpar_next( &bufferptr, &line, &numtokens, &onNotOff, &wildcard )){ if( numtokens == 0 ){ /* skip over empty lines */ continue ; } if( numtokens != 2 && numtokens != 3 ){ continue ; } if( strcmp( tokens[0], ROWSEP ) == STRINGEQ){ /* there better be only two or three tokens on this line */ /* 3rd token for absolute row spacing is not handled */ if( numtokens == 2 ){ rowSepS = atof( tokens[1] ) ; } else if (numtokens == 3 ){ rowSepS = atof( tokens[1] ) ; rowSepAbsS = atof( tokens[2] ) ; } else { sprintf( YmsgG, "Syntax error on line:%d\n", line ) ; M(ERRMSG, "read_par_file", YmsgG ) ; } } } if( rowSepS < 0.0 ) { M(ERRMSG,"read_par_file","Improper row separation.\n" ) ; M(MSG,NULL,"Row separaion should be specified in .par file\n" ) ; M(MSG,NULL,"Defaulting to 1.0\n" ) ; rowSepS = 1.0 ; rowSepAbsS = 0.0 ; } return( rowSepS ) ; } /* end read_par_file */ output_partition() { #define RELATIVE_TO_CURPOS 1 INT i ; long delta ; /* how far to jump backwards */ INT error ; /* error code returned from fseek */ INT x, y ; /* pin positions */ INT xc, yc ; /* cell center */ INT instance ; /* current cell instance */ INT line ; /* current line number */ BOOL found ; /* find mc keywords */ FILE *fp ; char filename[LRECL] ; char buffer[LRECL] ; char *bufferptr ; char *matchptr ; PINBOXPTR pin ; CELLBOXPTR cptr ; /* **************************************************************** Output the ports into sc cell file. ***************************************************************** */ /* other definitions for the apollo version */ char filename_out[LRECL] ; FILE *fout ; sprintf( filename, "%s.scel", cktNameG ) ; fp = TWOPEN( filename, "r", ABORT ) ; sprintf( filename_out, "%s.temp", cktNameG ) ; fout = TWOPEN( filename_out, "w", ABORT ) ; /* start at beginning of file and read till read mc entity or pad */ line = 0 ; while( bufferptr = fgets( buffer, LRECL, fp )){ /* remove leading blanks or tabs */ matchptr = Yremove_lblanks( bufferptr ) ; if( strncmp( matchptr, "hardcell", 8 ) == STRINGEQ ){ break ; } else if( strncmp( matchptr, "softcell", 8 ) == STRINGEQ ){ break ; } else if( strncmp( matchptr, "pad", 3 ) == STRINGEQ ){ break ; } else { /* do an echo */ line++ ; fprintf( fout, "%s", bufferptr ) ; } } D( "output_partition", fprintf( stderr, "broke on line:%d\n", line ) ; ) ; /* send the rest of the macro output of .mdat to fout */ output( fout ) ; TWCLOSE( fp ) ; Yrm_files( filename ) ; /* move the new file to .scel due to a bug in fseek on the apollo */ YmoveFile( filename_out, filename ) ; } /* end of prnt_data */ build_mver_file( left, right, bottom, top ) INT left, right, bottom, top ; { CELLBOXPTR cellptr ; FILE *fp ; char filename[LRECL] ; INT type ; INT i, k, cell ; INT xc, yc ; INT x, y ; INT separation ; BOUNBOXPTR bounptr ; /* bounding box pointer */ /* ######### Create genrows file and exec genrows ######### */ /* open vertex file for writing */ sprintf(filename, "%s.mver" , cktNameG ) ; fp = TWOPEN( filename , "w", ABORT ) ; fprintf( fp, "total_row_length %d\n", tlengthS ) ; if( num_classeS ){ fprintf( fp, "num_classes %d\n", num_classeS ) ; } for( i = 1 ; i <= num_classeS ; i++ ){ fprintf( fp, "class %d lb %d ub %d\n", classS[i], lbS[i], ubS[i] ) ; } fprintf( fp, "actual_row_height %d\n", cheightS ) ; separation = (INT) ( (DOUBLE) cheightS * rowSepS + rowSepAbsS) ; fprintf( fp, "channel_separation %d\n", separation ) ; fprintf( fp, "min_length %d\n", (right-left) / 5 ) ; fprintf( fp, "core %d %d %d %d\n", left, bottom, right, top ) ; fprintf( fp, "grid %d %d\n", track_spacingXG, track_spacingYG ) ; num_macroS = 0 ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = cellarrayG[cell] ; type = cellptr->celltype ; if( type != CUSTOMCELLTYPE && type != SOFTCELLTYPE ){ continue ; } num_macroS++ ; } fprintf( fp, "num_macro %d\n", num_macroS ) ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = cellarrayG[cell] ; type = cellptr->celltype ; if( type != CUSTOMCELLTYPE && type != SOFTCELLTYPE ){ continue ; } fprintf(fp,"macro orient %d %d vertices ", cellptr->orient, cellptr->numsides ) ; output_vertices( fp, cellptr ) ; } TWCLOSE( fp ) ; } /* end build_mver_file */ read_gen_file() { char filename[LRECL] ; char buffer[LRECL], *bufferptr ; char **tokens ; /* for parsing file */ INT numtokens, line ; INT cell ; /* current cell number */ INT type ; /* current cell type */ CELLBOXPTR cellptr ; /* current cell */ BOOL abort ; /* whether to abort program */ FILE *fp ; if( num_macroS == 0 ){ return ; } /* **************** READ RESULTS of genrows ************/ sprintf(filename, "%s.gen" , cktNameG ) ; fp = TWOPEN( filename , "r", ABORT ) ; /* parse file */ line = 0 ; abort = FALSE ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = cellarrayG[cell] ; type = cellptr->celltype ; if( type != CUSTOMCELLTYPE && type != SOFTCELLTYPE ){ continue ; } while( bufferptr=fgets(buffer,LRECL,fp )){ /* parse file */ line++ ; /* increment line number */ tokens = Ystrparser( bufferptr, " \t\n", &numtokens ); if( numtokens == 0 ){ /* skip over empty lines */ continue ; } else if( numtokens == 3 ){ cellptr->xcenter = atoi( tokens[0] ) ; cellptr->ycenter = atoi( tokens[1] ) ; cellptr->orient = atoi( tokens[2] ) ; break ; /* go on to the next cell */ } else if( strcmp(tokens[0], "core" ) == STRINGEQ && numtokens == 5 ){ blocklG = MIN( blocklG, atoi( tokens[1] ) ) ; blockbG = MIN( blockbG, atoi( tokens[2] ) ) ; blockrG = MAX( blockrG, atoi( tokens[3] ) ) ; blocktG = MAX( blocktG, atoi( tokens[4] ) ) ; } else { sprintf( YmsgG, "Problem reading .gen file on line:%d\n",line ) ; M( ERRMSG, "read_gen_file", YmsgG ) ; abort = TRUE ; } } } TWCLOSE( fp ) ; if( abort ){ M(ERRMSG, "read_gen_file", "Problem with genrows. Must abort\n" ) ; closegraphics() ; YexitPgm( PGMFAIL ) ; } /* ************ END READ RESULTS of genrows ************/ } /* end read_gen_file() */ graywolf-0.1.4+20170307gite1bf319/src/twmc/partition.h000066400000000000000000000015621305746555600217130ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) partition.h (Yale) version 3.3 9/5/90" FILE: partition.h DESCRIPTION:insert file to support standard cell partitioner. CONTENTS: DATE: May 17, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef PARTITION_H #define PARTITION_H #define INITROWSEP 1.0 #define EVEN_ODD( x ) ( (x) & 01 ) #define EVEN 0 typedef struct d_field { INT x_lb ; INT x_ub ; INT cell ; struct d_field *prev ; struct d_field *next ; } DFLD, *DFLDPTR ; typedef struct b_record { SHORT state ; SHORT number ; INT length ; INT x_lb ; INT x_ub ; INT y_lb ; INT y_ub ; struct d_field *macro ; } BLOCK, *BLOCKPTR ; #endif /* PARTITION_H */ graywolf-0.1.4+20170307gite1bf319/src/twmc/paths.c000066400000000000000000000570361305746555600210230ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: paths.c DESCRIPTION:output length of paths CONTENTS: print_paths. INT calc_incr_time( cell ) INT cell ; update_time( cell ) INT cell ; INT calc_incr_time2( cella, cellb ) INT cella, cellb ; update_time2( cella, cellb ) INT cella, cellb ; init_path_set() add2path_set( path ) INT path ; PSETPTR enum_path_set() clear_path_set() init_net_set() add2net_set( net ) INT net ; BOOL member_net_set( net ) clear_net_set() INT dcalc_full_penalty() INT dcalc_path_len(path_num) INT path_num ; DATE: Oct 22, 1988 REVISIONS: Dec 3, 1988 - completed timing driven code. Jan 29, 1989 - added \n's for pretty output. Mar 11, 1989 - added statistics to print_paths. - added wirelength to print_paths. Mar 13, 1989 - now output penalty in print_paths. Fri Jan 18 18:32:01 PST 1991 - updated output format. Sun Jan 20 21:34:36 PST 1991 - ported to AIX. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) paths.c version 3.9 4/21/91" ; #endif #include #include #include #include /* Forward declarations */ INT dcalc_min_path_len(); INT dcalc_max_path_len(); print_paths( ) { char filename[LRECL] ; PATHPTR pptr, get_path_list() ; GLISTPTR net ; NETBOXPTR nptr ; PINBOXPTR netptr ; FILE *fp ; DOUBLE mean ; DOUBLE paths ; BOOL pad ; INT *stat ; INT num_paths ; INT length ; INT pathLength ; INT loLength ; INT hiLength ; INT i = 0 ; INT xspan ; INT yspan ; INT in = 0 ; INT above = 0 ; INT below = 0 ; INT penalty = 0 ; INT way_above = 0 ; INT way_below = 0 ; INT really_above = 0 ; INT really_below = 0 ; INT really_way_above = 0 ; INT really_way_below = 0 ; /* get total number of paths in timing analysis */ num_paths = get_total_paths() ; /* allocate the an array for calculating statistics */ if( num_paths ){ stat = (INT *) Ysafe_malloc( num_paths * sizeof(INT) ) ; } sprintf(filename, "%s.mpth" , cktNameG ) ; fp = TWOPEN( filename , "w", ABORT ) ; /* first the lengths of the nets */ fprintf( fp, "The paths:\n" ) ; fprintf( fp, "##############################################\n" ) ; for( pptr=get_path_list() ;pptr;pptr=pptr->next ){ pathLength = 0 ; loLength = 0 ; hiLength = 0 ; xspan = 0 ; yspan = 0 ; /* get pathLength for path */ fprintf( fp, "path %3d:\n",++i ) ; for( net = pptr->nets ; net ; net = net->next ){ nptr = netarrayG[net->p.net] ; fprintf( fp, "\t\t%s\n", nptr->nname ) ; length = nptr->halfPx + (INT)(vertical_path_weightG * (DOUBLE) nptr->halfPy) ; xspan += nptr->halfPx ; yspan += nptr->halfPy ; pathLength += length ; loLength = loLength + (INT) (nptr->max_driver * (FLOAT)length + nptr->driveFactor); hiLength = hiLength + (INT) (nptr->min_driver * (FLOAT)length + nptr->driveFactor); } fprintf( fp, "\tpriority:%d lower bound:%d upper bound:%d\n", pptr->priority, pptr->lower_bound, pptr->upper_bound ) ; fprintf( fp,"\tweighted length:%d fast driver len:%d slow driver len:%d\n", pathLength, loLength, hiLength ) ; fprintf( fp, "\txspan:%d yspan:%d length:%d\n", xspan, yspan, xspan+yspan ) ; if( pptr->priority ){ ASSERT( loLength == pptr->lo_path_len,"print_paths", "lo_pathLength does not equal incremental value " ) ; ASSERT( hiLength == pptr->hi_path_len,"print_paths", "hi_pathLength does not equal incremental value " ) ; } if( loLength < pptr->lower_bound ){ penalty += pptr->lower_bound - loLength ; /* look for paths with some slack on bound */ if( loLength < (INT)( 0.90 * (DOUBLE) pptr->lower_bound) ){ below++ ; /* check if this path has a net with a pad in it */ pad = FALSE ; for( net = pptr->nets ; net ; net = net->next ){ netptr = netarrayG[net->p.net]->pins ; for( ; netptr ; netptr = netptr->next ) { if( netptr->cell > numcellsG ) { pad = TRUE ; break ; } } } if( !pad ) { really_below++ ; } } if( loLength < (INT)( 0.80 * (DOUBLE) pptr->lower_bound) ){ way_below++ ; if( !pad ) { really_way_below++ ; } } } else if( hiLength > pptr->upper_bound ){ penalty += hiLength - pptr->upper_bound ; if( hiLength > (INT)( 1.10 * (DOUBLE) pptr->upper_bound) ){ above++ ; pad = FALSE ; for( net = pptr->nets ; net ; net = net->next ){ netptr = netarrayG[net->p.net]->pins ; for( ; netptr ; netptr = netptr->next ) { if( netptr->cell > numcellsG ) { pad = TRUE ; break ; } } } if( !pad ) { really_above++ ; } } if( hiLength > (INT)( 1.20 * (DOUBLE) pptr->upper_bound) ){ way_above++ ; if( !pad ) { really_way_above++ ; } } } else { in++ ; } /* add pathlength to stat array */ stat[i-1] = pathLength ; } /* first the lengths of the nets */ fprintf( fp, "\nThe nets:\n" ) ; fprintf( fp, "##############################################\n" ) ; for( i=1;i<=numnetsG;i++ ){ nptr = netarrayG[i] ; fprintf( fp, "net %3d:%s xspan:%d yspan:%d length:%d numpins:%d\n", i, nptr->nname, nptr->halfPx, nptr->halfPy, nptr->halfPx + nptr->halfPy, nptr->numpins ) ; } /* avoid a divide by zero */ if( num_paths ){ paths = (DOUBLE) num_paths ; fprintf( fp, "\nSummary:\n" ) ; fprintf( fp, "Total wirelength :%5d\n", funccostG ) ; fprintf( fp, "Total time penalty :%5d\n", penalty ) ; fprintf( fp, "Number of paths :%5d\n", num_paths ) ; fprintf( fp, "Number of active paths :%5d\n", numpathsG ) ; fprintf( fp, "Number of paths 10%% below spec :%5d - %4.2f%%\n", below, 100.0 * (DOUBLE) below / paths ) ; fprintf( fp, "Number of paths 10%% above spec :%5d - %4.2f%%\n", above, 100.0 * (DOUBLE) above / paths ) ; fprintf( fp, "Number of paths within spec :%5d - %4.2f%%\n", in, 100.0 * (DOUBLE) in / paths ) ; fprintf( fp, "# of non-pad paths out of spec :%5d\n", really_above + really_below ) ; fprintf( fp, "Number of paths 20%% below spec :%5d - %4.2f%%\n", way_below, 100.0 * (DOUBLE) way_below / paths ) ; fprintf( fp, "Number of paths 20%% above spec :%5d - %4.2f%%\n", way_above, 100.0 * (DOUBLE) way_above / paths ) ; fprintf( fp, "# of non-pad paths out of spec :%5d\n", really_way_above + really_way_below ) ; fprintf( fp, "Min length :%4.2le\n", Ystat_min( stat, num_paths, sizeof(INT) ) ) ; fprintf( fp, "Max length :%4.2le\n", Ystat_max( stat, num_paths, sizeof(INT) ) ) ; mean = Ystat_mean( stat, num_paths, sizeof(INT) ) ; fprintf( fp, "Mean length :%4.2le\n", mean ) ; fprintf( fp, "Standard Dev. length :%4.2le\n", sqrt( Ystat_var( stat, num_paths, sizeof(INT),mean) ) ) ; Ysafe_free( stat ) ; } TWCLOSE( fp ) ; } /* end print_paths */ /* ----------------------------------------------------------------- The update path routines The incremental routines speed execution by looking at only those paths connected to the cells that are to be moved. In addition, only those nets which are modified by the move are updated. This gives us an incremental length which we add to old half perimeter to give us total lenght of this net. The penalty is based on this length. We calculate an incremental penalty based on the change in the penalty. ----------------------------------------------------------------- */ /* calculate the timing cost incrementally */ INT calc_incr_time( cell ) INT cell ; { INT newpenal ; /* proposed move's timing penalty delta */ INT oldpenal ; /* the old penalty of the nets that move */ INT length ; /* path length incremental */ INT loLength ; /* lo path length incremental */ INT hiLength ; /* hi path length incremental */ INT path_num ; /* name of path */ INT net ; /* net of path */ GLISTPTR pptr ; /* pointer to paths of a cell */ GLISTPTR net_of_path ; PATHPTR path ; NETBOXPTR dimptr ; newpenal = 0 ; oldpenal = 0 ; /* for all paths of the cell that has moved */ for( pptr = cellarrayG[cell]->paths; pptr ; pptr = pptr->next ) { path_num = pptr->p.path ; ASSERTNCONT( path_num > 0 && path_num <= numpathsG, "calc_incr_time", "path is out of bounds" ) ; path = patharrayG[path_num] ; /* for all nets k of a path i */ loLength = 0 ; hiLength = 0 ; for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ if( member_net_set( net ) ){ /* this half - perimeter has changed use update */ /* calculate total change on path */ length = ( dimptr->newhalfPx - dimptr->halfPx + (INT)(vertical_path_weightG * (DOUBLE)dimptr->newhalfPy) - (INT)(vertical_path_weightG * (DOUBLE)dimptr->halfPy) ); loLength = loLength + (INT) (dimptr->max_driver * (FLOAT) length + dimptr->driveFactor ) ; hiLength = hiLength + (INT) (dimptr->min_driver * (FLOAT) length + dimptr->driveFactor ) ; } /* else this half - perimeter has not changed use old */ } /* save total result - change to total length */ path->new_lo_path_len = loLength += path->lo_path_len ; path->new_hi_path_len = hiLength += path->hi_path_len ; ASSERT( loLength == dcalc_min_path_len(path_num), NULL, NULL ) ; ASSERT( hiLength == dcalc_max_path_len(path_num), NULL, NULL ) ; /* calculate change in timing penalty */ /* no penalty if within target window */ /* lowerbound <= length <= upperbound */ if( hiLength > path->upper_bound ){ newpenal += hiLength - path->upper_bound ; } else if( loLength < path->lower_bound ){ newpenal += path->lower_bound - loLength ; } /* now the old penalty */ if( path->hi_path_len > path->upper_bound ){ oldpenal += path->hi_path_len - path->upper_bound ; } else if( path->lo_path_len < path->lower_bound ){ oldpenal += path->lower_bound - path->lo_path_len ; } } /* return the change in penalty */ return( newpenal - oldpenal ) ; } /* end function calc_incr_time */ update_time( cell ) INT cell ; { INT path_num ; /* name of path */ GLISTPTR pptr ; /* pointer to paths of a cell */ PATHPTR path ; /* for all paths of the cell that has moved */ for( pptr = cellarrayG[cell]->paths; pptr ; pptr = pptr->next ) { path_num = pptr->p.path ; ASSERTNCONT( path_num > 0 && path_num <= numpathsG, "update_time", "path is out of bounds" ) ; path = patharrayG[path_num] ; /* keep result */ path->lo_path_len = path->new_lo_path_len ; path->hi_path_len = path->new_hi_path_len ; } } /* end function update_time */ /* calculate the timing cost incrementally for two cells */ INT calc_incr_time2( cella, cellb ) INT cella ; INT cellb ; { INT newpenal ; /* proposed move's timing penalty delta */ INT oldpenal ; /* the old penalty of the nets that move */ INT length ; /* incremental path length */ INT loLength ; /* lo path length incremental */ INT hiLength ; /* hi path length incremental */ INT path_num ; /* name of path */ INT net ; /* net of path */ GLISTPTR pptr ; /* pointer to paths of a cell */ GLISTPTR net_of_path ; PATHPTR path ; PSETPTR pathlist, enum_path_set() ; NETBOXPTR dimptr ; newpenal = 0 ; oldpenal = 0 ; clear_path_set() ; /* use add2path_set to get union of paths from cella and cellb */ for( pptr = cellarrayG[cella]->paths; pptr ; pptr = pptr->next ) { add2path_set( pptr->p.path ) ; } for( pptr = cellarrayG[cellb]->paths; pptr ; pptr = pptr->next ) { add2path_set( pptr->p.path ) ; } /* now use UNIQUE list of the union of the two cell's paths */ for( pathlist=enum_path_set(); pathlist; pathlist=pathlist->next){ path_num = pathlist->path ; ASSERTNCONT( path_num > 0 && path_num <= numpathsG, "calc_incr_time2", "path is out of bounds" ) ; path = patharrayG[path_num] ; /* for all nets k of a path i */ loLength = 0 ; hiLength = 0 ; for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ if( member_net_set( net ) ){ /* this half - perimeter has changed use update */ /* calculate total change on path */ length = ( dimptr->newhalfPx - dimptr->halfPx + (INT)(vertical_path_weightG * (DOUBLE)dimptr->newhalfPy) - (INT)(vertical_path_weightG * (DOUBLE)dimptr->halfPy) ); loLength = loLength + (INT) (dimptr->max_driver * (FLOAT) length + dimptr->driveFactor ) ; hiLength = hiLength + (INT) (dimptr->min_driver * (FLOAT) length + dimptr->driveFactor ) ; } /* else this half - perimeter has not changed use old */ } /* save total result - change to total length */ path->new_lo_path_len = loLength += path->lo_path_len ; path->new_hi_path_len = hiLength += path->hi_path_len ; ASSERT( loLength == dcalc_min_path_len(path_num), NULL, NULL ) ; ASSERT( hiLength == dcalc_max_path_len(path_num), NULL, NULL ) ; /* calculate change in timing penalty */ /* no penalty if within target window */ /* lowerbound <= length <= upperbound */ if( hiLength > path->upper_bound ){ newpenal += hiLength - path->upper_bound ; } else if( loLength < path->lower_bound ){ newpenal += path->lower_bound - loLength ; } /* now the old penalty */ if( path->hi_path_len > path->upper_bound ){ oldpenal += path->hi_path_len - path->upper_bound ; } else if( path->lo_path_len < path->lower_bound ){ oldpenal += path->lower_bound - path->lo_path_len ; } } /* return the change in penalty */ return( newpenal - oldpenal ) ; } /* end function calc_incr_time2 */ update_time2( cella, cellb ) INT cella, cellb ; { INT path_num ; /* name of path */ PATHPTR path ; PSETPTR pathlist, enum_path_set() ; /* now use UNIQUE list of the union of the two cell's paths */ for( pathlist=enum_path_set(); pathlist; pathlist=pathlist->next){ DS( path_num = pathlist->path ; ) ; ASSERTNCONT( path_num > 0 && path_num <= numpathsG, "update_time2", "path is out of bounds" ) ; path = patharrayG[pathlist->path] ; /* keep result */ path->lo_path_len = path->new_lo_path_len ; path->hi_path_len = path->new_hi_path_len ; } } /* end function update_time */ /* ----------------------------------------------------------------- The set required in the update path routines needs the following operations done efficiently : membership - O(1) add to set if unique - O(1) clear set - O(1) set enumeration - O( paths in set ) Below is a space hungry O( numpaths ) but time efficient implementation We combine two data structures to accomplish this goal. We use array for testing membership and uniqueness but use list for enumeration. By incrementing count we can reinitialize easily. Note: PSETBOX, PSETPTR definitions are in custom.h ----------------------------------------------------------------- */ static PSETPTR path_set_listS ; /* list is beginning of set as a list */ static PSETPTR *path_set_arrayS ; /* set is an array of path set boxes */ static INT path_set_countS ; /* current set count */ /* initialize set */ init_path_set() { INT i ; path_set_arrayS=(PSETPTR *)Ysafe_malloc((numpathsG+1)*sizeof(PSETPTR)); for( i=0;i<=numpathsG;i++ ){ path_set_arrayS[i] = (PSETPTR) Ysafe_calloc( 1, sizeof(PSETBOX) ) ; } path_set_countS = 1 ; path_set_listS = NULL ; } /* end initset */ /* add a path to the set if not already in set */ add2path_set( path ) INT path ; { PSETPTR temp, cpath ; if( path >= 1 || path <= numpathsG ){ cpath = path_set_arrayS[path] ; /* something is a member in set is counts match */ if( cpath->member != path_set_countS ){ /* new path to be added */ /* connect to the single linked list */ if( temp = path_set_listS ){ /* hook to old list */ path_set_listS = cpath ; cpath->next = temp ; } else { path_set_listS = cpath ; /* terminate new list */ cpath->next = NULL ; } cpath->path = path ; /* store data */ cpath->member = path_set_countS ; /* store membership */ } } else { M( ERRMSG, "ADD2SET","value of path is out of bounds of set\n" ) ; } } /* end add2path_set */ PSETPTR enum_path_set() { return( path_set_listS ) ; } clear_path_set() { path_set_countS ++ ; path_set_listS = NULL ; } /* end clear_path_set */ /* ----------------------------------------------------------------- Below is a second set of set routines required in the update path routines which operate on nets instead of paths. The following operations need to be done efficiently : membership - O(1) add to set if unique - O(1) clear set - O(1) Since we don't need to enumerate set we only need array to implement this set. ----------------------------------------------------------------- */ static INT *net_set_array ; /* set is an array of net set boxes */ static INT net_set_count ; /* current set count */ /* initialize set */ init_net_set() { net_set_array = (INT *) Ysafe_calloc((numnetsG+1), sizeof(INT) ); net_set_count = 1 ; } /* end initset */ /* add a net to the set if not already in set */ add2net_set( net ) INT net ; { if( net >= 1 || net <= numnetsG ){ /* current count make array member a valid member of set */ net_set_array[net] = net_set_count ; } else { M( ERRMSG, "ADD2SET", "value of path is out of bounds of set" ) ; } } /* end add2net_set */ BOOL member_net_set( net ) /* test for membership */ { if( net_set_array[net] == net_set_count ){ return( TRUE ) ; } else { return( FALSE ) ; } } /* end member_net_set */ clear_net_set() { /* to clear set we only need to increment net_set_count */ /* we can use this set up to 2 Gig times without any problem */ net_set_count ++ ; } /* end clear_path_set */ /* debug function to make sure calculation is correct */ INT dcalc_full_penalty() { INT timingpenal ; INT length ; /* path length incremental */ INT low_length ; /* lo path length */ INT high_length ; /* hi path length */ INT pathcount ; INT net ; /* net of path */ GLISTPTR net_of_path ; PATHPTR path ; NETBOXPTR dimptr ; /* now calculate the penalties */ /* first the timing penalty */ timingpenal = 0 ; for( pathcount = 1 ; pathcount <= numpathsG ; pathcount++ ) { path = patharrayG[pathcount] ; ASSERTNCONT( path, "findcost", "pointer to path is NULL" ) ; /* for all nets k of a path i */ low_length = 0 ; high_length = 0 ; for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ if( member_net_set( net ) ){ /* this half - perimeter has changed use update */ /* calculate total change on path */ length = dimptr->newhalfPx + (INT)(vertical_path_weightG * (DOUBLE) dimptr->newhalfPy) ; } else { /* old length */ length = dimptr->halfPx + (INT)(vertical_path_weightG * (DOUBLE) dimptr->halfPy) ; } low_length = low_length + (INT) (dimptr->max_driver * (FLOAT) length + dimptr->driveFactor ) ; high_length = high_length + (INT) (dimptr->min_driver * (FLOAT) length + dimptr->driveFactor ) ; } /* calculate penalty */ /* no penalty if within target window */ /* lowerbound <= length <= upperbound */ if( high_length > path->upper_bound ){ timingpenal += high_length - path->upper_bound ; } else if( low_length < path->lower_bound ){ timingpenal += path->lower_bound - low_length ; } } return( timingpenal ) ; } INT dcalc_min_path_len(path_num) INT path_num ; { INT length ; /* path length incremental */ INT net ; /* net of path */ INT halfP ; /* the modified half perimeter */ GLISTPTR net_of_path ; PATHPTR path ; NETBOXPTR dimptr ; path = patharrayG[path_num] ; /* for all nets k of a path i */ length = 0 ; for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ if( member_net_set( net ) ){ /* this half - perimeter has changed use update */ /* calculate total change on path */ halfP = dimptr->newhalfPx + (INT)(vertical_path_weightG * (DOUBLE) dimptr->newhalfPy) ; length = length + (INT) (dimptr->max_driver * halfP + dimptr->driveFactor ) ; } else { /* old length */ halfP = dimptr->halfPx + (INT)(vertical_path_weightG * (DOUBLE) dimptr->halfPy) ; length = length + (INT) (dimptr->max_driver * halfP + dimptr->driveFactor ) ; } } return( length ) ; } /* end dcald_min_path_len */ INT dcalc_max_path_len(path_num) INT path_num ; { INT length ; /* path length incremental */ INT net ; /* net of path */ INT halfP ; /* the modified half perimeter */ GLISTPTR net_of_path ; PATHPTR path ; NETBOXPTR dimptr ; path = patharrayG[path_num] ; /* for all nets k of a path i */ length = 0 ; for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ if( member_net_set( net ) ){ /* this half - perimeter has changed use update */ /* calculate total change on path */ halfP = dimptr->newhalfPx + (INT)(vertical_path_weightG * (DOUBLE) dimptr->newhalfPy) ; length = length + (INT) (dimptr->min_driver * halfP + dimptr->driveFactor ) ; } else { /* old length */ halfP = dimptr->halfPx + (INT)(vertical_path_weightG * (DOUBLE) dimptr->halfPy) ; length = length + (INT) (dimptr->min_driver * halfP + dimptr->driveFactor ) ; } } return( length ) ; } /* end dcalc_max_path_len */ graywolf-0.1.4+20170307gite1bf319/src/twmc/penalties.c000066400000000000000000000265121305746555600216630ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: penalties.c DESCRIPTION:calculation of the penalty coefficients CONTENTS: DATE: Mar 1, 1989 REVISIONS: May 16, 1989 - removed most doPartitionG conditions. Apr 23, 1990 - modified for new graph routines and modified timing constant update to use a constant derived at high temperatures. Mon Feb 4 02:16:26 EST 1991 - added overlap penalty override for testing purposes. Thu Feb 7 00:20:00 EST 1991 - reworked graph data. Thu Apr 18 01:40:16 EDT 1991 - refit overlap parameters. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) penalties.c version 3.8 9/16/91" ; #endif #include #include #include #include #define DEBUGLAPFACTOR #define DAMPFACTOR 0.015 /* damping factor on overlap penalty */ #define COREDAMPFACTOR 0.10 /* damping factor on core oversize */ #define CORECAP 1.30 /* maximum penalty for core error */ #define COREMIN 1.00 /* min error for core at end */ #define LAPMIN 1.00 /* min penalty factor for binpenalty */ #define LAPCAPFACTOR 100.00 /* lap penalty max is 100x funccost */ #define TIMEFACTOR 3.00 /* ration of time to funccost */ #define STARTCORE 0.10 /* start core for placement case */ #define ENDCORE 0.05 /* end core for placement case */ #define STARTOVERLAP 0.70 /* start overlap for placement case */ #define ENDOVERLAP 0.15 /* end overlap for placement case */ #define INITFACTOR 1.00 /* initial penalty factors */ #define INITNETPENAL 1000.00 /* dummy value to avoid / 0 */ /* ----------------------------------------------------------------- Initial weight of various penalties to wirelength cost Penalties are INITRELXXXX% of the wirelength part. This is not critical since negative feedback will correct our possible mistake. -------------------------------------------------------------- */ #define INITRELLAP 0.40 /* overlap relative to funccost */ static DOUBLE coreAreaS ; /* the area of the core */ static DOUBLE start_core_errorS ;/* the start and stop target */ static DOUBLE end_core_errorS ; /* ratios for the various */ static DOUBLE start_overlapS ; /* penalties. */ static DOUBLE end_overlapS ; static BOOL firstLapS = TRUE; /* 1st time calc_init_lapFactor called */ static BOOL firstTimeS = TRUE;/* 1st time calc_init_timeFactor called*/ /* ----------------------------------------------------------------- Use negative feedback to control relative ratio between penalties */ /* **** overlap penalty controller **** */ DOUBLE calc_lap_factor( percentDone ) DOUBLE percentDone ; { DOUBLE diff_lap, target_bin_penalty, bin_deviation ; DOUBLE sqrtCoreArea, sqrtBinPenal, lapCap ; INT iter ; char filename[LRECL] ; FILE *fp ; #define A 0.84379 #define B -1.7294E-4 #define C -2.3867E-5 /* - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - Initialize beginning average to one so that in beginning controller can change alot to adjust to conditions. Later the average will diminish the result. - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - */ # define NUMSAMPLE 15 # define RECIP_SAMPLE 0.06666666 static DOUBLE avg_devS[NUMSAMPLE] = { 0.0 } ; static INT avgCountS = 0 ; DOUBLE running_avg ; INT i ; /* **** overlap penalty controller **** */ /* no damping at the start so that controller can react quickly */ /* calculate target penalty for overlap penalty. */ sqrtCoreArea = sqrt( coreAreaS ) ; iter = iterationG + 2 ; diff_lap = A + B*iter + C*iter*iter ; if( percentDone > 2.0 ){ diff_lap = 0.01 ; } target_bin_penalty = diff_lap * sqrt( coreAreaS ) ; sqrtBinPenal = sqrt( (DOUBLE) binpenalG ) ; /* bin_deviation is percent error relative to target */ bin_deviation = (sqrtBinPenal - target_bin_penalty) / target_bin_penalty ; Yplot_heading( 0, "graph_lap", "iter","binpenal","sqrtbin", "coreArea","sqrtCore", "percent","sqrtpercent", "target", "lapFactor", "bin_dev", NULL ) ; Yplot( 0, "graph_lap", "%d", iterationG, "%4.4le %4.4le %4.4le %4.4le", (DOUBLE) binpenalG, sqrtBinPenal, coreAreaS, sqrtCoreArea ) ; /* save running average of deviations */ avg_devS[avgCountS++ % NUMSAMPLE] = bin_deviation ; running_avg = 0.0 ; for( i = 0; i < NUMSAMPLE; i++ ){ running_avg += avg_devS[i] ; } running_avg *= RECIP_SAMPLE ; if( avgCountS >= NUMSAMPLE ){ /* use running average to bound maximum change in lapFactor */ if( running_avg > 0.0 ){ /* bound between 0 and running average */ bin_deviation = MAX( bin_deviation, 0.0 ) ; bin_deviation = MIN( bin_deviation, running_avg ) ; } else { /* bound between 0 and - running average */ bin_deviation = MIN( bin_deviation, 0.0 ) ; bin_deviation = MAX( bin_deviation, running_avg ) ; } } lapFactorG *= (1.0 + bin_deviation) ; Yplot( "graph_lap", "%d", iterationG, "%4.4le %4.4le %4.4le %4.4le %4.4le", (DOUBLE) binpenalG / coreAreaS, sqrtBinPenal / sqrtCoreArea, target_bin_penalty, lapFactorG, bin_deviation ) ; Yplot_flush( "graph_lap" ) ; lapFactorG = (lapFactorG > LAPMIN) ? lapFactorG : LAPMIN ; lapCap = LAPCAPFACTOR * (DOUBLE) funccostG / sqrtBinPenal ; lapFactorG = (lapFactorG < lapCap) ? lapFactorG : lapCap ; /* this is an override mechanism to setting parameters */ sprintf( filename, "%s.lap", cktNameG ) ; if( fp = TWOPEN( filename, "r", NOABORT )){ HPI( fp, &lapFactorG ) ; TWCLOSE( fp ) ; } return( lapFactorG ) ; } /* ********* end overlap penalty controller ******** */ DOUBLE calc_time_factor( percentDone ) DOUBLE percentDone ; { /* **** timing penalty controller **** */ /* don't change it from initial value */ return( timeFactorG ) ; /* ********* end timing penalty controller ******** */ } /* end function calc_time_penalty */ /* ----------------------------------------------------------------- Calculate the new core area as a function of time. Reconfigure the core according to this new target compensating overlap penalty to account for change in cell areas. Calculate cell areas with routing areas = TRUE. Core_deviation varies as the negative of the error measurement. That is why target_core_error and core_error in core_deviation calculation are reversed. */ DOUBLE calc_core_factor( percentDone ) DOUBLE percentDone ; { INT binArea, cellArea ; DOUBLE diff_core, target_core_error, core_deviation ; DOUBLE core_error ; binArea = get_bin_area() ; cellArea = calc_cellareas( TRUE ) ; diff_core = start_core_errorS - end_core_errorS ; core_error = (DOUBLE) (binArea - cellArea) / (DOUBLE) cellArea ; target_core_error = (start_core_errorS - diff_core * percentDone ) ; core_deviation = COREDAMPFACTOR * (DOUBLE) (target_core_error - core_error) ; coreFactorG *= 1.0 + core_deviation ; coreFactorG = (coreFactorG > COREMIN ) ? coreFactorG : COREMIN ; coreFactorG = (coreFactorG < CORECAP) ? coreFactorG : CORECAP ; coreAreaS = coreFactorG * (DOUBLE) cellArea ; /* reconfigure area and place pads */ reconfigure( maxBinXG-1,maxBinYG-1, coreAreaS ) ; return( coreFactorG ) ; } /* end calc_core_factor */ /* ***************************************************************** INITIAL LAP FACTOR CALCULATION Currently, just set lapFactor initially to 40% of wirelength. This could use move investigation in the future. */ DOUBLE calc_init_lapFactor( totFunc, totPen ) DOUBLE totFunc ; DOUBLE totPen ; { DOUBLE factor ; #ifdef DEBUGLAPFACTOR extern DOUBLE saveLapFactorG ; #endif /* first iteration, we set all factors to 1 */ /* since every move is acceptted */ if( firstLapS ){ firstLapS = FALSE ; start_overlapS = INITFACTOR ; end_overlapS = INITFACTOR ; return( INITFACTOR ) ; } if( totPen > EPSILON ){ factor = INITRELLAP * totFunc / totPen ; } /* ----------------------------------------------------------- The penalty controller forces overlap to go from : start_overlap*binArea to end_overlap*binArea ----------------------------------------------------------- */ #ifdef DEBUGLAPFACTOR start_overlapS = STARTOVERLAP ; end_overlapS = saveLapFactorG ; #else start_overlapS = STARTOVERLAP ; end_overlapS = ENDOVERLAP ; #endif OUT2("\n\nOVERLAP FACTOR (COMPUTED) : %f\n", lapFactorG ) ; OUT3("start_overlap: %4.2le end_overlap: %4.2le\n\n", start_overlapS, end_overlapS ) ; return( factor ) ; } /* end calc_init_lapFactor */ /* ***************************************************************** INITIAL TIME FACTOR CALCULATION Currently, just set timeFactor initially to 40% of wirelength. This could use move investigation in the future. */ DOUBLE calc_init_timeFactor( avgdFunc, avgdTime ) DOUBLE avgdFunc ; DOUBLE avgdTime ; { if( firstTimeS ){ firstTimeS = FALSE ; return( INITFACTOR ) ; } else { if( avgdTime > EPSILON ){ return( TIMEFACTOR * avgdFunc / avgdTime ) ; } else { return( 0.0 ) ; } } } /* end calc_init_timeFactor */ DOUBLE calc_init_coreFactor( ) { /* -------------------------------------------------------------- The penalty controller forces corearea to go from : start_core_error*cellArea to end_core_error*cellArea initialize coreFactor to binArea / cellarea. ----------------------------------------------------------- */ coreFactorG = (DOUBLE) get_bin_area() / (DOUBLE) calc_cellareas(TRUE ) ; start_core_errorS = STARTCORE ; end_core_errorS = ENDCORE ; OUT3("start_core: %4.2le end_overcore: %4.2le\n\n", start_core_errorS, end_core_errorS ) ; return( coreFactorG ) ; } /* end calc_init_coreFactor */ graywolf-0.1.4+20170307gite1bf319/src/twmc/perimeter.c000066400000000000000000000036461305746555600216760ustar00rootroot00000000000000/* * Copyright (C) 1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char SccsId[] = "@(#) perimeter.c version 3.4 12/16/90" ; #endif #include #include #include perimeter( A, numcorners ) YBUSTBOXPTR A ; INT numcorners ; { INT i , sum ; sum = 0 ; for( i = 1 ; i <= numcorners ; i++ ) { if( i == numcorners ) { sum += ABS(A[1].x - A[i].x) + ABS(A[1].y - A[i].y) ; } else { sum += ABS(A[i + 1].x - A[i].x) + ABS(A[i + 1].y - A[i].y) ; } } return( sum ) ; } graywolf-0.1.4+20170307gite1bf319/src/twmc/placepads.c000066400000000000000000000713141305746555600216330ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * Copyright (C) 2014 Ruben Undheim * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: placepads.c DESCRIPTION:This file contains the place pads routines. CONTENTS: placepads() find_core() setVirtualCore( flag ) BOOL flag ; find_core_boundry( left, right, bottom, top ) INT *left, *right, *bottom, *top ; get_global_pos( cell, l, b, r, t ) INT cell, *l, *r, *b, *t ; DATE: Aug 12, 1988 REVISIONS: Oct 24, 1988 - added virtual core switch to control pad placement. Jan 17, 1988 - add find_core_boundary for channel graph generation code - outgeo.c . Jan 20, 1989 - fixed problem when pad has no pin connected to it. Made sure softcells are using correct fields and coordinates are translated. Feb. 15, 1989 - added get_global_pos so that amount of duplicated code is reduced. Apr 30, 1989 - added bound to padcenter for non-virtual core placement. Modified putChildren to place padgroups with sidespace restriction. Oct 20, 1989 - Now pads are output with global routing density. Feb 7, 1990 - Updated placepad core coordinates to reflect new routing scheme. Sun Jan 20 21:34:36 PST 1991 - ported to AIX. Wed Feb 13 23:55:50 EST 1991 - now call placepads program. Sat Feb 23 00:17:28 EST 1991 - added placepads algorithm. Sun May 5 14:30:08 EDT 1991 - after setVirtual switch is turned on update the block variables. Thu Sep 19 16:33:58 EDT 1991 - fixed problem with sidespace options when only a fraction of the pins to pads have connections to the core. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) placepads.c version 3.14 11/23/91" ; #endif #include #include #include #include #include #include #include #include "config-build.h" #define PLACEPADPROG "placepads" #define PLACEPADPATH "../placepads" #define PADKEYWORD "pad" /* ***************** STATIC FUNCTION DEFINITIONS ******************* */ static find_optimum_locations( P1(void) ) ; static place_pad( P2(PADBOXPTR pad,INT bestside ) ) ; static place_children( P5(PADBOXPTR pad,INT side,DOUBLE lb,DOUBLE ub,BOOL sr) ) ; static INT find_cost_for_a_side(P5(PADBOXPTR pad,INT side,DOUBLE lb,DOUBLE ub, BOOL spacing_restricted ) ) ; static find_core( P1(void) ) ; /* ***************** STATIC VARIABLE DEFINITIONS ******************* */ static INT sumposS ; /* sum of the modified opt. pin pos. of pad pins */ static INT sumtieS ; /* sum of all the opt. pin pos. of pad pins */ static INT pin_countS ; /* number of pins found with valid connections */ static BOOL virtualCoreS = FALSE ; static YSETPTR pad_net_setS = NIL(YSETPTR) ; static BOOL external_pad_programS = FALSE ; /*------------------------------------------------------------------- placepads() now call placepads program or uses internal algorithm. If you convert from placepads program remember to change numterms field to endsuper. ____________________________________________________________________*/ placepads() { if( padspacingG == EXACT_PADS ){ /* no work to do */ return ; } find_core(); /* GET THE UPDATED CORE'S DIMENSION */ if( external_pad_programG ){ call_place_pads() ; funccostG = findcost() ; return ; } /* otherwise do the internal routines */ D( "placepads/initially", print_pads( "pads initially\n", padarrayG, totalpadsG ) ; ) ; find_optimum_locations() ; D( "placepads/after_find_opt", print_pads( "pads after_cost\n", sortarrayG, totalpadsG ) ; ) ; sort_pads(); D( "placepads/after_sort", print_pads( "pads after sort\n", placearrayG, numpadsG ); ) ; align_pads(); D( "placepads/after_align", print_pads( "pads after align\n", placearrayG, numpadsG ) ; ) ; orient_pads(); D( "placepads/after_orient", print_pads( "pads after orient\n", placearrayG, numpadsG ) ; ) ; dimension_pads(); D( "placepads/after_dim", print_pads( "pads after dimension\n", placearrayG, numpadsG ) ; ) ; funccostG = findcost() ; } /* end placepads */ /* ***************************************************************** */ static find_optimum_locations() { INT i ; /* pad counter */ INT side ; /* loop thru valid sides */ INT cost ; /* current cost */ INT bestpos ; /* best modified position for pad */ INT besttie ; /* best position for pad for tiebreak */ INT bestcost ; /* best cost for pad or padgroup */ INT bestside ; /* best side to place pad or padgroup */ PADBOXPTR pad ; /* current pad */ /** FIND OPTIMUM PLACE FOR PADS ACCORDING TO THE RESTRICTIONS **/ for( i = 1; i <= totalpadsG; i++ ){ /**** LEAVES AND SUBROOTS NEED TO BE PLACED ON THE SAME **** SIDE AS THEIR PARENT ROOT, HENCE WE PLACE THE ROOT **** FIRST, AND THEN PLACE ALL ITS CHILDREN **/ pad = padarrayG[i] ; if( pad->padtype == PADGROUPTYPE && pad->hierarchy == ROOT ){ /* the case of a padgroup root */ bestcost = INT_MAX ; for (side = 1; side <= 4; side++ ) { if( pad->valid_side[ALL] || pad->valid_side[side] ){ cost = find_cost_for_a_side( pad,side, (DOUBLE) pad->lowerbound, (DOUBLE) pad->upperbound, pad->fixed ) ; if( cost < bestcost) { bestcost = cost; bestside = side ; } } } place_children( pad, bestside, (DOUBLE) pad->lowerbound, (DOUBLE) pad->upperbound, pad->fixed ) ; } else if( pad->padtype == PADCELLTYPE && pad->hierarchy == NONE ) { /* the case of a pad that is not in a padgroup */ bestcost = INT_MAX ; for (side = 1; side <= 4; side++ ) { if( pad->valid_side[ALL] || pad->valid_side[side] ){ cost = find_cost_for_a_side( pad,side, (DOUBLE) pad->lowerbound, (DOUBLE) pad->upperbound, pad->fixed ) ; if( cost < bestcost) { bestcost = cost; bestside = side ; bestpos = sumposS ; besttie = sumtieS ; } } } /* now use the best positions for the position */ sumposS = bestpos ; sumtieS = besttie ; place_pad( pad, bestside ) ; } /* end simple pad case */ } } /* end find_optimum */ /* ***************************************************************** */ static INT find_cost_for_a_side(pad,side,lb,ub,spacing_restricted) PADBOXPTR pad; INT side ; DOUBLE lb, ub ; BOOL spacing_restricted ; { INT i ; /* children counter */ INT pos ; /* current pos. of current core pin constrained*/ INT dist ; /* current distance from core pin to pad */ INT cost ; /* sum of the opt pad pins to closest core pin */ INT dist2 ; /* under restrictions dist from core pin to pad */ INT lowpos ; /* convert lower bound to a position */ INT uppos ; /* convert upper bound to a position */ INT bestpos ; /* best constrained pos for pad to core for 1 net */ INT besttie ; /* best position for pad to core for 1 net */ INT bestdist ; /* best distance for pad to core for 1 net */ INT tiebreak ; /* best place to put pad pin unconstrained */ BOOL pinFound ; /* true if we find a match on current net */ PINBOXPTR pinptr; /* current pin */ PINBOXPTR netterm;/* loop thru pins of a net */ PADBOXPTR child; /* go thru the children of the padgroup */ /**** FOR NORMAL PADS AND LEAVES, JUST CALCULATE THE COST */ /*** AND POSITION. THE LEAF CASE IS THE RETURN CONDITION OF */ /*** THE RECURSION ON THE ROOT PADS ***/ if( pad->hierarchy == LEAF || pad->hierarchy == SUBROOT ){ if( !(pad->valid_side[ALL]) && !(pad->valid_side[side]) ){ /* this is not a valid side return a huge cost */ return( PINFINITY ) ; } } /* At this point are guaranteed to have a valid side */ cost = 0 ; sumposS = 0 ; sumtieS = 0 ; /* determine spacing restrictions */ calc_constraints( pad, side, &lb, &ub, &spacing_restricted, &lowpos, &uppos ) ; if( pad->hierarchy == LEAF || pad->hierarchy == NONE ){ /**** FOR ALL PINS BELONGING TO THE SAME NET AS PINS ON THE PAD, FIND THE PIN CLOSEST TO THE SIDE IN padside. ****/ /**** ASSUME NO PIN WAS FOUND ***/ pin_countS = 0 ; for ( pinptr = cellarrayG[pad->cellnum]->pinptr ;pinptr; pinptr = pinptr->nextpin) { bestdist = INT_MAX ; /*** GO TO FIRST TERMS OF THE NET TO MAKE SURE ALL TERMINALS ARE INCLUDED ***/ pinFound = FALSE ; netterm = netarrayG[pinptr->net]->pins; for( ;netterm ;netterm = netterm->next ) { /**** CALCULATE THE DISTANCE FROM CORE. **** pos IS THE POSITION OF THE PAD ON THIS SIDE **** WHICH RESULTS IN THE SHORTEST DISTANCE TO THE PIN. **** ONLY PINS ON CELLS ARE IN THIS CONTEST **/ if( netterm->cell <= endsuperG ) { switch (side) { case L: pos = netterm->ypos; dist = netterm->xpos - coreG[X][MINI]; break; case T: pos = netterm->xpos; dist = coreG[Y][MAXI] - netterm->ypos; break; case R: pos = netterm->ypos; dist = coreG[X][MAXI] - netterm->xpos; break; case B: pos = netterm->xpos; dist = netterm->ypos - coreG[Y][MINI]; break; } /* end switch on side */ tiebreak = pos ; /* save original spot */ if( spacing_restricted ){ /* the pad placement on the side has been */ /* restricted in some way */ if( lowpos <= pos && pos <= uppos ){ /* everythings cool do no extra distance */ dist2 = 0 ; } else if( lowpos > pos ){ dist2 = ABS( lowpos - pos ) ; pos = lowpos ; } else if( pos > uppos ){ dist2 = ABS( pos - uppos ) ; pos = uppos ; } /* modify the distance by it Manhattan length */ /* to the pad in the orthogonal direction */ /* since this pad is fixed at a point */ /* could modify this to be more accurate since we want matching padpin*/ dist += dist2 ; } } if (dist < bestdist) { bestdist = dist; /*** UPDATE THE BEST DISTANCE */ bestpos = pos; /*** AND BEST POSITION */ besttie = tiebreak; /* save the original position */ pinFound = TRUE ; /* pin on this net was found */ } } /* end looking at this net */ if( pinFound ){ /*** SUM UP THE BEST POSITION OF ALL PINS */ sumposS += bestpos ; sumtieS += besttie ; /*** KEEP TRACK OF THE TOTAL COST FOR THIS SIDE */ cost += bestdist; pin_countS++ ; } } /* end for loop on pins of the pad */ /*** IF NO PIN IS FOUND TO MATCH WITH PAD ARBITRARILY ***/ /*** SET best position to random number for THIS PAD ***/ if( pin_countS == 0 ){ if( spacing_restricted ){ /* average between constraints */ sumposS = (lowpos + uppos) / 2 ; } else { /* Randomly pick a cost to break ties in the case that this pad could go on any side. Small value will not effect padgroups */ cost = PICK_INT( 0, 3 ) ; switch (side) { case L: sumposS = PICK_INT( coreG[Y][MINI],coreG[Y][MAXI] ) ; break; case T: sumposS = PICK_INT( coreG[X][MINI],coreG[X][MAXI] ) ; break; case R: sumposS = PICK_INT( coreG[Y][MINI],coreG[Y][MAXI] ) ; break; case B: sumposS = PICK_INT( coreG[X][MINI],coreG[X][MAXI] ) ; break; default: break; } } sumtieS = sumposS ; } /* end pin_countS == 0 */ return( cost ) ; } else { /*** IF THE PAD IS A SUPERPAD, THEN SEARCH THROUGH ALL *** ITS CHILDREN AND SUM THE COST AND IDEAL POSITION *** RECURSIVELY. Use the spacing restrictions derived above. ***/ for( i = 1 ;i <= pad->children[HOWMANY]; i++ ){ child = padarrayG[pad->children[i]]; cost += find_cost_for_a_side( child, side, lb, ub, spacing_restricted ) ; } return( cost ); } } /* end find_cost_for_a_side */ /* ***************************************************************** */ /**** SET POSITION OF THE PAD. POS IS THE SUM OF THE OPTIMAL POSITION **** FOR ALL TERMINALS OF THE PAD. WE DIVIDE BY THE NUMBER OF TERMINAL **** TO GET THE AVERAGE. Place_pad must be performed immediately **** after a find_cost_for_a_side since sumposS and sumtieS **** are set in those routines. Otherwise set sumposS and sumtieS **** to their proper values. ***/ static place_pad( pad, bestside ) PADBOXPTR pad ; INT bestside ; { if( pin_countS == 0 ){ /*** SET PAD TO RANDOM POSITION DETERMINED IN find_cost_for_side*/ pad->position = sumposS ; pad->tiebreak = sumtieS ; } else { pad->position = sumposS / pin_countS ; pad->tiebreak = sumtieS / pin_countS ; } /* now bound pad center to current core boundary for normal case */ pad->padside = bestside ; #ifdef LATER switch( bestside ){ case L: case R: pad->position = MAX( pad->position, coreG[Y][MINI] ) ; pad->position = MIN( pad->position, coreG[Y][MAXI] ) ; break; case T: case B: pad->position = MAX( pad->position, coreG[X][MINI] ) ; pad->position = MIN( pad->position, coreG[X][MAXI] ) ; } /* end bound of pad position */ #endif } /* end place_pad */ /* ***************************************************************** */ /**** RECURSIVELY SET THE PADSIDE OF ALL CHILDREN OF THE ROOT PAD TO THE **** PADSIDE OF THE PARENT. GIVEN THAT SIDE, SET THE OPTIMAL CXCENTER */ static place_children( pad, side, lb, ub, spacing_restricted ) PADBOXPTR pad ; INT side ; DOUBLE lb, ub ; BOOL spacing_restricted ; { INT i ; /* pad counter */ INT pos ; /* position of last placed pad */ INT min_pos ; /* min position of the last padgroup */ INT max_pos ; /* max position of the last padgroup */ DOUBLE lowbound ; /* lower bound for pad or pad group */ DOUBLE hibound ; /* upper bound for pad or pad group */ PADBOXPTR child; /* go thru the children of the padgroup */ /* DETERMINE SPACING RESTRICTIONS */ if( spacing_restricted ){ /* this is the case that the spacing has been restricted */ if( pad->fixed ){ /* if the padgroup bounds have been fixed, */ /* force position to be within bound */ /* assume we are ok and then correct it */ lowbound = pad->lowerbound ; if( lowbound < lb ){ lowbound = lb ; } if( lowbound > ub ){ lowbound = ub ; } hibound = pad->upperbound ; if( hibound < lb ){ hibound = lb ; } if( hibound > ub ){ hibound = ub ; } } else { /* this pad is not fixed use the given ub and lb */ lowbound = lb ; hibound = ub ; } } else { if( pad->fixed ){ /* the padgroup bounds have not been fixed */ /* just take the pad's restricted position */ lowbound = pad->lowerbound; hibound = pad->upperbound; spacing_restricted = TRUE ; } } /* **** END spacing restriction calculations *** */ if( pad->hierarchy == LEAF ){ find_cost_for_a_side( pad, side, lowbound, hibound, spacing_restricted ) ; place_pad( pad, side ) ; return ; } else { pos = 0 ; min_pos = INT_MAX ; max_pos = INT_MIN ; for( i = 1; i <= pad->children[HOWMANY]; i++ ){ child = padarrayG[pad->children[i]]; place_children( child, side, lowbound, hibound, spacing_restricted ) ; pos += child->position ; min_pos = MIN( child->position, min_pos ) ; max_pos = MAX( child->position, max_pos ) ; } if( pad->children[HOWMANY] ){ pad->position = pos /= pad->children[HOWMANY] ; } else { pad->position = pos ; } /* for tiebreak use the bounds of the padgroup and average them. */ /* set the side of the pad */ pad->padside = side ; pad->tiebreak = (min_pos + max_pos ) / 2 ; return ; } } /* end place_children */ /* ***************************************************************** */ /* ***************************************************************** */ #ifdef DEBUG print_pads( message, array, howmany ) char *message ; PADBOXPTR *array ; INT howmany ; { INT i ; PADBOXPTR ptr ; CELLBOXPTR cptr ; fprintf( stderr, "\n%s\n", message ) ; /* now print them out */ for( i = 1 ; i <= howmany; i++ ){ ptr = array[i] ; cptr = cellarrayG[ptr->cellnum] ; fprintf( stderr, "pad:%s x:%d y:%d type:%d side:%d pos:%d tie:%d orient:%d\n", cptr->cname, cptr->xcenter, cptr->ycenter, ptr->hierarchy, ptr->padside, ptr->position, ptr->tiebreak, cptr->orient ) ; } fprintf( stderr, "\n" ) ; dimension_pads() ; G( process_graphics() ) ; } /* end print_pads */ #endif /* DEBUG */ /* ***************************************************************** */ /* turn virtual core on and off */ setVirtualCore( flag ) BOOL flag ; { virtualCoreS = flag ; } /* end set Virtual core */ /* function finds and returns core boundary region including cells */ /* which overlap the core region */ find_core_boundary( left, right, bottom, top ) INT *left, *right, *bottom, *top ; { BOOL rememberFlag ; /* call routine to find core boundary based on virtual core */ rememberFlag = virtualCoreS ;/* so we can put flag back */ virtualCoreS = TRUE ; find_core() ; /* set flag back to whatever it was */ virtualCoreS = rememberFlag ; /* now return values */ *left = coreG[X][MINI] ; *right = coreG[X][MAXI] ; *bottom = coreG[Y][MINI] ; *top = coreG[Y][MAXI] ; } /* end find_core_boundary */ /* given a cell it returns bounding box of cell in global coordinates */ get_global_pos( cell, l, b, r, t ) INT cell ; INT *l, *r, *b, *t ; { INT orient ; BOUNBOXPTR bounptr ; CELLBOXPTR ptr ; ptr = cellarrayG[cell] ; orient = ptr->orient ; bounptr = ptr->bounBox[orient] ; *l = bounptr->l ; *r = bounptr->r ; *b = bounptr->b ; *t = bounptr->t ; /* now add xcenter ycenter to get global position */ *l += ptr->xcenter ; *r += ptr->xcenter ; *b += ptr->ycenter ; *t += ptr->ycenter ; } /* end get_global_pos */ /* given a cell it returns bounding box of cell including routing area */ get_routing_boundary( cell, ret_l, ret_b, ret_r, ret_t ) INT cell ; INT *ret_l, *ret_r, *ret_b, *ret_t ; /* return quantities */ { INT minx, maxx ; INT miny, maxy ; CELLBOXPTR ptr ; RTILEBOXPTR tileptr ; get_global_pos( cell, ret_l, ret_b, ret_r, ret_t ) ; if( !(routingTilesG) ){ /* return cell boundary if no routing tiles */ return ; } /* otherwise find bounding box of routing tiles */ minx = INT_MAX ; miny = INT_MAX ; maxx = INT_MIN ; maxy = INT_MIN ; for( tileptr = routingTilesG[cell];tileptr;tileptr=tileptr->next ){ minx = MIN( minx, tileptr->x1 ) ; maxx = MAX( maxx, tileptr->x2 ) ; miny = MIN( miny, tileptr->y1 ) ; maxy = MAX( maxy, tileptr->y2 ) ; } /* now add xcenter ycenter to get global position */ ptr = cellarrayG[cell] ; *ret_l = MIN( minx + ptr->xcenter, *ret_l ) ; *ret_r = MAX( maxx + ptr->xcenter, *ret_r ) ; *ret_b = MIN( miny + ptr->ycenter, *ret_b ) ; *ret_t = MAX( maxy + ptr->ycenter, *ret_t ) ; return ; } /* end get_routing_boundary */ static INT get_pad_routing( cell ) INT cell ; { CELLBOXPTR cptr ; /* pad cell in question */ RTILEBOXPTR tptr ; /* look at all the routing tiles */ INT last_core_cell ; /* calc last core cell index */ INT new ; /* new position with routing */ INT old ; /* old position with no routing */ last_core_cell = ( (INT) routingTilesG[HOWMANY] ) - 4 ; /* find bounding box of routing tiles */ cptr = cellarrayG[endpadgrpsG + cell] ; tptr = routingTilesG[last_core_cell + cell] ; new = 0 ; switch( cell ){ case L: for( ; tptr ; tptr = tptr->next ){ new = MAX( new, tptr->x2 ) ; } old = cptr->tiles->right ; break ; case T: for( ; tptr ; tptr = tptr->next ){ new = MIN( new, tptr->y1 ) ; } old = cptr->tiles->bottom ; break ; case R: for( ; tptr ; tptr = tptr->next ){ new = MIN( new, tptr->x1 ) ; } old = cptr->tiles->left ; break ; case B: for( ; tptr ; tptr = tptr->next ){ new = MAX( new, tptr->y2 ) ; } old = cptr->tiles->top ; break ; } /* end switch */ if( new ){ return( ABS( new - old ) ) ; } return( 0 ) ; } /* end get_pad_routing */ static find_core() { INT ominx, ominy ; INT omaxx, omaxy ; INT l, r, b, t ; INT i ; if( virtualCoreS ){ /* initialize xmin, ymax, etc. */ coreG[X][MINI] = INT_MAX ; coreG[Y][MINI] = INT_MAX ; coreG[X][MAXI] = INT_MIN ; coreG[Y][MAXI] = INT_MIN ; /* reset bounding boxes for all cells for get_global_pos */ regenorient(1, numcellsG) ; /* find virtual boundary of core */ for( i=1;i<=numcellsG;i++ ){ if( cellarrayG[i]->celltype == STDCELLTYPE && doPartitionG ){ /* ignore standard cell types */ continue ; } if( doPartitionG ){ get_global_pos( i, &l, &b, &r, &t ) ; } else { get_routing_boundary( i, &l, &b, &r, &t ) ; } coreG[X][MINI] = MIN( coreG[X][MINI], l ) ; coreG[X][MAXI] = MAX( coreG[X][MAXI], r ) ; coreG[Y][MINI] = MIN( coreG[Y][MINI], b ) ; coreG[Y][MAXI] = MAX( coreG[Y][MAXI], t ) ; } if( doPartitionG ){ coreG[X][MINI] = MIN( coreG[X][MINI], blocklG ) ; coreG[X][MAXI] = MAX( coreG[X][MAXI], blockrG ) ; coreG[Y][MINI] = MIN( coreG[Y][MINI], blockbG ) ; coreG[Y][MAXI] = MAX( coreG[Y][MAXI], blocktG ) ; } /* set block parameters once virtual core is set */ blocklG = coreG[X][MINI] ; blockrG = coreG[X][MAXI] ; blockbG = coreG[Y][MINI] ; blocktG = coreG[Y][MAXI] ; } else { coreG[X][MINI] = blocklG ; coreG[X][MAXI] = blockrG ; coreG[Y][MINI] = blockbG ; coreG[Y][MAXI] = blocktG ; } /* now guarantee space between core and pads */ /* if global router info not available */ if( !(routingTilesG) ){ coreG[X][MINI] -= track_spacingXG ; coreG[Y][MINI] -= track_spacingYG ; coreG[X][MAXI] += track_spacingXG ; coreG[Y][MAXI] += track_spacingYG ; } else if(!(doPartitionG)){ /* find delta in pad spacing */ coreG[X][MINI] -= get_pad_routing( L ) ; coreG[Y][MAXI] += get_pad_routing( T ) ; coreG[X][MAXI] += get_pad_routing( R ) ; coreG[Y][MINI] -= get_pad_routing( B ) ; } /* if the grid is given force to grid positions */ if( gridCellsG ){ ominx = coreG[X][MINI] ; ominy = coreG[Y][MINI] ; omaxx = coreG[X][MAXI] ; omaxy = coreG[Y][MAXI] ; YforceGrid( &coreG[X][MINI], &coreG[Y][MINI] ) ; YforceGrid( &coreG[X][MAXI], &coreG[Y][MAXI] ) ; /* make sure gridded data is outside of core to avoid overlap */ if( ominx < coreG[X][MINI] ){ coreG[X][MINI] -= track_spacingXG ; } if( ominy < coreG[Y][MINI] ){ coreG[Y][MINI] -= track_spacingYG ; } if( omaxx > coreG[X][MAXI] ){ coreG[X][MAXI] += track_spacingXG ; } if( omaxy > coreG[Y][MAXI] ){ coreG[Y][MAXI] += track_spacingYG ; } } perdimG[X] = coreG[X][MAXI] - coreG[X][MINI] ; perdimG[Y] = coreG[Y][MAXI] - coreG[Y][MINI] ; } /* end find_core */ /* ***********************EXTERNAL ROUTINES ************************** */ call_place_pads() { FILE *fp ; INT pad ; INT line ; INT numnets ; INT numtokens ; INT closegraphics() ; INT find_numnets() ; BOOL abort ; char **tokens ; char *bufferptr ; char *pathname, *Yrelpath() ; char *twdir, *Ygetenv() ; char filename[LRECL] ; char buffer[LRECL] ; CELLBOXPTR cellptr ; /* build the input file for the placepads program */ sprintf( filename, "%s.pads", cktNameG ); fp = TWOPEN( filename, "w", ABORT ) ; numnets = find_numnets() ; fprintf( fp, "core %d %d %d %d\n", coreG[X][MINI], coreG[Y][MINI], coreG[X][MAXI], coreG[Y][MAXI] ) ; fprintf( fp, "pads %d numnets %d\n", numpadsG+numpadgroupsG, numnets); output_pads( fp ) ; output_nets( fp, numnets ) ; TWCLOSE( fp ) ; /* now call the placepad program */ /* find the path of placepads relative to main program */ pathname = Yrelpath( argv0G, PLACEPADPATH ) ; if( !(YfileExists(pathname))){ if( twdir = TWFLOWDIR ){ sprintf( filename, "%s/bin/%s", twdir, PLACEPADPROG ) ; pathname = Ystrclone( filename ) ; } } switch( padspacingG ){ case ABUT_PADS: sprintf( YmsgG, "%s -asn %s", pathname, cktNameG ) ; break ; case UNIFORM_PADS: sprintf( YmsgG, "%s -usn %s", pathname, cktNameG ) ; break ; case VARIABLE_PADS: sprintf( YmsgG, "%s -osn %s", pathname, cktNameG ) ; break ; } M( MSG, NULL, YmsgG ) ; M( MSG, NULL, "\n" ) ; /* Ysystem will kill program if catastrophe occurred */ Ysystem( PLACEPADPROG, ABORT, YmsgG, closegraphics ) ; Ysafe_free( pathname ) ; /* free name created in Yrelpath */ /* ############# end of placepads execution ############# */ /* **************** READ RESULTS of placepads ************/ /* open pad placement file for reading */ M( MSG, NULL, "Reading results of placing pads...\n" ) ; sprintf(filename, "%s.pout" , cktNameG ) ; fp = TWOPEN( filename , "r", ABORT ) ; /* parse file */ line = 0 ; abort = FALSE ; pad = endsuperG ; while( bufferptr=fgets(buffer,LRECL,fp )){ /* parse file */ line ++ ; /* increment line number */ tokens = Ystrparser( bufferptr, ": \t\n", &numtokens ); if( numtokens == 0 ){ /* skip over empty lines */ continue ; } else if( strcmp( tokens[0], PADKEYWORD ) == STRINGEQ){ /* look at first field for keyword */ /* ie. pad x y orient padside */ if( numtokens != 6 ){ sprintf( YmsgG, "Syntax error on line:%d\n", line ) ; M(ERRMSG, "placepads", YmsgG ) ; abort = TRUE ; continue ; } pad++ ; ASSERTNBREAK( pad > 0 && pad <= endpadsG, "placepads", "pad out of bounds\n" ) ; cellptr = cellarrayG[pad] ; cellptr->xcenter = atoi(tokens[2] ) ; cellptr->ycenter = atoi(tokens[3] ) ; cellptr->orient = atoi(tokens[4] ) ; cellptr->padptr->padside = atoi(tokens[5] ) ; } else { sprintf( YmsgG, "Syntax error on line:%d\n", line ) ; M(ERRMSG, "placepads", YmsgG ) ; abort = TRUE ; continue ; } } TWCLOSE( fp ) ; if( abort ){ M(ERRMSG, "placepads", "Problem with placing pads.Must abort\n") ; closegraphics() ; YexitPgm( PGMFAIL ) ; } /* ************ END READ RESULTS of placepads ************/ } /* end call_place_pads */ INT find_numnets() { INT pad ; INT numnets ; CELLBOXPTR ptr ; PINBOXPTR pin ; if(!(pad_net_setS) ){ pad_net_setS = Yset_init( 1, numnetsG ) ; } Yset_empty( pad_net_setS ) ; numnets = 0 ; for( pad = endsuperG; pad <= endpadsG; pad++ ){ ptr = cellarrayG[ pad ] ; for( pin = ptr->pinptr; pin ; pin = pin->nextpin ){ if( netarrayG[ pin->net ]->numpins <= 1 ){ continue ; } if( Yset_add( pad_net_setS, pin->net ) ){ /* Yset_add returns TRUE if a new member of set */ numnets++ ; } } } return( numnets ) ; } /* end find_numnets */ output_nets( fp, numnets ) FILE *fp ; { INT net ; INT pincount ; PINBOXPTR pin ; NETBOXPTR netptr ; YSETLISTPTR list ; for( list = Yset_enumerate(pad_net_setS) ;list; list = list->next ){ net = list->node ; netptr = netarrayG[ net ] ; fprintf( fp, "net %s ", netptr->nname ) ; pincount = 0 ; for( pin = netptr->pins; pin ; pin = pin->next ){ if( pin->cell > endsuperG ){ /* skip over the pad connections */ continue ; } fprintf( fp, "%d %d ", pin->xpos, pin->ypos ) ; if( ++pincount > 5 ){ pincount = 0 ; fprintf( fp, "\n" ) ; } } if( pincount != 0 ){ fprintf( fp, "\n" ) ; } } } /* end output_nets */ graywolf-0.1.4+20170307gite1bf319/src/twmc/placepin.c000066400000000000000000001645261305746555600215020ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: placepin.c DESCRIPTION:find initial placement of softpins CONTENTS: placepin() DATE: Mar 16, 1989 - added header and rewrote data structure. REVISIONS: Apr 23, 1990 - working version of softpin placement for instance changes. Apr 28, 1990 - added control over overflow output. May 2, 1990 - fixed problem with softcells with no pins and fixed error in find_hardpin_side. May 15, 1990 - fixed problems with standard cells. Oct 14, 1990 - fixed problem with pins moving off cell. Sun Jan 20 21:45:41 PST 1991 - ported to AIX. Fri Jan 25 18:14:17 PST 1991 - added routines for wire estimation. Wed Jan 30 14:17:19 EST 1991 - updated for new trans library routines. Sat Feb 2 00:00:22 EST 1991 - renamed find_rtile_side to file_tile_side a general routine. Mon Feb 4 02:52:04 EST 1991 - added new placepin algorithm which correctly handles pin groups and side space restrictions. Mon Feb 4 15:08:16 EST 1991 - each level of the recursion in install_pin_groups needs a workspace. Tue Mar 12 17:05:03 CST 1991 - fixed initialization problem with permutation. Sat Apr 27 01:11:41 EDT 1991 - now avoid crash during stdcell designs with no pads. Tue May 21 17:06:38 CDT 1991 - fixed argument problem, FLOAT vs. DOUBLE. Wed Jun 5 15:43:33 CDT 1991 - changed REL_POS to REL_POST for accuracy. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) placepin.c version 3.18 11/23/91" ; #endif #include #include #include #include #undef NONE #define NONE 0 #define LEAF 1 #define SUBROOT 2 #define ROOT 3 #ifdef INFINITY #undef INFINITY #endif #define INFINITY INT_MAX >> 4 #define DIV_2 >> 1 #define UP 1 #define DOWN 2 #define LEFT 3 #define RIGHT 4 #define USESIDERESTRICTIONS 0 #define ONESIDE 1 #define SOMESIDES 2 #define ALLSIDES 3 #define HOWMANY 0 /* the 0th element of arrays store # elements */ #define UNCOMMITTED 0 #define LAYER1 1 #define LAYER2 2 #define LAYER3 3 #define VSMALL INT_MIN / 10 #define VLARGE INT_MAX / 10 typedef struct sidebox { INT x ; INT y ; INT start ; INT end ; INT loc ; INT length ; /* length of the side */ INT direction ; /* LEFT, RIGHT, TOP, BOTTOM */ } SIDEBOX, *SIDEBOXPTR ; static SIDEBOXPTR *sideArrayS ; /* the sides of the cell */ static CELLBOXPTR ptrS ; /* the current cell pointer */ static INT aveTrackPitchS ; /* the average track pitch */ static INT numpinS ; /* number of pins (leaves only)for a cell */ static INT maxsideS = 0 ; /* the max numsides over all cells */ static INT bestposS ; /* the position to put pin */ static INT besttieS ; /* the best tie breaker */ static INT *greedy_posS ; /* array of pin positions for greedy method */ static PINBOXPTR *placearrayS;/* the leaves of a cell */ static BOOL tell_overflowS = FALSE ; /* turn on overflow message */ static BOOL softequivS ; /* true if soft equivs are present */ BOOL contiguous_pinsG = TRUE ; /* ****** static FUNCTION definitions ******** */ static find_optimal_locations( P1(BOOL newVertFlag )); static INT find_cost_for_a_side( P5( PINBOXPTR pin, INT side, DOUBLE lb, DOUBLE ub, BOOL spacing_restricted )) ; static determine_bbox( P2( INT net, INT cell )) ; static place_pin( P4( PINBOXPTR pin, INT pos, INT tiebreak, INT side ) ) ; static place_children( P5( PINBOXPTR pin, INT side, DOUBLE lb, DOUBLE ub, BOOL spacing_restricted ) ) ; static set_hardpin_pos( P2( PINBOXPTR pin, BOOL newVertFlag ) ); static sort_softpins() ; static INT compare_pins( P2( PINBOXPTR *pinptr1, PINBOXPTR *pinptr2 ) ) ; static INT sort_by_pos( P2( PINBOXPTR *pinptr1, PINBOXPTR *pinptr2 ) ) ; static install_pin_groups( P1( PINBOXPTR pin ) ) ; static permute_pg( P1( PINBOXPTR pin ) ) ; static space_pins() ; static place_soft_equivs() ; static find_next_free_spotm( P3( SIDEBOXPTR sideptr, PINBOXPTR pin, INT *pos )) ; static BOOL find_next_free_spotg(P3( SIDEBOXPTR sideptr, PINBOXPTR pin, INT *pos )) ; static init_side_array( P1( BOOL newVertFlag ) ) ; static side_to_global() ; static find_hardpin_side() ; /* ****** global FUNCTION definitions ******** */ extern init_wire_est() ; extern set_up_pinplace() ; extern set_pin_verbosity( P1(BOOL flag ) ) ; extern update_pins( P1( BOOL initialFlag ) ) ; extern print_pins( P3( char *message , PINBOXPTR *array , INT howmany ) ) ; extern INT *find_pin_sides( P1( INT cell ) ) ; extern INT find_tile_side( P3( INT center, INT loc, INT direction ) ) ; /* ################################################################## */ /*------------------------------------------------------------------- placepin() performs all the necessary step to place soft pins on a soft cell. It first find the best spot for each pin using the half perimeter bounding box metric. The best spot for pin groups is the average of all its children. Placepin then spaces the pins along the sides and returns all answers in the pin->t?pos_new fields. No calculation to funccost or timing penalty is performed. ____________________________________________________________________*/ placepin( cell, newVertFlag ) INT cell ; BOOL newVertFlag ; /* use the x_new field if true otherwise use x field */ { INT i ; /* counter */ INT howmany ; /* number of soft pins including pg */ INT where ; /* where to put the pin on boundary */ INT side ; /* the side the pin is to be placed */ PINBOXPTR pin ; SOFTBOXPTR spin ; GLISTPTR pptr ; /* pointer to nets of a cell */ ptrS = cellarrayG[cell] ; if( ptrS->numpins <= 0 ){ return ; /* no work to do */ } init_side_array( newVertFlag ) ; numpinS = 0 ; softequivS = FALSE ; howmany = (INT) ptrS->softpins[HOWMANY] ; /** DETERMINE THE BOUNDING BOX OF NETS EXCLUDING THIS CELL **/ for( pptr = ptrS->nets; pptr ; pptr = pptr->next ) { determine_bbox( pptr->p.net, cell ) ; /* tell unet that this net has been modified. */ netarrayG[ pptr->p.net ]->nflag = TRUE ; } find_optimal_locations( newVertFlag ) ; D( "placepins/after_find_opt", print_pins( "pins after_cost\n", ptrS->softpins, howmany ) ; ) ; sort_softpins() ; D( "placepins/after_sort", print_pins( "pins after all sorting\n", placearrayS, numpinS ); ) ; space_pins() ; D( "placepins/after_spacing", print_pins( "pins after spacing\n", placearrayS, numpinS ); ) ; side_to_global() ; } /* end placepins */ /* ***************************************************************** */ static find_optimal_locations( newVertFlag ) BOOL newVertFlag ; { INT i, j ; /* pin counters */ INT side ; /* loop thru valid sides */ INT cost ; /* current cost */ INT bestpos ; /* best modified position for pins */ INT besttie ; /* best position for pins for tiebreak */ INT bestcost ; /* best cost for pin or pingroup */ INT bestside ; /* best side to place pin or pingroup */ INT howmany ; /* number of soft pins including pg */ INT num_restrict ; /* number of side restrictions for pin */ BOOL invalid ; /* whether side is invalid */ PINBOXPTR pin ; SOFTBOXPTR spin ; /** PLACE THE PINS ACCORDING TO THE RESTRICTIONS **/ howmany = (INT) ptrS->softpins[HOWMANY] ; for( i = 1 ; i <= howmany; i++ ){ /**** LEAVES AND SUBROOTS NEED TO BE PLACED ON THE SAME **** SIDE AS THEIR PARENT ROOT, HENCE WE PLACE THE ROOT **** FIRST, AND THEN PLACE ALL ITS CHILDREN **/ pin = ptrS->softpins[i] ; spin = pin->softinfo ; if( pin->type == HARDPINTYPE ){ set_hardpin_pos( pin, newVertFlag ) ; continue ; } else if( pin->type == PINGROUPTYPE && spin->hierarchy == ROOT ){ /* the case of a pingroup root */ bestcost = INT_MAX ; /* calculate number of restricted sides */ num_restrict = spin->restrict1[HOWMANY] ; for( side = 1; side <= ptrS->numsides; side++ ) { if( num_restrict != 0 ){ invalid = TRUE ; /* make sure this side is a valid side */ for( j = 1; j <= num_restrict; j++ ){ if( spin->restrict1[j] == side ){ invalid = FALSE ; break ; } } if( invalid ){ /* this side is not valid go to next side */ continue ; } } /* at this point we have a valid side */ cost = find_cost_for_a_side( pin, side, spin->lowerbound, spin->upperbound, spin->fixed ) ; if( cost < bestcost) { bestcost = cost; bestside = side ; } } /* loop on sides */ place_children( pin, bestside, spin->lowerbound, spin->upperbound, spin->fixed ) ; } else if( pin->type == SOFTPINTYPE && spin->hierarchy == NONE ) { /* the case of a pin that is not in a pingroup */ bestcost = INT_MAX ; /* calculate number of restricted sides */ num_restrict = spin->restrict1[HOWMANY] ; for( side = 1; side <= ptrS->numsides; side++ ) { if( num_restrict != 0 ){ invalid = TRUE ; /* make sure this side is a valid side */ for( j = 1; j <= num_restrict; j++ ){ if( spin->restrict1[j] == side ){ invalid = FALSE ; break ; } } if( invalid ){ /* this side is not valid go to next side */ continue ; } } /* at this point we have a valid side */ cost = find_cost_for_a_side( pin,side, spin->lowerbound, spin->upperbound, spin->fixed ) ; if( cost < bestcost) { bestcost = cost; bestside = side ; bestpos = bestposS ; besttie = besttieS ; } } /* now use the best positions for the position */ place_pin( pin, bestpos, besttie, bestside ) ; } /* end simple pin case */ } /* loop on number of pins */ } /* end find_optimal_locations */ /* ***************************************************************** */ static INT find_cost_for_a_side(pin,side,lb,ub,spacing_restricted) PINBOXPTR pin; INT side ; DOUBLE lb, ub ; BOOL spacing_restricted ; { INT i ; /* children counter */ INT pos ; /* current pos. of current core pin constrained*/ INT dist ; /* current distance from core pin to pin */ INT cost ; /* cost of the opt pin placement */ INT dista ; /* under restrictions dist from core pin to ideal */ INT dist1 ; /* under restrictions dist from core pin to ideal */ INT dist2 ; /* under restrictions dist from core pin to ideal */ INT xideal ; /* ideal place to put pin */ INT yideal ; /* ideal place to put pin */ INT pin_count ; /* number of pins found */ INT lowpos ; /* convert lower bound to a position */ INT uppos ; /* convert upper bound to a position */ INT bestpos ; /* best constrained pos for ideal to core for 1 net */ INT besttie ; /* best position for ideal to core for 1 net */ INT bestdist ; /* best distance for ideal to core for 1 net */ INT tiebreak ; /* best place to put pin unconstrained */ INT howmany ; /* number of soft pins including pg */ BOOL invalid ; /* whether side is invalid */ BOOL intersect ; /* whether pin intersects side */ INT num_restrict ;/* number of side restrictions for pin */ BOOL pinFound ; /* true if we find a match on current net */ FLOAT lowbound ; /* lower bound for pin or pin group */ FLOAT hibound ; /* upper bound for pin or pin group */ PINBOXPTR pinptr; /* current pin */ PINBOXPTR netterm;/* loop thru pins of a net */ PINBOXPTR child; /* child of the pin group */ SIDEBOXPTR sideptr;/* pointer to side information */ SOFTBOXPTR spin ; /* current soft information pointer */ NETBOXPTR netptr ;/* current net */ /**** FOR NORMAL PINS AND LEAVES, JUST CALCULATE THE COST */ /*** AND POSITION. THE LEAF CASE IS THE RETURN CONDITION OF */ /*** THE RECURSION ON THE ROOT PINS ***/ spin = pin->softinfo ; if( spin->hierarchy == LEAF || spin->hierarchy == SUBROOT ){ /* check to make sure we have a valid side */ num_restrict = spin->restrict1[HOWMANY] ; if( num_restrict != 0 ){ invalid = TRUE ; /* make sure this side is a valid side */ for( i = 1; i <= num_restrict; i++ ){ if( spin->restrict1[i] == side ){ invalid = FALSE ; break ; } } if( invalid ){ /* this side is not valid go to next side */ /* set cost = INFINITY */ return( INFINITY ) ; } } } /* at this point we are processing a valid side */ cost = 0 ; bestposS = 0 ; besttieS = 0 ; sideptr = sideArrayS[side] ; /* determine spacing restrictions */ if( spacing_restricted ){ /* this is the case that the spacing has been restricted */ if( spin->fixed ){ /* if the pingroup bounds have been fixed, */ /* force position to be within bound */ /* assume we are ok and then correct it */ lowbound = spin->lowerbound ; if( lowbound < lb ){ lowbound = lb ; } if( lowbound > ub ){ lowbound = ub ; } hibound = spin->upperbound ; if( hibound < lb ){ hibound = lb ; } if( hibound > ub ){ hibound = ub ; } } else { /* this pin is not fixed use the given ub and lb */ lowbound = lb ; hibound = ub ; } } else { if( spin->fixed ){ /* the pingroup bounds have not been fixed */ /* just take the pin's restricted position */ spacing_restricted = TRUE ; } lowbound = spin->lowerbound; hibound = spin->upperbound; } if( spacing_restricted ){ lowpos = (INT) ( lowbound * (DOUBLE) sideptr->length ) ; lowpos += sideptr->start ; uppos = (INT) ( hibound * (DOUBLE) sideptr->length ) ; uppos += sideptr->start ; /* lowpos and uppos are global coordinates here */ /* which relate to the given sidepointer start and end points */ } /* **** END spacing restriction calculations *** */ if( spin->hierarchy == LEAF || spin->hierarchy == NONE ){ netptr = netarrayG[pin->net] ; /* the ideal position for the pin is center of bounding box */ xideal = (netptr->newxmin + netptr->newxmax ) DIV_2 ; yideal = (netptr->newymin + netptr->newymax ) DIV_2 ; bestdist = INT_MAX ; intersect = FALSE ; if( sideptr->direction==LEFT || sideptr->direction==RIGHT ){ /* horizontal side */ if( sideptr->start <= xideal && xideal <= sideptr->end ){ /* side encompasses the point */ dist = ABS( yideal - sideptr->loc ) ; pos = xideal ; intersect = TRUE ; } else { /* check the 2 corner point using Manhattan dist */ /* the constant part */ dist1 = dist2 = ABS( sideptr->y - yideal ) ; /* the part due to the corners */ dist1 += ABS( sideptr->x - xideal ) ; dist2 += ABS( (sideptr->x + sideptr->length) - xideal ) ; if( dist1 < dist2 ){ dist = dist1 ; pos = sideptr->x ; } else { dist = dist2 ; pos = sideptr->x + sideptr->length ; } } } else { /* else vertical side */ if( sideptr->start <= yideal && yideal <= sideptr->end ){ /* side is encompasses the point */ dist = ABS( xideal - sideptr->loc ) ; pos = yideal ; intersect = TRUE ; } else { /* check the 2 corner point using Manhattan dist */ /* the constant part */ dist1 = dist2 = ABS( sideptr->x - xideal ) ; /* the part due to the corners */ dist1 += ABS( sideptr->y - yideal ) ; dist2 += ABS( (sideptr->y + sideptr->length) - yideal ) ; if( dist1 < dist2 ){ dist = dist1 ; pos = sideptr->y ; } else { dist = dist2 ; pos = sideptr->y + sideptr->length ; } } } /* NOW CHECK SPACING RESTRICTIONS */ tiebreak = pos ; /* save original spot */ if( spacing_restricted ){ /* the pin placement on the side has been */ /* restricted in some way */ if( lowpos <= pos && pos <= uppos ){ /* everythings cool do no extra distance */ dista = 0 ; } else if( lowpos > pos ){ dista = ABS( lowpos - pos ) ; pos = lowpos ; } else if( pos > uppos ){ dista = ABS( pos - uppos ) ; pos = uppos ; } /* modify the distance by it Manhattan length */ /* to the pin in the orthogonal direction */ /* since this pin is fixed at a point */ dist += dista ; } if( dist < bestdist || (dist == bestdist && intersect) ){ bestdist = dist; /*** UPDATE THE BEST DISTANCE */ bestposS = pos; /*** AND BEST POSITION */ besttieS = tiebreak; /* save the original position */ } return( bestdist ) ; /* end single pin code */ } else { /*** IF THE PIN IS A SUPERPIN, THEN SEARCH THROUGH ALL *** ITS CHILDREN AND SUM THE COST AND IDEAL POSITION *** RECURSIVELY. Use the spacing restrictions derived above. ***/ howmany = (INT) spin->children[HOWMANY] ; for( i = 1 ; i <= howmany; i++ ){ child = spin->children[i] ; cost += find_cost_for_a_side( child, side, lowbound, hibound, spacing_restricted ) ; } return( cost ); } } /* end find_cost_for_a_side */ /* ***************************************************************** */ /* find the bounding box of this net without this cell */ static determine_bbox( net, cell ) INT net ; /* calculate this net */ INT cell ; /* exclude this cell */ { NETBOXPTR netptr ; /* current net */ PINBOXPTR pinptr ; /* current pin */ BOOL noPinsFound ; /* see if pins are found for this net */ INT x, y ; /* current pinpos for speed */ /* ********* calculate net half perimeter bounding box *********** */ netptr = netarrayG[net] ; noPinsFound = TRUE ; if( netptr->skip != TRUE ) { /* find first pin that we don't have skip field set */ /* initialize bounding box pin count to 1 */ for( pinptr = netptr->pins;pinptr; pinptr = pinptr->next ) { if( pinptr->skip == 1 || pinptr->cell == cell ) { continue ; } noPinsFound = FALSE ; netptr->newxmin = netptr->newxmax = pinptr->xpos ; netptr->newymin = netptr->newymax = pinptr->ypos ; pinptr = pinptr->next ; break ; } /* Now find whether this pin impacts the bounding box */ /* Note when we get more than one pin on the bounding box */ for( ; pinptr ; pinptr = pinptr->next ) { if( pinptr->skip == 1 || pinptr->cell == cell ) { continue ; } x = pinptr->xpos ; y = pinptr->ypos ; if( x <= netptr->newxmin ) { netptr->newxmin = x ; } else if( x >= netptr->newxmax ) { netptr->newxmax = x ; } if( y <= netptr->newymin ) { netptr->newymin = y ; } else if( y >= netptr->newymax ) { netptr->newymax = y ; } } } if( noPinsFound ){ /* this means we are free to put pin anywhere to minimize */ /* wirelength */ netptr->newxmin = VSMALL ; netptr->newxmax = VLARGE ; netptr->newymin = VSMALL ; netptr->newymax = VLARGE ; } } /* end half perimeter bounding box calculation */ /* ***************************************************************** */ /**** SET XPOS OF THE PIN TO DESIRED POSITION. *****/ static place_pin( pin, pos, tiebreak, side ) PINBOXPTR pin; INT pos; INT tiebreak; INT side; { pin->txpos_new = pos ; pin->typos_new = tiebreak ; pin->softinfo->side = side ; } /* end place_pin */ /* ***************************************************************** */ /**** RECURSIVELY SET THE SIDE OF ALL CHILDREN OF THE ROOT PIN TO THE **** PADSIDE OF THE PARENT. GIVEN THAT SIDE, SET THE OPTIMAL POSITION */ static place_children( pin, side, lb, ub, spacing_restricted ) PINBOXPTR pin ; INT side ; DOUBLE lb, ub ; BOOL spacing_restricted ; { INT i ; /* pin counter */ INT pos ; /* position of last placed pin */ INT min_pos ; /* min position of the last pingroup */ INT max_pos ; /* max position of the last pingroup */ INT howmany ; /* number of soft pins including pg */ INT child_pos ; /* position of children */ FLOAT lowbound ; /* lower bound for pin or pingroup */ FLOAT hibound ; /* upper bound for pin or pingroup */ PINBOXPTR child; /* go thru the children of the pingroup */ SOFTBOXPTR spin ; /* current soft information pointer */ spin = pin->softinfo ; /* DETERMINE SPACING RESTRICTIONS */ if( spacing_restricted ){ /* this is the case that the spacing has been restricted */ if( spin->fixed ){ /* if the pingroup bounds have been fixed, */ /* force position to be within bound */ /* assume we are ok and then correct it */ lowbound = spin->lowerbound ; if( lowbound < lb ){ lowbound = lb ; } if( lowbound > ub ){ lowbound = ub ; } hibound = spin->upperbound ; if( hibound < lb ){ hibound = lb ; } if( hibound > ub ){ hibound = ub ; } } else { /* this pin is not fixed use the given ub and lb */ lowbound = lb ; hibound = ub ; } } else { if( spin->fixed ){ /* the pingroup bounds have not been fixed */ /* just take the pin's restricted position */ lowbound = spin->lowerbound; hibound = spin->upperbound; spacing_restricted = TRUE ; } } /* **** END spacing restriction calculations *** */ if( spin->hierarchy == LEAF ){ find_cost_for_a_side( pin, side, lowbound, hibound, spacing_restricted ) ; /* bestposS and besttieS are set in find_cost_for_a_side */ place_pin( pin, bestposS, besttieS, side ) ; return ; } else { pos = 0 ; min_pos = INT_MAX ; max_pos = INT_MIN ; /* txpos_new holds the best position on this side */ /* typos_new holds the tie breaker */ howmany = (INT) spin->children[HOWMANY] ; /* find the position of the children */ for (i = 1; i <= howmany; i++) { child = spin->children[i] ; place_children( child, side, lowbound, hibound, spacing_restricted ) ; child_pos = child->txpos_new ; pos += child_pos ; min_pos = MIN( child_pos, min_pos ) ; max_pos = MAX( child_pos, max_pos ) ; } if( howmany ){ pin->txpos_new = pos /= howmany ; } else { pin->txpos_new = pos ; } /* for tiebreak use the bounds of the pingroup and average them. */ pin->typos_new = (min_pos + max_pos ) / 2 ; /* mark the side */ spin->side = side ; return ; } } /* end place_children */ /* ***************************************************************** */ /**** SET XPOS OF THE PIN TO DESIRED POSITION. *****/ static set_hardpin_pos( pin, newVertFlag ) PINBOXPTR pin; BOOL newVertFlag ; { INT x, y ; /* pin x, y location */ SOFTBOXPTR sptr ; /* pointer to soft information */ SIDEBOXPTR sideptr ; /* pointer to side information */ if( newVertFlag ){ REL_POS( ptrS->orient, x, y, /* result */ pin->txpos_new, pin->typos_new, /* cell relative */ ptrS->xcenter, ptrS->ycenter ) ; /* cell center */ } else { REL_POS( ptrS->orient, x, y, /* result */ pin->txpos, pin->typos, /* cell relative */ ptrS->xcenter, ptrS->ycenter ) ; /* cell center */ } sptr = pin->softinfo ; /* we already know the side */ sideptr = sideArrayS[sptr->side] ; switch( sideptr->direction ){ case UP: case DOWN: pin->txpos_new = y ; break ; case LEFT: case RIGHT: pin->txpos_new = x ; break ; } } /* end set_hardpin_pos */ /********************************************************************** PIN SORTING ROUTINES ***********************************************************************/ static sort_softpins() { INT i ; /* pin counter */ INT pos ; /* position in place array */ INT howmany ; /* number of soft pins including pg */ SOFTBOXPTR spin ; /* pointer to soft information */ PINBOXPTR pin ; /* current pin */ /* first perform an initial sort to order the pins by side, hierarchy, */ /* and position on the side. */ howmany = (INT) ptrS->softpins[HOWMANY] ; Yquicksort( &(ptrS->softpins[1]), howmany, sizeof(PINBOXPTR), compare_pins ) ; D( "sort_softpins/1st_sort", print_pins( "pins after 1st sort\n", ptrS->softpins, howmany ); ) ; /* Now make sure the pins are permuted correctly */ for( i = 1; i <= howmany; i++ ){ pin = ptrS->softpins[i] ; spin = pin->softinfo ; ASSERTNCONT( spin, "sort_softpins","Problem with pointer" ) ; if (spin->hierarchy == ROOT){ permute_pg(pin) ; } } /* NOW INSTALL THE PIN GROUPS IN THEIR PROPER ORDER. There are 2 cases: */ /* CASE I - CONTIGUOUS INSURE THAT GROUPS REMAIN INTACT */ /* It is here that we set numpinS the number of actual pins of a cell */ if( contiguous_pinsG ){ for( i = 1; i <= howmany; i++ ){ pin = ptrS->softpins[i] ; spin = pin->softinfo ; if( spin->hierarchy == ROOT || spin->hierarchy == NONE ){ install_pin_groups( pin ) ; } } } else { /* CASE II - LEAVES ARE ALIGNED LIKE ORDINARY PINS IF THEY HAVE NO */ /* CONSTRAINTS SUCH AS ORDER OR PERMUTE. **/ /* put pins in place array then sort pins */ for( i = 1; i <= howmany; i++ ){ pin = ptrS->softpins[i] ; spin = pin->softinfo ; if( spin->hierarchy == LEAF || spin->hierarchy == NONE ){ placearrayS[++numpinS] = pin ; } } Yquicksort( &(placearrayS[1]),numpinS,sizeof(PINBOXPTR),sort_by_pos); } /* at this point numpinS is set properly */ } /* end sort_softpins */ /* ***************************************************************** */ /*** compare_pins() RETURNS TRUE IF ARG1 > ARG2 BY ITS OWN RULES **/ static INT compare_pins( pinptr1, pinptr2 ) PINBOXPTR *pinptr1, *pinptr2 ; { PINBOXPTR pin1, pin2; SOFTBOXPTR spin1, spin2; pin1 = *pinptr1 ; pin2 = *pinptr2 ; spin1 = pin1->softinfo ; spin2 = pin2->softinfo ; /* move the soft equivtypes to the end of the array */ /* these don't have a correct side so move to the end */ if( pin1->type == SOFTEQUIVTYPE ){ return( 1 ) ; } else if( pin2->type == SOFTEQUIVTYPE ){ return( 0 ) ; } if( spin1->side != spin2->side) { return( spin1->side - spin2->side ) ; } if( spin1->hierarchy != spin2->hierarchy ){ /*** MOVE ROOTS TO THE BEGINNING OF ARRAY MOVE */ /* LEAVES ARE SEPARATED, ROOTS ARE MERGED **/ if( spin1->hierarchy == SUBROOT ){ return( 1 ) ; } else if( spin2->hierarchy == SUBROOT ){ return( 0 ) ; } else if( spin1->hierarchy == LEAF ){ return( 1 ) ; } else if( spin2->hierarchy == LEAF ){ return( 0 ) ; } } /* check the position for equality */ if( pin1->txpos_new == pin2->txpos_new ){ /* hard pins always get preference */ if( pin1->type == HARDPINTYPE ){ /* move pin2 to the end */ return( 0 ) ; } else if( pin2->type == HARDPINTYPE ){ /* move pin1 to the beginning */ return( 1 ) ; } else { /* a softpin - typos_new field is tiebreaker */ /* use the tiebreaker field to break ties */ return( pin1->typos_new - pin2->typos_new ) ; } } else { return( pin1->txpos_new - pin2->txpos_new ) ; } } /* end compare_pins */ /* ***************************************************************** */ static INT sort_by_pos( pinptr1, pinptr2 ) PINBOXPTR *pinptr1, *pinptr2 ; { PINBOXPTR pin1, pin2; SOFTBOXPTR spin1, spin2; pin1 = *pinptr1 ; pin2 = *pinptr2 ; spin1 = pin1->softinfo ; spin2 = pin2->softinfo ; /* move the soft equivtypes to the end of the array */ /* these don't have a correct side so move to the end */ if( pin1->type == SOFTEQUIVTYPE ){ return( 1 ) ; } else if( pin2->type == SOFTEQUIVTYPE ){ return( 0 ) ; } /* always must maintain side */ if( spin1->side != spin2->side) { return( spin1->side - spin2->side ) ; } if( spin1->ordered || spin1->permute ){ return( 0 ) ; } else if( spin2->ordered || spin2->permute ){ return( 1 ) ; } else if( pin1->txpos_new == pin2->txpos_new ){ /* hard pins always get preference */ if( pin1->type == HARDPINTYPE ){ /* move pin2 to the end */ return( 0 ) ; } else if( pin2->type == HARDPINTYPE ){ /* move pin1 to the beginning */ return( 1 ) ; } else { /* a softpin - typos_new field is tiebreaker */ /* use the tiebreaker field to break ties */ return( pin1->typos_new - pin2->typos_new ) ; } } else { return( pin1->txpos_new - pin2->txpos_new ) ; } } /* end sort_by_pos */ /* ***************************************************************** */ /* install the pin groups and set numpinS */ static install_pin_groups( pin ) PINBOXPTR pin ; { INT i ; /* pin counter */ INT howmany ; /* number of pins in group */ INT initial_position ; /* position of next open place in placearray */ PINBOXPTR child ; /* current child */ PINBOXPTR *temparray; /* sort the pingroups */ SOFTBOXPTR spin ; /* soft information */ spin = pin->softinfo ; if( spin->hierarchy == LEAF || spin->hierarchy == NONE ){ placearrayS[++numpinS] = pin ; } else { howmany = (INT) spin->children[HOWMANY] ; /* each level of the recursion needs its own temparray */ temparray = (PINBOXPTR *) Yvector_alloc( 1,howmany,sizeof(PINBOXPTR) ) ; for( i = 1 ;i <= howmany ; i++ ){ child = spin->children[i] ; temparray[i] = child ; } /* now sort the subroots or leaves to obey both order constraints */ /* and permutation constraints. Otherwise try to sort by opt. pos.*/ Yquicksort( &(temparray[1]), howmany, sizeof(PINBOXPTR), sort_by_pos ) ; /* now that we have subroots or leaves in correct order */ /* look at next level down */ for( i = 1 ;i <= howmany ; i++ ){ child = temparray[ i ] ; install_pin_groups( child ) ; } /* now free temp array */ Yvector_free( temparray, 1, sizeof(PINBOXPTR) ) ; } } /* end install_pin_groups */ /* ***************************************************************** */ static permute_pg( pin ) PINBOXPTR pin ; { INT j, k ; /* used to reverse pins */ INT i ; /* pincounter */ INT howmany ; /* number of children in current pingroup */ INT max_pos ; /* max. value of the ideal positions of pin in pg */ INT min_pos ; /* min. value of the ideal positions of pin in pg */ INT child_pos ; /* position of children */ INT forward_cost ; /* cost to place pins in current order */ INT bakward_cost ; /* cost to place pins in reverse order */ INT proposed_fpos ; /* proposed uniformly spaced pos in forward order */ INT proposed_bpos ; /* proposed uniformly spaced pos in bakward order */ DOUBLE spacing ; /* spacing if we place pins in pg uniformly */ PINBOXPTR child ; /* current child */ PINBOXPTR tmp ; /* used to reverse permutable pins */ PINBOXPTR *array ; /* sort the children */ SOFTBOXPTR spin ; /* soft information */ spin = pin->softinfo ; howmany = (INT) spin->children[HOWMANY] ; if( spin->permute ){ /* first calculate span of pingroup */ ASSERTNRETURN( howmany >= 2,"permute_pg", "Must have at least 2 pins in a pingroup\n"); child = spin->children[1] ; child_pos = child->txpos_new ; min_pos = child_pos ; max_pos = child_pos ; for( i = 2; i <= howmany ; i++ ){ child = spin->children[i] ; child_pos = child->txpos_new ; min_pos = MIN( child_pos, min_pos ) ; max_pos = MAX( child_pos, max_pos ) ; } /* now find the cost if we evenly space the pins over that region */ spacing = (DOUBLE) (max_pos - min_pos) / (DOUBLE) (howmany - 1) ; forward_cost = 0 ; bakward_cost = 0 ; for( i = 1; i <= howmany ; i++ ){ child = spin->children[i] ; child_pos = child->txpos_new ; proposed_fpos = min_pos + ROUND( (i - 1) * spacing ) ; proposed_bpos = max_pos - ROUND( (i - 1) * spacing ) ; forward_cost += ABS( child_pos - proposed_fpos ) ; bakward_cost += ABS( child_pos - proposed_bpos ) ; } if( bakward_cost < forward_cost ) { /* we need to reverse the permutation */ array = spin->children + 1; j = howmany - 1; k = 0; while( k < j ){ tmp = array[j]; array[j--] = array[k]; array[k++] = tmp; } } } /*** NEED TO CHECK THE CHILDREN REGARDLESS OF THE PERMUTABILITY OF THE PARENT ROOT */ for( i = 1; i <= howmany; i++ ){ child = spin->children[i] ; if( child->softinfo->hierarchy == SUBROOT){ permute_pg( child ) ; } } } /* end permute_pg */ /* ***************************************************************** */ static space_pins() { INT i ; /* counter on pins */ INT j ; INT pos ; INT howmany ; INT old_side ; INT pincount ; /* count the pins on a side */ INT pos_orig ; /* used to restore original start on side */ INT first_pin_on_side ; /* as the name says */ BOOL invalid ; BOOL greedy ; /* TRUE if greedy spacing method is on */ BOOL status ; /* TRUE if greedy method failed */ PINBOXPTR pin ; SOFTBOXPTR spin ; SIDEBOXPTR sptr ; SIDEBOXPTR sideptr ; /* now we only have to space the leaves */ /* find the first pin and last pin on the side */ greedy = FALSE ; old_side = 0 ; pincount = 0 ; for( i = 1 ; i <= numpinS; ){ pin = placearrayS[i] ; spin = pin->softinfo ; if( spin->side == old_side ){ while( spin->side == old_side ){ if( pin->type == HARDPINTYPE ){ pos = pin->txpos_new ; if( greedy ){ /* put hardpin in greedy array to make life simpler */ greedy_posS[pincount++] = pos ; } } else if( pin->type != SOFTEQUIVTYPE ){ if( greedy ){ status = find_next_free_spotg( sideptr, pin, &pos ) ; /* delay storage of this position so we don't wipe */ /* out txpos_new field in case we need to call */ /* minimize overflow later */ greedy_posS[pincount++] = pos ; if( status ){ /* this means we overflow the side minimize overflow */ /* redo this side */ greedy = FALSE ; i = first_pin_on_side - 1 ; /* restore pos */ pos = pos_orig ; } } else { /* minimize the overflow on this side */ find_next_free_spotm( sideptr, pin, &pos ) ; pin->txpos_new = pos ; } } if( ++i > numpinS || pin->type == SOFTEQUIVTYPE ){ /* this is where we exit the loop. Finish off last greedy first*/ if( greedy ){ for( j = 0; j < pincount; j++ ){ pin = placearrayS[first_pin_on_side+j] ; pin->txpos_new = greedy_posS[j] ; } } if( pin->type == SOFTEQUIVTYPE ){ softequivS = TRUE ; } break ; } pin = placearrayS[i] ; spin = pin->softinfo ; } /* end while loop on this side */ } else if( pin->type != SOFTEQUIVTYPE ){ /* see if we need to process the old side */ if( greedy ){ for( j = 0; j < pincount; j++ ){ pin = placearrayS[first_pin_on_side+j] ; pin->txpos_new = greedy_posS[j] ; } } /* start a new side */ old_side = spin->side ; sideptr = sideArrayS[old_side] ; /* always try to be greedy first */ greedy = TRUE ; first_pin_on_side = i ; pincount = 0 ; /* set the initial position depending on direction on edge */ switch( sideptr->direction ){ case RIGHT: case UP: pos = sideptr->start ; break ; case DOWN: case LEFT: pos = sideptr->end ; break ; } pos_orig = pos ; } else { /* set side so we traverse thru SOFTEQUIV pins */ old_side = spin->side ; softequivS = TRUE ; } } if( softequivS ){ place_soft_equivs() ; } D( "space_pins", for( i = 1 ; i <= numpinS; i++ ){ pin = placearrayS[i] ; spin = pin->softinfo ; fprintf( stderr, "pin:%s signal:%s side:%d oldpos:%d pos:%d pintype:%d\n", pin->pinname, netarrayG[pin->net]->nname, spin->side, pin->typos_new, pin->txpos_new, pin->type ) ; } fprintf( stderr, "\n\n" ) ; ) ; /* end of debug */ } /* end space_pins */ static place_soft_equivs() { INT i ; /* counter on pins */ INT j ; INT k ; INT pos ; INT num_restrict ; /* number of side restrictions for pin */ INT orthog1, orthog2 ; /* two directions orthogonal to current one */ BOOL invalid ; /* whether side is invalid */ PINBOXPTR pin ; PINBOXPTR parent ; SOFTBOXPTR spin ; SOFTBOXPTR sparent ; SIDEBOXPTR sptr ; SIDEBOXPTR sideptr ; /* now place the equivalent pins */ for( i = 1 ; i <= numpinS; i++ ){ pin = placearrayS[i] ; spin = pin->softinfo ; if( pin->type != SOFTEQUIVTYPE ){ continue ; } parent = spin->parent ; sparent = parent->softinfo ; /* now find opposite side */ sideptr = sideArrayS[sparent->side] ; if( sideptr->direction == UP || sideptr->direction == DOWN ){ orthog1 = LEFT ; orthog2 = RIGHT ; } else if( sideptr->direction == RIGHT || sideptr->direction == LEFT ){ orthog1 = UP ; orthog2 = DOWN ; } pos = parent->txpos_new ; /* find the closest side that is valid */ num_restrict = spin->restrict1[HOWMANY] ; for( j = 1; j <= ptrS->numsides; j++ ){ sptr = sideArrayS[j] ; if( j == sparent->side || sptr->direction == orthog1 || sptr->direction == orthog2 ){ /* avoid the parent side and orthogonal sides */ continue ; } if( num_restrict >= 1 ){ /* make sure this side is a valid side */ invalid = TRUE ; for( k = 1; k <= num_restrict; k++ ){ if( spin->restrict1[k] == j ){ invalid = FALSE ; break ; } } if( invalid ){ continue ; } } if( sptr->start <= pos && pos <= sptr->end ){ pin->txpos_new = pos ; pin->softinfo->side = j ; pin->skip = FALSE ; } /* end for loop on number of sides */ } } /* end placing equiv pins */ } /* end place_softequivs */ /* minimize the amount of overflow on this side */ static find_next_free_spotm( sideptr, pin, pos ) SIDEBOXPTR sideptr ; PINBOXPTR pin ; INT *pos ; { INT space ; SOFTBOXPTR spin ; switch( ABS(pin->layer) ){ case UNCOMMITTED: space = aveTrackPitchS ; break ; case LAYER1: space = track_spacingXG ; break ; case LAYER2: space = track_spacingYG ; break ; case LAYER3: space = aveTrackPitchS ; break ; } /* end switch */ switch( sideptr->direction ){ case RIGHT: case UP: *pos += space ; if( tell_overflowS ){ if( *pos >= sideptr->end ){ /* overflow on this side */ sprintf( YmsgG, "overflow for cell:%d pin:%s\n", pin->cell, pin->pinname ) ; M( WARNMSG, "space_pins", YmsgG ) ; } } break ; case DOWN: case LEFT: *pos -= space ; if( tell_overflowS ){ if( *pos <= sideptr->start ){ /* overflow on this side */ sprintf( YmsgG, "overflow for cell:%d pin:%s\n", pin->cell, pin->pinname ) ; M( WARNMSG, "space_pins", YmsgG ) ; } } break ; } } /* find_next_free_spotm */ /* ***************************************************************** */ /* this is a greedy method which may overflow quite often */ /* pos is the last place a pin was placed. Returns TRUE if overflow has */ /* occurred while placing on this side */ static BOOL find_next_free_spotg( sideptr, pin, pos ) SIDEBOXPTR sideptr ; PINBOXPTR pin ; INT *pos ; { INT space ; INT newpos ; SOFTBOXPTR spin ; switch( ABS(pin->layer) ){ case UNCOMMITTED: space = aveTrackPitchS ; break ; case LAYER1: space = track_spacingXG ; break ; case LAYER2: space = track_spacingYG ; break ; case LAYER3: space = aveTrackPitchS ; break ; } /* end switch */ newpos = pin->txpos_new ; switch( sideptr->direction ){ case RIGHT: case UP: /* account for spacing - pos is now at the minimum valid position */ *pos += space ; if( newpos > *pos ){ *pos = newpos ; } if( *pos >= sideptr->end ){ /* overflow on this side */ return( TRUE ) ; } break ; case DOWN: case LEFT: /* account for spacing - pos is now at the maximum valid position */ *pos -= space ; if( newpos < *pos ){ *pos = newpos ; } if( *pos <= sideptr->start ){ /* overflow on this side */ return( TRUE ) ; } break ; } return( FALSE ) ; } /* find_next_free_spotg */ /* ***************************************************************** */ static side_to_global() { INT i; INT side ; INT tmp ; INT rev_orient ; INT x, y ; PINBOXPTR pin ; SOFTBOXPTR spin ; SIDEBOXPTR sptr ; rev_orient = Ytrans_inv_orient( ptrS->orient ) ; for( i = 1 ; i <= numpinS; i++ ){ pin = placearrayS[i] ; spin = pin->softinfo ; if( !spin ){ continue ; } side = spin->side ; if( side > 0 ){ sptr = sideArrayS[side] ; } else { if( pin->type == SOFTEQUIVTYPE ){ pin->skip = TRUE ; } else { fprintf( stderr, "side = 0\n" ) ; } } switch( sptr->direction ){ case UP: tmp = pin->txpos_new ; pin->txpos_new = sptr->loc ; pin->typos_new = tmp ; break ; case DOWN: tmp = pin->txpos_new ; pin->txpos_new = sptr->loc ; pin->typos_new = tmp ; break ; case LEFT: case RIGHT: pin->txpos_new = pin->txpos_new ; pin->typos_new = sptr->loc ; break ; } x = pin->txpos_new -= ptrS->xcenter ; y = pin->typos_new -= ptrS->ycenter ; /* translate back to current view */ REL_POS( rev_orient, pin->txpos_new, pin->typos_new, /* result */ x, y, /* cell relative */ 0, 0 ) ; /* cell center */ /* now calculate global coordinates */ REL_POS( ptrS->orient, pin->newx, pin->newy, /* result */ pin->txpos_new, pin->typos_new, /* cell relative */ ptrS->xcenter, ptrS->ycenter ) ; /* cell center */ /* tell unet that this pin has changed position */ pin->flag = TRUE ; D( "twmc/side_to_global", fprintf( stderr, "pin:%s signal:%s side:%d txpos:%d typos:%d xpos:%d ypos:%d\n", pin->pinname, netarrayG[pin->net]->nname, spin->side, pin->txpos_new, pin->typos_new, pin->newx, pin->newy, pin->type ) ; fprintf( stderr, "\n\n" ) ; ) ; /* end of debug */ } /* end for loop */ } /* end side_to_global() */ set_up_pinplace() { INT i ; /* counter */ INT j ; /* counter */ INT k ; /* counter */ INT numinst ; /* the number of instances for cell */ INT howmany ; /* the number of sofpins for cell */ INT max_soft ; /* count the number of softpins overall inst. */ INT last_net ; /* last unique net */ PINBOXPTR pin ; /* current pin pointer */ GLISTPTR nlist, tmp ; /* used to build nets of a cell */ INSTBOXPTR instptr ; /* instance information */ if( numsoftG == 0 && numstdcellG == 0 ){ return ; } /* find the maximum number of sides on a cell */ for( i = 1; i <= numcellsG ; i++ ){ ptrS = cellarrayG[i] ; if( ptrS->softflag ){ if( instptr = ptrS->instptr ){ numinst = ptrS->instptr->numinstances ; for( j = 0; j < numinst ; j++ ){ maxsideS = MAX( maxsideS, instptr->numsides[j] ) ; } } else { maxsideS = MAX( maxsideS, ptrS->numsides ) ; } /* build data structure for nets of the cell */ /* pins are sorted by net in sortpins() */ /* make use of this fact to find set of unique nets */ last_net = 0 ; for( pin = ptrS->pinptr ; pin; pin = pin->nextpin ){ if( pin->net != last_net ){ last_net = pin->net ; /* allocate space for net list */ if( tmp = ptrS->nets ){ nlist = ptrS->nets = (GLISTPTR) Ysafe_malloc(sizeof(GLISTBOX)); nlist->next = tmp ; } else { nlist = ptrS->nets = (GLISTPTR) Ysafe_malloc(sizeof(GLISTBOX)); nlist->next = NULL ; } nlist->p.net = last_net ; } } } } /* now allocate the array */ sideArrayS = (SIDEBOXPTR *) Yvector_alloc( 1,maxsideS,sizeof(SIDEBOXPTR) ) ; for( i = 1; i <= maxsideS ; i++ ){ sideArrayS[i] = (SIDEBOXPTR) Ysafe_malloc(sizeof(SIDEBOX) ) ; } /* initialize average track pitch */ aveTrackPitchS = (track_spacingXG + track_spacingYG) / 2 ; max_soft = 0 ; for( i = 1; i <= numcellsG ; i++ ){ ptrS = cellarrayG[i] ; if( ptrS->softflag ){ /* need to initialize each instance */ if( instptr = ptrS->instptr ){ numinst = ptrS->instptr->numinstances ; for( j = 0; j < numinst; j++ ){ ptrS->numsides = instptr->numsides[j] ; ptrS->vertices = instptr->vert_inst[j] ; if( !(ptrS->softpins)){ continue ; } howmany = (INT) ptrS->softpins[HOWMANY] ; max_soft = MAX( max_soft, howmany ) ; /* set each pin's correct instance */ for( k = 1 ; k <= howmany; k++ ){ pin = ptrS->softpins[k] ; pin->softinfo = pin->soft_inst[j] ; } /* now set the pins */ init_side_array( FALSE ) ; find_hardpin_side() ; } /* now set everything as it was */ j = ptrS->cur_inst ; ptrS->numsides = instptr->numsides[j] ; ptrS->vertices = instptr->vert_inst[j] ; } else if( ptrS->softpins ){ howmany = (INT) ptrS->softpins[HOWMANY] ; max_soft = MAX( max_soft, howmany ) ; init_side_array( FALSE ) ; find_hardpin_side() ; } } } if( max_soft > 0 ){ placearrayS = (PINBOXPTR *) Yvector_alloc( 1, max_soft,sizeof(PINBOXPTR) ) ; greedy_posS = (INT *) Yvector_alloc( 0, max_soft,sizeof(INT) ) ; } } /* end set_up_pinplace */ static init_side_array( newVertFlag ) BOOL newVertFlag ; /* use _new fields if true use x, y otherwise */ { INT i ; /* counter */ INT j ; /* counter */ INT *xvert ; /* the xvertices of cell */ INT *yvert ; /* the yvertices of cell */ VERTBOXPTR vert ; /* the cells vertices */ SIDEBOXPTR this_side ; /* current side pointer */ SIDEBOXPTR next_side ; /* next side pointer */ BOUNBOXPTR bounptr ; /* bounding box pointer */ vert = ptrS->vertices ; if( newVertFlag ){ xvert = vert->x_new ; yvert = vert->y_new ; } else { xvert = vert->x ; yvert = vert->y ; } /* setup translation of output points */ bounptr = ptrS->bounBox[0] ; /* now init the translation routines using bounding box */ Ytrans_init( bounptr->l,bounptr->b,bounptr->r,bounptr->t, ptrS->orient ) ; for( i = 1; i <= ptrS->numsides; i++ ){ this_side = sideArrayS[i] ; /* rel position is a macro which calculates */ /* absolute pin loc - defined in relpos.h */ REL_POST( ptrS->orient, this_side->x, this_side->y, /* result */ xvert[i], yvert[i], /* cell relative */ ptrS->xcenter, ptrS->ycenter ) ; /* cell center */ } /* now determine the direction and path for edge */ for( i = 1, j = 1; i <= ptrS->numsides; i++ ){ if( ++j > ptrS->numsides ){ j = 1 ; } this_side = sideArrayS[i] ; next_side = sideArrayS[j] ; if( this_side->x == next_side->x ){ if( this_side->y < next_side->y ){ this_side->direction = UP ; this_side->start = this_side->y ; this_side->end = next_side->y ; } else { this_side->direction = DOWN ; this_side->start = next_side->y ; this_side->end = this_side->y ; } this_side->loc = this_side->x ; } else if( this_side->y == next_side->y ){ if( this_side->x < next_side->x ){ this_side->direction = RIGHT ; this_side->start = this_side->x ; this_side->end = next_side->x ; } else { this_side->direction = LEFT ; this_side->start = next_side->x ; this_side->end = this_side->x ; } this_side->loc = this_side->y ; } this_side->length = this_side->end - this_side->start ; D( "twmc/sidearray", fprintf( stderr, "x:%d y:%d start:%d end:%d loc:%d len:%d D:%d\n", this_side->x, this_side->y, this_side->start, this_side->end, this_side->loc, this_side->length, this_side->direction ) ; ) ; } } /* end init_side_array() */ /* find the side that the hardpin is nearest. */ static find_hardpin_side() { INT i ; /* counter */ INT x, y ; /* pin x,y location */ INT dist ; /* find the best place for pin */ INT dist1 ; /* determine dist for pin */ INT howmany ; /* # of pingroup children */ INT bestdist ; /* determine dist for pin */ INT bestside ; /* best side for the pin */ BOOL intersect ; /* true if ideal pt intersects side */ PINBOXPTR pin ; /* the current pin */ SOFTBOXPTR sptr ; /* soft information */ SIDEBOXPTR sideptr ; /* current side */ for( pin = ptrS->pinptr; pin; pin = pin->nextpin ){ sptr = pin->softinfo ; if( pin->type != HARDPINTYPE ){ continue ; } x = pin->txpos + ptrS->xcenter ; y = pin->typos + ptrS->ycenter ; bestdist = INT_MAX ; for( i = 1; i <= ptrS->numsides; i++ ){ sideptr = sideArrayS[i] ; intersect = FALSE ; if( sideptr->direction==LEFT || sideptr->direction==RIGHT ){ if( sideptr->start <= x && x <= sideptr->end ){ /* side is encompasses the point */ dist = ABS( y - sideptr->loc ) ; intersect = TRUE ; } else { /* check the corner point */ dist = ABS( sideptr->x - x ) ; dist1 = ABS( sideptr->y - y ) ; /* find Manhattan dist */ dist += dist1 ; } } else { /* else vertical side */ if( sideptr->start <= y && y <= sideptr->end ){ /* side is encompasses the point */ dist = ABS( x - sideptr->loc ) ; intersect = TRUE ; } else { /* check the corner point */ dist = ABS( sideptr->x - x ) ; dist1 = ABS( sideptr->y - y ) ; /* find Manhattan dist */ dist += dist1 ; } } if( dist < bestdist || (dist == bestdist && intersect) ){ bestdist = dist ; bestside = i ; } } /* end loop on number of sides */ /* now that we know the best side save it */ sptr->side = bestside ; } /* end loop on hardpins */ } /* end find_hardpin_side() */ update_pins( initialFlag ) /* initialize pin placement */ BOOL initialFlag ;/* if TRUE set all fields;if FALSE update orig fields */ { INT howmany ; /* number of cells with soft pins */ INT i ; /* counter */ INT orient ; /* cell orientation */ INT inst ; /* current instance */ CELLBOXPTR cellptr ; /* current cell */ PINBOXPTR pin ; /* current pin */ SOFTBOXPTR spin ; /* current soft pin information */ if( numsoftG > 0 || numstdcellG > 0 ){ howmany = (INT) softPinArrayG[HOWMANY] ; for( i = 1; i <= howmany; i++ ){ cellptr = softPinArrayG[i] ; placepin( cellptr->cellnum, FALSE ) ; inst = cellptr->cur_inst ; orient = cellptr->orient ; for( pin = cellptr->pinptr; pin ; pin = pin->nextpin ){ if( initialFlag ){ pin->txpos_orig[inst] = pin->txpos = pin->txpos_new ; pin->typos_orig[inst] = pin->typos = pin->typos_new ; } else { pin->txpos_orig[inst] = pin->txpos ; pin->typos_orig[inst] = pin->typos ; } /* rel pos is a macro which calculates */ /* absolute pin location */ /* defined in relpos.h */ REL_POS( orient, pin->xpos, pin->ypos, /* result */ pin->txpos, pin->typos, /* cell relative */ cellptr->xcenter, cellptr->ycenter );/* cell center */ } D( "initial_pinplace", for( pin = cellptr->pinptr; pin ; pin = pin->nextpin ){ spin = pin->softinfo ; fprintf( stderr, "pin:%10s signal:%8s side:%d tx:%d x:%d ", pin->pinname, netarrayG[pin->net]->nname, spin->side, pin->txpos, pin->xpos ) ; fprintf( stderr, "ty:%d y:%d pintype:%d\n", pin->typos, pin->ypos, pin->type ) ; } /* end for loop on pins */ fprintf( stderr, "\n\n" ) ; ) ; /* end of debug */ } /* loop on cells with softpins */ } /* end test on existence of soft cells */ } /* initial pinplace */ set_pin_verbosity( flag ) BOOL flag ; { tell_overflowS = flag ; } /* end set_pin_verbosity */ /* **************************************************************** */ /* THE FUNCTIONS BELOW ARE USED FOR THE WIRE ESTIMATOR. WE TRY TO */ /* SHARE CODE WITH THE PLACEPIN FUNCTIONS. ******* */ INT *find_pin_sides( cell ) INT cell ; { INT i ; /* counter */ INT x, y ; /* pin x,y location */ INT dist ; /* find the best place for pin */ INT dist1 ; /* determine dist for pin */ INT howmany ; /* # of pingroup children */ INT bestdist ; /* determine dist for pin */ INT bestside ; /* best side for the pin */ INT *pins_on_a_side ; /* number of pins on each side */ BOOL intersect ; /* true if ideal pt intersects side */ PINBOXPTR pin ; /* the current pin */ SIDEBOXPTR sideptr ; /* current side */ ptrS = cellarrayG[cell] ; if( ptrS->numpins <= 0 ){ return( NULL ) ; /* no work to do */ } /* allocate space for pin counter */ pins_on_a_side = (INT *) Yvector_calloc(1,ptrS->numsides,sizeof(INT)) ; /** DETERMINE THE BOUNDARY OF THE CURRENT CELL **/ init_side_array( FALSE ) ; for( pin = ptrS->pinptr; pin; pin = pin->nextpin ){ x = pin->xpos ; y = pin->ypos ; bestdist = INT_MAX ; for( i = 1; i <= ptrS->numsides; i++ ){ sideptr = sideArrayS[i] ; intersect = FALSE ; if( sideptr->direction==LEFT || sideptr->direction==RIGHT ){ if( sideptr->start <= x && x <= sideptr->end ){ /* side is encompasses the point */ dist = ABS( y - sideptr->loc ) ; intersect = TRUE ; } else { /* check the corner point */ dist = ABS( sideptr->x - x ) ; dist1 = ABS( sideptr->y - y ) ; /* find Manhattan dist */ dist += dist1 ; } } else { /* else vertical side */ if( sideptr->start <= y && y <= sideptr->end ){ /* side is encompasses the point */ dist = ABS( x - sideptr->loc ) ; intersect = TRUE ; } else { /* check the corner point */ dist = ABS( sideptr->x - x ) ; dist1 = ABS( sideptr->y - y ) ; /* find Manhattan dist */ dist += dist1 ; } } if( dist < bestdist || (dist == bestdist && intersect) ){ bestdist = dist ; bestside = i ; } } /* end loop on number of sides */ pins_on_a_side[bestside]++ ; } /* end loop on pins */ return( pins_on_a_side ) ; } /* end find_pinsides() */ #include /* given a routing tile edge find matching side */ INT find_tile_side( center, loc, direction ) INT center, loc, direction ; { INT i ; /* traverse the sides of cell */ SIDEBOXPTR this_side ; /* current side pointer */ for( i = 1; i <= ptrS->numsides; i++ ){ this_side = sideArrayS[i] ; if( direction == TILEL || direction == TILER ){ if( this_side->direction == UP || this_side->direction == DOWN ){ if( this_side->loc == loc && this_side->start <= center && center <= this_side->end ){ return( i ) ; } } } else { /* TILET or TILEB */ if( this_side->direction == LEFT || this_side->direction == RIGHT ){ if( this_side->loc == loc && this_side->start <= center && center <= this_side->end ){ return( i ) ; } } } } return( 0 ) ; } /* end find_tile_side */ init_wire_est() { INT i ; /* counter */ INT j ; /* counter */ INT maxsides ; /* the max numsides over all cells */ INT numinst ; /* the number of instances for cell */ INSTBOXPTR instptr ; /* instance information */ maxsides = 0 ; for( i = 1; i <= numcellsG ; i++ ){ ptrS = cellarrayG[i] ; if( instptr = ptrS->instptr ){ numinst = ptrS->instptr->numinstances ; for( j = 0; j < numinst ; j++ ){ maxsides = MAX( maxsides, instptr->numsides[j] ) ; } } else { maxsides = MAX( maxsides, ptrS->numsides ) ; } } if( sideArrayS ){ if( maxsides > maxsideS ){ sideArrayS = (SIDEBOXPTR *) Yvector_realloc(sideArrayS,1,maxsides,sizeof(SIDEBOXPTR)); for( i = maxsideS+1; i <= maxsides ; i++ ){ sideArrayS[i] = (SIDEBOXPTR)Ysafe_malloc(sizeof(SIDEBOX)); } } } else { sideArrayS = (SIDEBOXPTR *) Yvector_alloc(1,maxsides,sizeof(SIDEBOXPTR)); for( i = 1; i <= maxsides ; i++ ){ sideArrayS[i] = (SIDEBOXPTR)Ysafe_malloc(sizeof(SIDEBOX)); } } } /* end init_wire_est() */ /* ***************************************************************** */ #ifdef DEBUG print_pins( message, array, howmany ) char *message ; PINBOXPTR *array ; INT howmany ; { INT i ; PINBOXPTR ptr ; SOFTBOXPTR sptr ; fprintf( stderr, "\n%s\n", message ) ; /* now print them out */ for( i = 1 ; i <= howmany; i++ ){ ptr = array[i] ; sptr = ptr->softinfo ; fprintf( stderr, "pin:%s pos:%d tie:%d type:%d side:%d order:%d fixed:%d\n", ptr->pinname, ptr->txpos_new, ptr->typos_new, sptr->hierarchy, sptr->side, sptr->ordered, sptr->fixed ) ; } fprintf( stderr, "\n" ) ; /* G( process_graphics() ) ; */ } /* end print_pins */ #endif /* DEBUG */ graywolf-0.1.4+20170307gite1bf319/src/twmc/prboard.c000066400000000000000000000063611305746555600213300ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: prboard.c DESCRIPTION:print board routine CONTENTS: config1( ) DATE: Jan 30, 1988 REVISIONS: Jul 30, 1988 - fixed output for softcells and added gridding of cells for mighty interface. Mon Jan 7 18:31:00 CST 1991 - don't grid pads. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) prboard.c version 3.6 4/18/91" ; #endif #include #include grid_cells() { INT xcenter , ycenter, remainder ; INT cell ; INT old_left, old_bottom ;/* original xy center of cell before gridding */ INT delta_x, delta_y ; /* delta to move cell lower left to grid */ INT left, right, bottom, top ; /* sides of cell bounding box */ CELLBOXPTR cellptr ; BOUNBOXPTR bounptr ; if(!(gridCellsG)){ return ; } for( cell = 1 ; cell <= endsuperG ; cell++ ) { cellptr = cellarrayG[ cell ] ; if( cellptr->celltype == GROUPCELLTYPE || cellptr->celltype == SUPERCELLTYPE ) { /* avoid these cell types */ continue ; } bounptr = cellptr->bounBox[cellptr->orient] ; xcenter = cellptr->xcenter ; ycenter = cellptr->ycenter ; left = bounptr->l ; right = bounptr->r ; bottom = bounptr->b ; top = bounptr->t ; /* add offset */ old_left = left += xcenter ; old_bottom = bottom += ycenter ; /* grid cell data if requested */ /* set lower left corner to grid */ YforceGrid( &left, &bottom ) ; /* now modify center of cell coordinates */ delta_x = left - old_left ; delta_y = bottom - old_bottom ; cellptr->xcenter += delta_x ; cellptr->ycenter += delta_y ; } /* end for loop */ /* update all the costs */ funccostG = findcost() ; } /* end grid_cells */ graywolf-0.1.4+20170307gite1bf319/src/twmc/readcells.c000066400000000000000000001441141305746555600216340ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley) 01/20/90"; #endif #define YYBYACC 1 /* ----------------------------------------------------------------- FILE: readcells.c <- readcells_yacc <- readcells_lex DESCRIPTION:This file contains the grammar (BNF) for the TimberWolfMC input file parser. The rules for lex are in readcells_lex. The grammar for yacc is in readcells_yacc. The output of yacc (y.tab.c) is renamed to readcells.c CONTENTS: readcells( fp ) FILE *fp ; yyerror(s) char *s; yywrap() Note:readcells.c will also include the yacc parser. DATE: Aug 7, 1988 REVISIONS: Oct 27, 1988 - modified fixed and group cell code. Now accept designs without pads. Jan 29, 1989 - changed to YmsgG and added \n. Mar 6, 1989 - removed redundant string from padgroupname Mar 7, 1989 - now able to parse instance lists but don't process them. Mar 12, 1989 - changed group cell and supercell reference from integer to string to be easier for user. Mar 13, 1989 - added string to instance to tell them apart. May 7, 1989 - added layer to input format. Also fixed multiple equiv case. May 12, 1989 - added layer to data structures. Oct 2, 1989 - added warning messages for cells without pins. Feb 2, 1989 - added orient to input fields. Thu Dec 20 00:01:58 EST 1990 - now specify an ANALOGPIN. Dec 21, 1990 - rewrote pinrecord to make it more flexible and also changed NO_CROSS_UNDER to NO_LAYER_CHANGE. Sun Jan 20 21:34:36 PST 1991 - ported to AIX. Wed Jan 23 14:40:30 PST 1991 - made language context free. Mon Feb 4 02:17:24 EST 1991 - added new pinspace option and fixed fixCell problem. Wed Feb 13 23:56:34 EST 1991 - modified for new pad code. Thu Apr 18 01:44:14 EDT 1991 - renamed stdcell to cluster and reversed corners. Thu Aug 22 22:10:09 CDT 1991 - fixed problem with fixed cells moving during pairwise flips. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) readcells.y version 3.15 3/6/92" ; #endif #include #include #include #include #include /* redefine yacc and lex globals */ #undef REJECT /* undefine TWMC macro for lex's version */ #define YYDEBUG 1 /* condition compile for yacc debug */ /* #define LEXDEBUG 1 */ /* conditional compile for lex debug */ #ifdef LEXDEBUG /* two bugs in yale version of lex */ #define allprint(x) fprintf( stdout, "%c\n", x ) #define sprint(x) fprintf( stdout, "%s\n", x ) #endif static INT line_countS ; static char bufferS[LRECL] ; typedef union { INT ival ; char *string ; DOUBLE fval ; } YYSTYPE; #define INTEGER 257 #define STRING 258 #define FLOAT 259 #define ADDEQUIV 260 #define ASPLB 261 #define ASPUB 262 #define AT 263 #define CELLGROUP 264 #define CLASS 265 #define CONNECT 266 #define CORNERS 267 #define EQUIV 268 #define FIXED 269 #define FROM 270 #define HARDCELL 271 #define INSTANCE 272 #define LAYER 273 #define NAME 274 #define NEIGHBORHOOD 275 #define NONFIXED 276 #define NOPERMUTE 277 #define ORIENT 278 #define ORIENTATIONS 279 #define PAD 280 #define PADGROUP 281 #define PERMUTE 282 #define PIN 283 #define PINGROUP 284 #define RESTRICT 285 #define SIDE 286 #define SIDESPACE 287 #define SIGNAL 288 #define SOFTCELL 289 #define SOFTPIN 290 #define CLUSTER 291 #define SUPERGROUP 292 #define TIMING 293 #define CURRENT 294 #define KEEPOUT 295 #define NO_LAYER_CHANGE 296 #define POWER 297 #define YYERRCODE 256 short yylhs[] = { -1, 0, 0, 7, 7, 9, 9, 11, 11, 8, 8, 14, 14, 15, 15, 10, 10, 12, 12, 20, 20, 22, 22, 13, 13, 30, 30, 31, 31, 31, 23, 16, 16, 17, 18, 18, 19, 19, 29, 29, 29, 44, 44, 21, 21, 46, 2, 3, 35, 39, 39, 39, 41, 41, 43, 43, 24, 6, 47, 47, 26, 26, 27, 27, 48, 49, 49, 36, 36, 32, 33, 50, 50, 51, 51, 28, 28, 52, 52, 54, 56, 57, 57, 62, 63, 63, 59, 59, 60, 60, 61, 61, 53, 53, 64, 67, 67, 67, 68, 70, 69, 69, 71, 72, 5, 5, 34, 34, 73, 73, 74, 74, 75, 75, 55, 55, 76, 4, 4, 65, 65, 77, 77, 66, 66, 66, 38, 38, 38, 78, 78, 37, 37, 40, 40, 79, 79, 42, 42, 45, 45, 25, 25, 80, 80, 81, 82, 82, 58, 58, 1, 1, 1, }; short yylen[] = { 2, 2, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 2, 3, 1, 3, 5, 4, 2, 3, 1, 3, 7, 6, 5, 2, 6, 5, 4, 4, 3, 4, 2, 4, 4, 2, 13, 14, 8, 14, 1, 1, 1, 4, 3, 3, 2, 4, 2, 4, 2, 2, 2, 2, 3, 2, 2, 4, 3, 1, 1, 2, 0, 2, 4, 1, 1, 2, 1, 1, 1, 2, 1, 2, 6, 6, 2, 2, 2, 2, 3, 0, 2, 0, 2, 0, 1, 3, 4, 7, 1, 2, 1, 2, 1, 1, 2, 3, 4, 0, 1, 4, 5, 3, 3, 1, 2, 2, 2, 1, 2, 6, 0, 2, 0, 3, 1, 2, 0, 2, 3, 0, 2, 3, 1, 1, 0, 3, 1, 2, 2, 2, 1, 2, 1, 2, 0, 1, 1, 2, 5, 2, 3, 0, 2, 1, 1, 1, }; short yydefred[] = { 0, 0, 0, 0, 0, 0, 0, 5, 7, 8, 0, 0, 37, 151, 150, 152, 0, 40, 0, 0, 0, 1, 0, 11, 0, 0, 0, 0, 6, 15, 0, 0, 0, 45, 0, 0, 0, 19, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 12, 13, 0, 0, 55, 0, 53, 0, 16, 137, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 36, 38, 39, 0, 51, 0, 14, 0, 0, 133, 0, 0, 0, 0, 0, 138, 0, 0, 0, 139, 0, 58, 0, 30, 20, 0, 0, 144, 0, 0, 0, 0, 26, 48, 50, 49, 135, 136, 0, 0, 134, 68, 0, 54, 52, 61, 60, 64, 0, 34, 0, 0, 0, 140, 59, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 65, 0, 0, 46, 0, 0, 0, 0, 0, 75, 0, 0, 0, 0, 69, 0, 130, 129, 132, 0, 0, 66, 63, 0, 0, 0, 0, 0, 0, 76, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 73, 74, 0, 128, 62, 0, 0, 146, 0, 0, 0, 115, 81, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 47, 0, 0, 147, 0, 0, 149, 0, 0, 84, 0, 43, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, 85, 0, 0, 109, 108, 0, 112, 113, 0, 111, 121, 0, 0, 99, 0, 93, 0, 0, 0, 100, 0, 0, 0, 80, 118, 0, 89, 91, 79, 0, 0, 0, 106, 122, 125, 0, 0, 101, 98, 0, 0, 0, 116, 0, 0, 107, 0, 105, 102, 0, 0, 0, 94, 103, 0, 0, 0, 41, 0, 44, 42, }; short yydgoto[] = { 4, 230, 148, 215, 240, 292, 34, 5, 21, 6, 27, 7, 8, 9, 22, 49, 23, 51, 29, 10, 35, 36, 37, 67, 38, 70, 95, 128, 152, 11, 42, 43, 77, 184, 209, 24, 90, 118, 142, 52, 87, 30, 60, 31, 62, 99, 39, 65, 129, 145, 185, 186, 153, 188, 154, 175, 155, 179, 202, 222, 243, 272, 180, 204, 189, 213, 235, 259, 260, 261, 262, 263, 264, 210, 231, 232, 176, 255, 162, 88, 71, 72, 171, }; short yysindex[] = { -207, -145, -141, -233, 0, -203, -231, 0, 0, 0, -138, -138, 0, 0, 0, 0, -194, 0, -144, -134, -150, 0, -157, 0, -175, -137, -131, -242, 0, 0, -150, -130, -162, 0, -115, -129, -175, 0, -151, -189, -175, -114, -129, 0, -150, -150, -150, -128, -122, -127, 0, 0, -150, -126, 0, -125, 0, -124, 0, 0, -186, -182, -150, 0, -109, -106, -150, -175, -129, -117, -110, -151, 0, -100, -99, -129, -98, -151, -175, 0, 0, 0, -150, 0, -183, 0, -180, -223, 0, -97, -123, -150, -150, -118, 0, -241, -111, -94, 0, -150, 0, -92, 0, 0, -90, -241, 0, -102, -101, -91, -110, 0, 0, 0, 0, 0, 0, -116, -113, 0, 0, -113, 0, 0, 0, 0, 0, -85, 0, -104, -82, -89, 0, 0, -103, -105, -82, -82, -80, -241, -155, -77, 0, -105, 0, -209, -85, 0, -84, -82, -74, -88, -105, 0, -83, -239, -73, -70, 0, -193, 0, 0, 0, -71, -105, 0, 0, -209, -81, -67, -66, -65, -150, 0, -79, -83, 0, -64, -63, -96, -61, -72, -69, -75, -107, -193, 0, 0, 0, -76, 0, 0, -58, -68, 0, -54, -78, -150, 0, 0, 0, -55, -62, -52, -51, -58, -58, -150, -150, -107, -150, 0, -60, -57, 0, -49, -58, 0, -150, -56, 0, -48, -53, 0, -45, 0, -43, -50, -177, -150, -178, -215, 0, -42, -41, -192, -47, -38, -56, -37, -36, 0, -35, -46, 0, -39, -150, 0, 0, -215, 0, 0, -57, 0, 0, -32, -31, 0, -40, 0, -33, -33, -76, 0, -76, -82, -34, 0, 0, -24, 0, 0, 0, -82, -56, -57, 0, 0, 0, -150, -33, 0, 0, -44, -20, -82, 0, -18, -96, 0, -56, 0, 0, -30, -16, -27, 0, 0, -58, -25, -58, 0, -58, 0, 0, }; short yyrindex[] = { 0, 0, 0, 0, 0, 216, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 598, 0, 0, -19, 0, 0, 0, 621, 0, 0, 0, 0, 0, 0, 247, 0, 0, 0, 207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 629, 0, 0, -17, 0, 0, 0, 635, 0, -19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 544, 0, 0, 0, 0, 0, 0, 0, 21, 0, 495, 0, 0, 0, 0, 0, 0, 548, 0, 311, 0, 0, 0, 0, 574, 0, 0, 0, 57, 25, 0, 0, 495, 0, 0, 0, -250, 0, 0, 0, 370, 0, 0, 0, 32, 0, 0, 0, 0, 584, 227, 0, 0, 0, 213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 1, 0, 0, 0, 0, 588, 0, 0, 0, 275, 0, 0, 0, 0, 0, -8, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 509, 0, 0, 0, 428, 0, 0, -179, 0, 0, 0, 0, 289, 0, 0, 0, 0, 0, 509, 0, 0, 538, 0, 0, 166, 325, 0, 0, 0, 442, 466, 399, 0, 356, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 538, 0, 0, 0, 0, 480, 0, 0, 413, 0, 0, 0, 0, 180, 0, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; short yygindex[] = { 0, 903, -132, -196, -235, 0, 0, 0, 0, 0, 0, 245, 0, 0, 0, 0, 230, 204, 228, 0, 218, 246, 189, -28, -11, 181, -59, -93, 116, 0, 220, 183, 0, 0, 0, 0, -86, 172, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 0, 81, -133, 0, 0, 0, 0, 0, -21, 0, 0, 0, 0, 0, 0, -208, -222, 0, 0, 10, 0, -195, 0, 59, 45, -166, 101, 0, 0, 190, 0, 208, 0, }; #define YYTABLESIZE 1182 short yytable[] = { 41, 82, 126, 267, 156, 157, 3, 35, 4, 225, 226, 105, 135, 53, 78, 145, 126, 169, 177, 173, 237, 32, 25, 252, 19, 31, 187, 131, 178, 41, 276, 173, 148, 25, 13, 14, 15, 126, 127, 288, 1, 275, 13, 14, 15, 145, 159, 78, 165, 131, 26, 139, 187, 289, 282, 297, 283, 127, 2, 166, 3, 26, 117, 86, 1, 253, 281, 41, 257, 89, 212, 13, 14, 15, 73, 96, 258, 20, 117, 93, 44, 191, 2, 253, 3, 281, 74, 97, 117, 115, 151, 250, 32, 88, 113, 63, 116, 183, 251, 114, 247, 160, 301, 161, 303, 248, 304, 13, 14, 15, 56, 12, 13, 14, 15, 17, 13, 14, 15, 54, 13, 14, 15, 20, 48, 56, 13, 14, 15, 32, 45, 33, 117, 284, 83, 13, 14, 15, 124, 125, 46, 287, 64, 66, 69, 61, 82, 76, 100, 91, 92, 101, 89, 294, 48, 93, 104, 107, 108, 130, 120, 109, 117, 131, 150, 133, 120, 134, 136, 137, 140, 138, 144, 168, 141, 146, 147, 208, 151, 158, 148, 149, 163, 170, 181, 174, 172, 182, 190, 192, 193, 194, 195, 199, 200, 197, 203, 201, 205, 207, 214, 206, 216, 217, 220, 223, 224, 67, 236, 212, 218, 241, 244, 119, 245, 254, 2, 239, 256, 266, 268, 269, 291, 265, 270, 277, 233, 70, 278, 9, 234, 273, 221, 286, 279, 258, 285, 293, 246, 295, 298, 299, 117, 300, 242, 302, 141, 10, 142, 117, 271, 28, 50, 85, 68, 58, 103, 40, 110, 164, 75, 111, 121, 143, 167, 82, 211, 296, 229, 82, 280, 35, 82, 82, 249, 123, 198, 119, 0, 106, 0, 82, 82, 126, 82, 82, 3, 35, 4, 90, 82, 82, 82, 82, 82, 82, 148, 82, 82, 35, 148, 32, 32, 148, 148, 31, 31, 131, 131, 0, 131, 77, 148, 148, 131, 148, 148, 126, 126, 0, 126, 148, 148, 148, 148, 124, 148, 86, 148, 148, 131, 86, 0, 0, 86, 86, 131, 127, 127, 0, 127, 0, 0, 86, 86, 0, 86, 86, 0, 0, 0, 0, 86, 86, 86, 86, 119, 88, 0, 86, 86, 88, 0, 0, 88, 88, 0, 0, 0, 0, 78, 56, 0, 88, 88, 56, 88, 88, 0, 0, 0, 0, 88, 88, 88, 88, 0, 0, 56, 88, 56, 56, 117, 56, 0, 56, 117, 56, 0, 119, 117, 0, 0, 117, 117, 56, 0, 0, 0, 0, 0, 0, 117, 104, 0, 117, 117, 117, 0, 117, 0, 117, 117, 117, 117, 117, 120, 0, 92, 0, 120, 0, 120, 0, 120, 0, 0, 120, 120, 0, 148, 0, 95, 0, 148, 0, 120, 0, 148, 120, 120, 148, 148, 120, 0, 120, 120, 120, 120, 0, 148, 0, 0, 148, 148, 148, 97, 148, 0, 148, 148, 148, 148, 119, 0, 0, 0, 119, 0, 0, 96, 119, 0, 0, 119, 119, 0, 67, 67, 0, 67, 70, 67, 119, 67, 67, 119, 119, 70, 70, 119, 0, 119, 119, 119, 119, 117, 70, 117, 119, 117, 70, 0, 117, 117, 0, 70, 0, 70, 70, 0, 0, 117, 0, 0, 117, 117, 117, 0, 0, 0, 117, 117, 117, 117, 123, 0, 0, 123, 123, 0, 0, 0, 123, 22, 0, 123, 123, 21, 0, 0, 0, 0, 90, 0, 123, 0, 90, 123, 123, 90, 90, 0, 0, 123, 123, 123, 123, 0, 90, 90, 0, 90, 90, 29, 77, 0, 0, 90, 90, 90, 90, 77, 77, 28, 124, 0, 0, 27, 124, 0, 77, 77, 124, 77, 77, 124, 124, 17, 0, 77, 77, 77, 77, 0, 124, 0, 0, 124, 124, 0, 0, 0, 0, 124, 124, 124, 124, 0, 0, 119, 23, 119, 0, 119, 0, 0, 119, 119, 18, 0, 0, 0, 0, 78, 24, 119, 0, 0, 119, 119, 78, 78, 0, 0, 119, 119, 119, 119, 0, 78, 78, 0, 78, 78, 0, 0, 0, 0, 78, 78, 78, 78, 119, 0, 0, 0, 119, 0, 0, 119, 119, 0, 0, 0, 0, 0, 104, 0, 119, 0, 104, 119, 119, 104, 104, 0, 0, 119, 119, 119, 119, 92, 104, 0, 0, 104, 104, 0, 92, 92, 0, 104, 104, 104, 104, 95, 0, 92, 0, 0, 92, 92, 95, 95, 0, 0, 92, 92, 92, 92, 0, 95, 0, 0, 95, 95, 0, 0, 0, 97, 95, 95, 95, 95, 0, 0, 97, 97, 0, 0, 0, 0, 0, 96, 0, 97, 0, 0, 97, 97, 96, 96, 0, 0, 97, 97, 97, 97, 67, 96, 0, 0, 96, 96, 0, 67, 67, 0, 96, 96, 96, 96, 119, 0, 67, 0, 0, 67, 0, 119, 119, 0, 0, 67, 67, 67, 67, 0, 119, 0, 0, 0, 119, 0, 0, 119, 0, 119, 0, 119, 119, 123, 0, 0, 0, 0, 0, 22, 123, 123, 0, 21, 0, 0, 22, 22, 0, 123, 21, 21, 0, 123, 0, 22, 0, 0, 123, 21, 123, 123, 0, 0, 22, 0, 22, 22, 21, 29, 21, 21, 0, 0, 0, 0, 29, 29, 0, 28, 0, 0, 0, 27, 0, 29, 28, 28, 0, 0, 27, 27, 0, 17, 29, 28, 29, 29, 0, 27, 17, 0, 0, 0, 28, 0, 28, 28, 27, 17, 27, 27, 0, 0, 0, 0, 23, 0, 17, 0, 17, 17, 0, 23, 18, 0, 0, 0, 0, 0, 24, 18, 23, 0, 0, 16, 18, 24, 0, 0, 18, 23, 0, 23, 23, 0, 24, 0, 0, 18, 0, 18, 18, 0, 47, 24, 0, 24, 24, 55, 57, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 80, 81, 0, 84, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 94, 0, 98, 0, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 86, 0, 0, 0, 122, 123, 0, 0, 0, 0, 0, 0, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, }; short yycheck[] = { 11, 0, 0, 238, 136, 137, 0, 0, 0, 205, 206, 70, 105, 24, 42, 265, 257, 149, 257, 152, 216, 0, 264, 231, 257, 0, 159, 0, 267, 40, 252, 164, 0, 264, 257, 258, 259, 0, 279, 274, 271, 249, 257, 258, 259, 295, 139, 75, 257, 0, 292, 110, 185, 275, 262, 290, 264, 0, 289, 145, 291, 292, 285, 0, 271, 231, 261, 78, 260, 278, 285, 257, 258, 259, 263, 257, 268, 280, 257, 265, 274, 167, 289, 249, 291, 280, 275, 269, 267, 269, 283, 269, 267, 0, 277, 257, 276, 290, 276, 282, 277, 256, 298, 258, 300, 282, 302, 257, 258, 259, 0, 256, 257, 258, 259, 256, 257, 258, 259, 256, 257, 258, 259, 280, 281, 256, 257, 258, 259, 267, 274, 269, 0, 265, 256, 257, 258, 259, 256, 257, 274, 273, 257, 272, 295, 275, 274, 261, 257, 274, 274, 257, 278, 285, 281, 265, 273, 257, 257, 270, 257, 259, 285, 257, 267, 257, 0, 257, 270, 270, 286, 262, 257, 257, 287, 279, 258, 284, 283, 259, 0, 270, 259, 257, 257, 268, 274, 257, 259, 270, 257, 257, 257, 257, 257, 274, 257, 293, 270, 274, 258, 270, 270, 257, 259, 257, 257, 0, 257, 285, 288, 259, 257, 0, 257, 257, 0, 273, 259, 257, 257, 257, 266, 270, 259, 257, 286, 0, 259, 0, 287, 270, 294, 257, 274, 268, 270, 257, 288, 257, 270, 257, 0, 270, 297, 270, 265, 0, 265, 257, 296, 6, 22, 49, 36, 27, 67, 11, 77, 143, 40, 78, 90, 121, 146, 264, 185, 288, 209, 268, 260, 264, 271, 272, 229, 0, 175, 87, -1, 71, -1, 280, 281, 281, 283, 284, 280, 280, 280, 0, 289, 290, 291, 292, 293, 294, 264, 296, 297, 292, 268, 280, 281, 271, 272, 280, 281, 280, 281, -1, 283, 0, 280, 281, 287, 283, 284, 280, 281, -1, 283, 289, 290, 291, 292, 0, 294, 264, 296, 297, 281, 268, -1, -1, 271, 272, 287, 280, 281, -1, 283, -1, -1, 280, 281, -1, 283, 284, -1, -1, -1, -1, 289, 290, 291, 292, 0, 264, -1, 296, 297, 268, -1, -1, 271, 272, -1, -1, -1, -1, 0, 261, -1, 280, 281, 265, 283, 284, -1, -1, -1, -1, 289, 290, 291, 292, -1, -1, 278, 296, 280, 281, 260, 283, -1, 285, 264, 287, -1, 0, 268, -1, -1, 271, 272, 295, -1, -1, -1, -1, -1, -1, 280, 0, -1, 283, 284, 285, -1, 287, -1, 289, 290, 291, 292, 293, 260, -1, 0, -1, 264, -1, 266, -1, 268, -1, -1, 271, 272, -1, 260, -1, 0, -1, 264, -1, 280, -1, 268, 283, 284, 271, 272, 287, -1, 289, 290, 291, 292, -1, 280, -1, -1, 283, 284, 285, 0, 287, -1, 289, 290, 291, 292, 260, -1, -1, -1, 264, -1, -1, 0, 268, -1, -1, 271, 272, -1, 280, 281, -1, 283, 264, 285, 280, 287, 0, 283, 284, 271, 272, 287, -1, 289, 290, 291, 292, 264, 280, 266, 0, 268, 284, -1, 271, 272, -1, 289, -1, 291, 292, -1, -1, 280, -1, -1, 283, 284, 285, -1, -1, -1, 289, 290, 291, 292, 260, -1, -1, 0, 264, -1, -1, -1, 268, 0, -1, 271, 272, 0, -1, -1, -1, -1, 264, -1, 280, -1, 268, 283, 284, 271, 272, -1, -1, 289, 290, 291, 292, -1, 280, 281, -1, 283, 284, 0, 264, -1, -1, 289, 290, 291, 292, 271, 272, 0, 260, -1, -1, 0, 264, -1, 280, 281, 268, 283, 284, 271, 272, 0, -1, 289, 290, 291, 292, -1, 280, -1, -1, 283, 284, -1, -1, -1, -1, 289, 290, 291, 292, -1, -1, 264, 0, 266, -1, 268, -1, -1, 271, 272, 0, -1, -1, -1, -1, 264, 0, 280, -1, -1, 283, 284, 271, 272, -1, -1, 289, 290, 291, 292, -1, 280, 281, -1, 283, 284, -1, -1, -1, -1, 289, 290, 291, 292, 264, -1, -1, -1, 268, -1, -1, 271, 272, -1, -1, -1, -1, -1, 264, -1, 280, -1, 268, 283, 284, 271, 272, -1, -1, 289, 290, 291, 292, 264, 280, -1, -1, 283, 284, -1, 271, 272, -1, 289, 290, 291, 292, 264, -1, 280, -1, -1, 283, 284, 271, 272, -1, -1, 289, 290, 291, 292, -1, 280, -1, -1, 283, 284, -1, -1, -1, 264, 289, 290, 291, 292, -1, -1, 271, 272, -1, -1, -1, -1, -1, 264, -1, 280, -1, -1, 283, 284, 271, 272, -1, -1, 289, 290, 291, 292, 264, 280, -1, -1, 283, 284, -1, 271, 272, -1, 289, 290, 291, 292, 264, -1, 280, -1, -1, 283, -1, 271, 272, -1, -1, 289, 290, 291, 292, -1, 280, -1, -1, -1, 284, -1, -1, 287, -1, 289, -1, 291, 292, 264, -1, -1, -1, -1, -1, 264, 271, 272, -1, 264, -1, -1, 271, 272, -1, 280, 271, 272, -1, 284, -1, 280, -1, -1, 289, 280, 291, 292, -1, -1, 289, -1, 291, 292, 289, 264, 291, 292, -1, -1, -1, -1, 271, 272, -1, 264, -1, -1, -1, 264, -1, 280, 271, 272, -1, -1, 271, 272, -1, 264, 289, 280, 291, 292, -1, 280, 271, -1, -1, -1, 289, -1, 291, 292, 289, 280, 291, 292, -1, -1, -1, -1, 264, -1, 289, -1, 291, 292, -1, 271, 264, -1, -1, -1, -1, -1, 264, 271, 280, -1, -1, 1, 2, 271, -1, -1, 280, 289, -1, 291, 292, -1, 280, -1, -1, 289, -1, 291, 292, -1, 20, 289, -1, 291, 292, 25, 26, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 45, 46, -1, 48, -1, -1, -1, 52, -1, -1, -1, -1, -1, -1, -1, 60, -1, 62, -1, -1, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 82, -1, -1, -1, -1, 87, -1, -1, -1, 91, 92, -1, -1, -1, -1, -1, -1, 99, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 172, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 197, -1, -1, -1, -1, -1, -1, -1, -1, -1, 207, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, 218, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 246, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 279, }; #define YYFINAL 4 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 297 #if YYDEBUG char *yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"INTEGER","STRING","FLOAT", "ADDEQUIV","ASPLB","ASPUB","AT","CELLGROUP","CLASS","CONNECT","CORNERS","EQUIV", "FIXED","FROM","HARDCELL","INSTANCE","LAYER","NAME","NEIGHBORHOOD","NONFIXED", "NOPERMUTE","ORIENT","ORIENTATIONS","PAD","PADGROUP","PERMUTE","PIN","PINGROUP", "RESTRICT","SIDE","SIDESPACE","SIGNAL","SOFTCELL","SOFTPIN","CLUSTER", "SUPERGROUP","TIMING","CURRENT","KEEPOUT","NO_LAYER_CHANGE","POWER", }; char *yyrule[] = { "$accept : start_file", "start_file : core pads", "start_file : core", "core : corecells", "core : corecells cellgroups", "corecells : coretype", "corecells : corecells coretype", "coretype : customcell", "coretype : softcell", "pads : padcells", "pads : padcells padgroups", "padcells : padcell", "padcells : padcells padcell", "padgroups : padgroup", "padgroups : padgroups padgroup", "cellgroups : cellgroup", "cellgroups : cellgroups cellgroup", "customcell : cellname custom_instance_list", "customcell : cellname fixed custom_instance_list", "custom_instance_list : custom_instance", "custom_instance_list : custom_instance_list instance custom_instance", "custom_instance : corners keep_outs class orient hardpins", "custom_instance : corners keep_outs class orient", "softcell : softname soft_instance_list", "softcell : softname fixed soft_instance_list", "soft_instance_list : soft_instance", "soft_instance_list : soft_instance_list instance soft_instance", "soft_instance : corners aspect keep_outs class orient softpins pingroup", "soft_instance : corners aspect keep_outs class orient softpins", "soft_instance : corners aspect keep_outs class orient", "instance : INSTANCE string", "padcell : padname corners cur_orient restriction sidespace hardpins", "padcell : padname corners cur_orient restriction sidespace", "padgroup : padgroupname padgrouplist restriction sidespace", "cellgroup : supergroupname supergrouplist class orient", "cellgroup : cellgroupname neighborhood cellgrouplist", "cellname : HARDCELL string NAME string", "cellname : HARDCELL error", "softname : SOFTCELL string NAME string", "softname : CLUSTER INTEGER NAME string", "softname : SOFTCELL error", "neighborhood : NEIGHBORHOOD INTEGER FROM xloc INTEGER FROM yloc INTEGER FROM xloc INTEGER FROM yloc", "neighborhood : NEIGHBORHOOD FIXED INTEGER FROM xloc INTEGER FROM yloc INTEGER FROM xloc INTEGER FROM yloc", "fixed : fixedcontext AT INTEGER FROM xloc INTEGER FROM yloc", "fixed : fixedcontext NEIGHBORHOOD INTEGER FROM xloc INTEGER FROM yloc INTEGER FROM xloc INTEGER FROM yloc", "fixedcontext : FIXED", "xloc : STRING", "yloc : STRING", "padname : PAD string NAME string", "padgroupname : PADGROUP string PERMUTE", "padgroupname : PADGROUP string NOPERMUTE", "padgroupname : PADGROUP error", "supergroupname : SUPERGROUP string NAME string", "supergroupname : SUPERGROUP error", "cellgroupname : CELLGROUP string NAME string", "cellgroupname : CELLGROUP error", "corners : numcorners cornerpts", "numcorners : CORNERS INTEGER", "cornerpts : INTEGER INTEGER", "cornerpts : cornerpts INTEGER INTEGER", "class : CLASS INTEGER", "class : CLASS error", "orient : numorientations ORIENTATIONS orientlist cur_orient", "orient : ORIENTATIONS orientlist cur_orient", "numorientations : INTEGER", "orientlist : INTEGER", "orientlist : orientlist INTEGER", "cur_orient :", "cur_orient : ORIENT INTEGER", "aspect : ASPLB FLOAT ASPUB FLOAT", "softpins : softpinlist", "softpinlist : softtype", "softpinlist : softpinlist softtype", "softtype : pintype", "softtype : softpin", "hardpins : pintype", "hardpins : hardpins pintype", "pintype : pinrecord", "pintype : pinrecord equiv_list", "pinrecord : required_pinfo contour timing current power no_layer_change", "required_pinfo : PIN NAME string SIGNAL string layer", "contour : INTEGER INTEGER", "contour : num_corners pin_pts", "num_corners : CORNERS INTEGER", "pin_pts : INTEGER INTEGER", "pin_pts : pin_pts INTEGER INTEGER", "current :", "current : CURRENT FLOAT", "power :", "power : POWER FLOAT", "no_layer_change :", "no_layer_change : NO_LAYER_CHANGE", "softpin : softpin_info siderestriction pinspace", "softpin : softpin_info siderestriction pinspace softequivs", "softpin_info : SOFTPIN NAME string SIGNAL string layer timing", "softequivs : mc_equiv", "softequivs : mc_equiv user_equiv_list", "softequivs : user_equiv_list", "mc_equiv : addequiv siderestriction", "addequiv : ADDEQUIV", "user_equiv_list : user_equiv", "user_equiv_list : user_equiv_list user_equiv", "user_equiv : equiv_name siderestriction connect", "equiv_name : EQUIV NAME string layer", "connect :", "connect : CONNECT", "pingroup : pingroupname pingrouplist siderestriction pinspace", "pingroup : pingroup pingroupname pingrouplist siderestriction pinspace", "pingroupname : PINGROUP string PERMUTE", "pingroupname : PINGROUP string NOPERMUTE", "pingrouplist : pinset", "pingrouplist : pingrouplist pinset", "pinset : string FIXED", "pinset : string NONFIXED", "equiv_list : equiv", "equiv_list : equiv_list equiv", "equiv : EQUIV NAME string layer INTEGER INTEGER", "layer :", "layer : LAYER INTEGER", "siderestriction :", "siderestriction : RESTRICT SIDE side_list", "side_list : INTEGER", "side_list : side_list INTEGER", "pinspace :", "pinspace : SIDESPACE FLOAT", "pinspace : SIDESPACE FLOAT FLOAT", "sidespace :", "sidespace : SIDESPACE FLOAT", "sidespace : SIDESPACE FLOAT FLOAT", "sideplace : STRING", "sideplace : error", "restriction :", "restriction : RESTRICT SIDE sideplace", "padgrouplist : padset", "padgrouplist : padgrouplist padset", "padset : string FIXED", "padset : string NONFIXED", "supergrouplist : string", "supergrouplist : supergrouplist string", "cellgrouplist : string", "cellgrouplist : cellgrouplist string", "keep_outs :", "keep_outs : keep_out_list", "keep_out_list : keep_out", "keep_out_list : keep_out_list keep_out", "keep_out : KEEPOUT LAYER INTEGER CORNERS keep_pts", "keep_pts : INTEGER INTEGER", "keep_pts : keep_pts INTEGER INTEGER", "timing :", "timing : TIMING FLOAT", "string : STRING", "string : INTEGER", "string : FLOAT", }; #endif #define yyclearin (yychar=(-1)) #define yyerrok (yyerrflag=0) #ifdef YYSTACKSIZE #ifndef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #endif #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 500 #define YYMAXDEPTH 500 #endif #endif int yycnprs = 0; int yydebug; int yynerrs; int yyerrflag; int yychar; short *yyssp; YYSTYPE *yyvsp; YYSTYPE yyval; YYSTYPE yylval; short yyss[YYSTACKSIZE]; YYSTYPE yyvs[YYSTACKSIZE]; #define yystacksize YYSTACKSIZE #include "readcells_l.h" /* add readcells_l.h for debug purposes */ /* ********************* #include "readcells_l.h" *******************/ /* ********************* #include "readcells_l.h" *******************/ readcells( fp ) FILE *fp ; { #ifdef YYDEBUG extern int yydebug ; yydebug = FALSE ; #endif yyin = fp ; line_countS = 0 ; initCellInfo() ; /* parse input file using yacc */ yyparse(); cleanupReadCells() ; } /* end readcells */ yyerror(s) char *s; { sprintf(YmsgG,"problem reading %s.[m]cel:", cktNameG ); M( ERRMSG, "readcells", YmsgG ) ; sprintf(YmsgG, " line %d near '%s' : %s\n" , line_countS+1, yytext, s ); M( ERRMSG, NULL, YmsgG ) ; setErrorFlag() ; } yywrap() { return(1); } #define YYABORT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int yyparse() { register int yym, yyn, yystate; #if YYDEBUG register char *yys; extern char *getenv(); if (yys = getenv("YYDEBUG")) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = (-1); yyssp = yyss; yyvsp = yyvs; *yyssp = yystate = 0; yyloop: if (yyn = yydefred[yystate]) goto yyreduce; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, shifting to state %d\n", yystate, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; #ifdef lint goto yynewerror; #endif yynewerror: #if YYDEBUG { int test_state, i, expect, two_or_more ; char err_msg[BUFSIZ] ; if( yyname[yychar] ){ sprintf( err_msg, "Found %s.\nExpected ", yyname[yychar] ) ; two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } yyerror( err_msg ) ; if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } } else { sprintf( err_msg, "Found unknown token.\nExpected "); two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } yyerror( err_msg ) ; if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } } } #else yyerror("syntax error"); if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } #endif #ifdef lint goto yyerrlab; #endif yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, error recovery shifting\ to state %d\n", *yyssp, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("yydebug: error recovery discarding state %d\n", *yyssp); #endif if (yyssp <= yyss) goto yyabort; --yyssp; --yyvsp; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, error recovery discards token %d (%s)\n", yystate, yychar, yys); } #endif yychar = (-1); goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("yydebug: state %d, reducing by rule %d (%s)\n", yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; yyval = yyvsp[1-yym]; switch (yyn) { case 7: { endCell() ; } break; case 8: { endCell() ; } break; case 11: { endCell() ; } break; case 12: { endCell() ; } break; case 13: { endCell() ; } break; case 14: { endCell() ; } break; case 15: { endCell() ; } break; case 16: { endCell() ; } break; case 22: { sprintf(YmsgG, "cell at line %d does not have any pins\n", line_countS+1); M( WARNMSG,"readcells", YmsgG ) ; } break; case 29: { sprintf(YmsgG, "cell at line %d does not have any pins\n", line_countS+1); M( WARNMSG,"readcells", YmsgG ) ; } break; case 30: { endCell() ; add_instance( yyvsp[0].string ) ; } break; case 32: { sprintf(YmsgG, "pad at line %d does not have any pins\n", line_countS+1); M( WARNMSG,"readcells", YmsgG ) ; } break; case 36: { addCell( yyvsp[0].string, CUSTOMCELLTYPE ) ; } break; case 38: { addCell( yyvsp[0].string, SOFTCELLTYPE ) ; } break; case 39: { addCell( yyvsp[0].string, STDCELLTYPE ) ; } break; case 41: { /* group neighborhood is free to move */ /* we use fixCell to build group box */ fixCell( GROUPFLAG, yyvsp[-11].ival, yyvsp[-9].string, yyvsp[-8].ival, yyvsp[-6].string, yyvsp[-5].ival, yyvsp[-3].string, yyvsp[-2].ival, yyvsp[0].string ) ; addClass( --unique_classG ) ; } break; case 42: { /* group neighborhood is fixed */ /* we use fixCell to build group box */ fixCell( FIXEDGROUPFLAG, yyvsp[-11].ival, yyvsp[-9].string, yyvsp[-8].ival, yyvsp[-6].string, yyvsp[-5].ival, yyvsp[-3].string, yyvsp[-2].ival, yyvsp[0].string ) ; addClass( --unique_classG ) ; } break; case 43: { /* cell is fixed at a point */ fixCell( POINTFLAG, yyvsp[-5].ival, yyvsp[-3].string, yyvsp[-2].ival, yyvsp[0].string, 0, "L", 0, "B" ) ; addClass( --unique_classG ) ; } break; case 44: { /* cell is fixed within a fixed neighborhood */ fixCell( NEIGHBORHOODFLAG, yyvsp[-11].ival, yyvsp[-9].string, yyvsp[-8].ival, yyvsp[-6].string, yyvsp[-5].ival, yyvsp[-3].string, yyvsp[-2].ival, yyvsp[0].string ) ; addClass( --unique_classG ) ; } break; case 46: { yyval.string = yyvsp[0].string ; } break; case 47: { yyval.string = yyvsp[0].string ; } break; case 48: { addCell( yyvsp[0].string, PADCELLTYPE ) ; } break; case 49: { addCell( yyvsp[-1].string, PADGROUPTYPE ) ; setPermutation( TRUE ) ; } break; case 50: { addCell( yyvsp[-1].string, PADGROUPTYPE ) ; setPermutation( FALSE ) ; } break; case 52: { addCell( yyvsp[0].string, SUPERCELLTYPE ) ; /* initSuperGroup() ; */ } break; case 54: { addCell( yyvsp[0].string, GROUPCELLTYPE ) ; } break; case 56: { processCorners( yyvsp[-1].ival ) ; } break; case 57: { yyval.ival = yyvsp[0].ival ; } break; case 58: { addCorner( yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 59: { addCorner( yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 60: { addClass( yyvsp[0].ival ) ; } break; case 65: { /* first in the list is the initial orientation */ initOrient( yyvsp[0].ival ) ; } break; case 66: { addOrient( yyvsp[0].ival ) ; } break; case 68: { set_cur_orient( yyvsp[0].ival ) ; } break; case 69: { addAspectBounds( yyvsp[-2].fval, yyvsp[0].fval ) ; } break; case 70: { add_soft_array() ; } break; case 79: { process_pin() ; } break; case 80: { addPin( yyvsp[-3].string, yyvsp[-1].string, yyvsp[0].ival, HARDPINTYPE ) ; } break; case 81: { set_pin_pos( yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 83: { add_analog( yyvsp[0].ival ) ; } break; case 84: { add_pin_contour( yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 85: { add_pin_contour( yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 87: { add_current( yyvsp[0].fval ) ; } break; case 89: { add_power( yyvsp[0].fval ) ; } break; case 91: { no_layer_change() ; } break; case 94: { addPin( yyvsp[-4].string, yyvsp[-2].string, yyvsp[-1].ival, SOFTPINTYPE ) ; set_restrict_type( SOFTPINTYPE ) ; } break; case 98: { /* we are now done with addequiv types */ set_restrict_type( SOFTEQUIVTYPE ) ; } break; case 99: { set_restrict_type( ADDEQUIVTYPE ) ; addEquivPin( NULL, 0, 0, 0, ADDEQUIVTYPE ) ; } break; case 103: { addPin( yyvsp[-1].string, NULL, yyvsp[0].ival, SOFTEQUIVTYPE ) ; } break; case 104: { yyval.ival = FALSE ; } break; case 105: { yyval.ival = TRUE ; } break; case 108: { set_restrict_type( PINGROUPTYPE ) ; start_pin_group( yyvsp[-1].string, TRUE ) ; } break; case 109: { set_restrict_type( PINGROUPTYPE ) ; start_pin_group( yyvsp[-1].string, FALSE ) ; } break; case 112: { add2pingroup( yyvsp[-1].string, TRUE ) ; /* fixed */ } break; case 113: { add2pingroup( yyvsp[-1].string, FALSE ) ; /* nonfixed */ } break; case 116: { addEquivPin( yyvsp[-3].string, yyvsp[-2].ival, yyvsp[-1].ival, yyvsp[0].ival, HARDPINTYPE ) ; } break; case 117: { /* default any layer */ yyval.ival = 0 ; } break; case 118: { yyval.ival = yyvsp[0].ival ; } break; case 121: { addSideRestriction( yyvsp[0].ival ) ; } break; case 122: { addSideRestriction( yyvsp[0].ival ) ; } break; case 124: { add_pinspace( yyvsp[0].fval, yyvsp[0].fval ) ; } break; case 125: { add_pinspace( yyvsp[-1].fval, yyvsp[0].fval ) ; } break; case 127: { addSideSpace( yyvsp[0].fval, yyvsp[0].fval ) ; } break; case 128: { addSideSpace( yyvsp[-1].fval, yyvsp[0].fval ) ; } break; case 129: { addPadSide( yyvsp[0].string ) ; } break; case 135: { add2padgroup( yyvsp[-1].string, TRUE ) ; /* fixed */ } break; case 136: { add2padgroup( yyvsp[-1].string, FALSE ) ; /* nonfixed */ } break; case 139: { add_cell_to_group( yyvsp[0].string ) ; } break; case 140: { add_cell_to_group( yyvsp[0].string ) ; } break; case 150: { yyval.string = yyvsp[0].string ; } break; case 151: { /* convert integer to string */ /* this allows integers to be used as strings */ /* a kluge but timberwolf's old parser supported it */ sprintf( bufferS,"%d", yyvsp[0].ival ) ; /* now clone string */ yyval.string = (char *) Ystrclone( bufferS ) ; } break; case 152: { /* convert float to string */ /* this allows floats to be used as strings */ /* a kluge but timberwolf's old parser supported it */ sprintf( bufferS,"%f", yyvsp[0].fval ) ; /* now clone string */ yyval.string = (char *) Ystrclone( bufferS ) ; } break; } yyssp -= yym; yystate = *yyssp; yyvsp -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state 0 to\ state %d\n", YYFINAL); #endif yystate = YYFINAL; *++yyssp = YYFINAL; *++yyvsp = yyval; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state %d \ to state %d\n", *yyssp, yystate); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate; *++yyvsp = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: return (1); yyaccept: return (0); } graywolf-0.1.4+20170307gite1bf319/src/twmc/readcells.h000066400000000000000000000040401305746555600216320ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: custom_parser.h DESCRIPTION:This file redefines global variable of yacc and lex so that we can have more than one parser in TimberWolfMC. CONTENTS: macro redefinitions for parser in readcells. DATE: Aug 7, 1988 REVISIONS: ----------------------------------------------------------------- */ /* ***************************************************************** static char SccsId[] = "@(#) readcells.h version 3.4 3/6/92" ; ***************************************************************** */ #define yyact CUSTOM_yyact #define yyback CUSTOM_yyback #define yybgin CUSTOM_yybgin #define yychar CUSTOM_yychar #define yychk CUSTOM_yychk #define yycrank CUSTOM_yycrank #define yycnprs CUSTOM_yycnprs #define yydebug CUSTOM_yydebug #define yydef CUSTOM_yydef #define yyerrflag CUSTOM_yyerrflag #define yyerror CUSTOM_yyerror #define yyestate CUSTOM_yyestate #define yyexca CUSTOM_yyexca #define yyextra CUSTOM_yyextra #define yyfnd CUSTOM_yyfnd #define yyin CUSTOM_yyin #define yyinput CUSTOM_yyinput #define yyleng CUSTOM_yyleng #define yylex CUSTOM_yylex #define yylineno CUSTOM_yylineno #define yylook CUSTOM_yylook #define yylsp CUSTOM_yylsp #define yylstate CUSTOM_yylstate #define yylval CUSTOM_yylval #define yymatch CUSTOM_yymatch #define yymorfg CUSTOM_yymorfg #define yynerrs CUSTOM_yynerrs #define yyolsp CUSTOM_yyolsp #define yyout CUSTOM_yyout #define yyoutput CUSTOM_yyoutput #define yypact CUSTOM_yypact #define yyparse CUSTOM_yyparse #define yypgo CUSTOM_yypgo #define yyprevious CUSTOM_yyprevious #define yyreds CUSTOM_yyreds #define yyr1 CUSTOM_yyr1 #define yyr2 CUSTOM_yyr2 #define yysbuf CUSTOM_yysbuf #define yysptr CUSTOM_yysptr #define yysvec CUSTOM_yysvec #define yytchar CUSTOM_yytchar #define yytext CUSTOM_yytext #define yytoks CUSTOM_yytoks #define yytop CUSTOM_yytop #define yyunput CUSTOM_yyunput #define yyv CUSTOM_yyv #define yyval CUSTOM_yyval #define yyvstop CUSTOM_yyvstop #define yywrap CUSTOM_yywrap graywolf-0.1.4+20170307gite1bf319/src/twmc/readcells_l.h000066400000000000000000000403001305746555600221440ustar00rootroot00000000000000#ifdef linux #include #else # include "stdio.h" #endif # define U(x) ((x)&0377) # define NLSTATE yyprevious=YYNEWLINE # define BEGIN yybgin = yysvec + 1 + # define INITIAL 0 # define YYLERR yysvec # define YYSTATE (yyestate-yysvec-1) # define YYOPTIM 1 # define YYLMAX 200 # define output(c) putc(c,yyout) # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} # define yymore() (yymorfg=1) # define ECHO fprintf(yyout, "%s",yytext) # define REJECT { nstr = yyreject(); goto yyfussy;} int yyleng; extern char yytext[]; int yymorfg; extern char *yysptr, yysbuf[]; int yytchar; #ifdef linux FILE *yyin =NULL, *yyout =NULL; #else FILE *yyin ={stdin}, *yyout ={stdout}; #endif extern int yylineno; struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops;}; struct yysvf *yyestate; extern struct yysvf yysvec[], *yybgin; /* ----------------------------------------------------------------- FILE: readcells_lex DESCRIPTION:rules for lexical analyzer in readcell. This lexical analyzer uses a binary search to reduce the size of the f.a. generated by lex. Thanks to Gary Richey who showed me the trick. See chapter 3 of "Introduction to Compiler Construction with UNIX" by Schreiner & Friedman for more details. CONTENTS: lex rules - screen() DATE: Aug 07, 1988 - need to add SccsId in comments due to yacc static char SccsId[] = "@(#) readcells.l version 3.9 4/18/91" ; REVISIONS: Oct 6, 1988 - fixed sign mistake in INTEGER & FLOAT Feb 12, 1989 - added <> to alphanum to handle DEC case. Mar 7, 1989 - added instance keyword. Apr 4, 1989 - added comments over multiple lines. May 7, 1989 - added layer to keywords. Feb 7, 1990 - added orient keyword. Thu Dec 20 00:00:25 EST 1990 - updated FLOAT def. Dec 21, 1990 - changed NO_CROSS_UNDER to NO_LAYER_CHANGE Mon Jan 21 22:31:24 PST 1991 - added ASCII charset for alphanum. Wed Jan 23 14:39:34 PST 1991 - made language context free. Fri Mar 22 20:03:52 CST 1991 - made letter more general. Thu Apr 18 01:42:15 EDT 1991 - made pingroup standard with SC and rename stdcell to cluster. ----------------------------------------------------------------- */ #undef YYLMAX #define YYLMAX 2000 /* comments may be at most 2000 characters */ #define token(x) x /* makes it look like regular lex */ #define END(v) (v-1 + sizeof(v) / sizeof( v[0] ) ) /* for table lookup */ static INT screen() ; static INT check_line_count() ; # define YYNEWLINE 10 yylex(){ int nstr; extern int yyprevious; while((nstr = yylook()) >= 0) yyfussy: switch(nstr){ case 0: if(yywrap()) return(0); break; case 1: { /* C-style comments over multiple lines */ check_line_count(yytext) ; } break; case 2: { /* convert to an integer */ yylval.ival = atoi( yytext ) ; return (INTEGER); } break; case 3: { /* convert to an integer */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 4: { /* convert to an integer */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 5: { return( screen() ) ; } break; case 6: { line_countS++;} break; case 7: ; break; case 8: { return( token(yytext[0]) ) ;} break; case -1: break; default: fprintf(yyout,"bad switch yylook %d",nstr); } return(0); } /* end of yylex */ /* reserved word screener */ /* ----------------------------------------------------------------- The following is table of the reserved words - Table must be in alphabetical order for binary search to work properly. ----------------------------------------------------------------- */ static struct rw_table { /* reserved word table */ char *rw_name ; /* pattern */ INT rw_yylex ; /* lex token number */ } rwtable[] = { "addequiv", token(ADDEQUIV), "asplb", token(ASPLB), "aspub", token(ASPUB), "at", token(AT), "cellgroup", token(CELLGROUP), "class", token(CLASS), "cluster", token(CLUSTER), "connect", token(CONNECT), "corners", token(CORNERS), "current", token(CURRENT), "equiv", token(EQUIV), "fixed", token(FIXED), "from", token(FROM), "hardcell", token(HARDCELL), "instance", token(INSTANCE), "keepout", token(KEEPOUT), "layer", token(LAYER), "name", token(NAME), "neighborhood", token(NEIGHBORHOOD), "no_layer_change", token(NO_LAYER_CHANGE), "nonfixed", token(NONFIXED), "nopermute", token(NOPERMUTE), "orient", token(ORIENT), "orientations", token(ORIENTATIONS), "pad", token(PAD), "padgroup", token(PADGROUP), "permute", token(PERMUTE), "pin", token(PIN), "pin_group", token(PINGROUP), "power", token(POWER), "restrict", token(RESTRICT), "side", token(SIDE), "sidespace", token(SIDESPACE), "signal", token(SIGNAL), "softcell", token(SOFTCELL), "softpin", token(SOFTPIN), "supergroup", token(SUPERGROUP), "timing", token(TIMING) } ; static INT screen() { INT c ; struct rw_table *low = rwtable, /* ptr to beginning */ *mid , *high = END(rwtable) ; /* ptr to end */ /* binary search to look thru table to find pattern match */ while( low <= high){ mid = low + (high-low) / 2 ; if( (c = strcmp(mid->rw_name, yytext) ) == STRINGEQ){ return( mid->rw_yylex ) ; /* return token number */ } else if( c < 0 ){ low = mid + 1 ; } else { high = mid - 1 ; } } /* at this point we haven't found a match so we have a string */ /* save the string by making copy */ yylval.string = (char *) Ystrclone( yytext ) ; return (STRING); } /* end screen function */ static INT check_line_count( s ) char *s ; { if( s ){ if( strlen(s) >= YYLMAX ){ sprintf(YmsgG, "comment beginning at line %d ",line_countS+1 ); M( ERRMSG, "lex", YmsgG ) ; sprintf(YmsgG,"exceeds maximum allowed length:%d chars.\n", YYLMAX ); M( MSG, NULL, YmsgG ) ; setErrorFlag() ; } for( ;*s;s++ ){ if( *s == '\n'){ line_countS++; } } } } /* end check_line_count */ int yyvstop[] ={ 0, 7, 0, 7, 0, 8, 0, 7, 8, 0, 6, 0, 5, 8, 0, 5, 8, 0, 3, 5, 8, 0, 5, 8, 0, 2, 8, 0, 7, 0, 5, 0, 3, 5, 0, 2, 5, 0, 5, 0, 3, 5, 0, 2, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 4, 5, 0, 5, 0, 5, 0, 1, 5, 0, 1, 0, 5, 0, 1, 5, 0, 1, 0, 0}; # define YYTYPE unsigned char struct yywork { YYTYPE verify, advance; } yycrank[] ={ 0,0, 0,0, 1,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,4, 1,5, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 1,7, 9,15, 0,0, 1,8, 1,9, 1,10, 7,13, 0,0, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 20,20, 27,33, 28,34, 32,26, 33,27, 34,27, 0,0, 0,0, 1,6, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 10,16, 0,0, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 14,16, 10,18, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 15,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 15,19, 15,19, 0,0, 14,18, 0,0, 0,0, 0,0, 0,0, 0,0, 18,23, 0,0, 18,23, 0,0, 10,18, 18,24, 18,24, 18,24, 18,24, 18,24, 18,24, 18,24, 18,24, 18,24, 18,24, 15,20, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 15,21, 15,20, 14,18, 0,0, 15,20, 15,22, 15,20, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 21,26, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 21,26, 21,26, 15,20, 16,18, 17,16, 0,0, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 19,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 21,27, 19,25, 19,19, 17,18, 0,0, 19,19, 19,19, 19,19, 0,0, 21,28, 21,27, 16,18, 0,0, 21,27, 21,29, 21,27, 23,24, 23,24, 23,24, 23,24, 23,24, 23,24, 23,24, 23,24, 23,24, 23,24, 0,0, 0,0, 19,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 17,18, 21,27, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 24,24, 25,26, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 26,19, 0,0, 25,30, 25,26, 0,0, 0,0, 25,26, 25,31, 25,26, 26,25, 26,19, 30,19, 0,0, 26,19, 26,32, 26,19, 0,0, 0,0, 0,0, 0,0, 30,25, 30,19, 0,0, 0,0, 30,19, 30,35, 30,19, 0,0, 0,0, 25,26, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 26,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 30,19, 0,0, 0,0, 0,0, 0,0}; struct yysvf yysvec[] ={ 0, 0, 0, yycrank+-1, 0, yyvstop+1, yycrank+0, yysvec+1, yyvstop+3, yycrank+0, 0, yyvstop+5, yycrank+3, 0, yyvstop+7, yycrank+0, 0, yyvstop+10, yycrank+38, 0, yyvstop+12, yycrank+4, yysvec+6, yyvstop+15, yycrank+117, yysvec+6, yyvstop+18, yycrank+3, yysvec+6, yyvstop+22, yycrank+129, yysvec+6, yyvstop+25, yycrank+0, yysvec+4, yyvstop+28, yycrank+0, yysvec+6, yyvstop+30, yycrank+139, yysvec+6, yyvstop+32, yycrank+151, yysvec+6, yyvstop+35, yycrank+-208, 0, yyvstop+38, yycrank+209, yysvec+6, yyvstop+40, yycrank+233, yysvec+6, yyvstop+43, yycrank+183, yysvec+6, yyvstop+45, yycrank+-258, yysvec+15, 0, yycrank+-15, yysvec+15, yyvstop+47, yycrank+-266, 0, yyvstop+49, yycrank+0, yysvec+15, yyvstop+51, yycrank+267, yysvec+6, yyvstop+53, yycrank+288, yysvec+6, yyvstop+55, yycrank+-313, yysvec+21, 0, yycrank+-320, yysvec+15, 0, yycrank+-16, yysvec+15, yyvstop+58, yycrank+-17, yysvec+15, yyvstop+60, yycrank+0, yysvec+6, yyvstop+62, yycrank+-331, yysvec+15, 0, yycrank+0, 0, yyvstop+65, yycrank+18, 0, 0, yycrank+19, yysvec+6, yyvstop+67, yycrank+20, yysvec+6, yyvstop+69, yycrank+0, yysvec+32, yyvstop+72, 0, 0, 0}; struct yywork *yytop = yycrank+400; struct yysvf *yybgin = yysvec+1; char yymatch[] ={ 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 011 ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'*' ,'+' ,'!' ,'+' ,'.' ,'/' , '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , '0' ,'0' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 0}; char yyextra[] ={ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0}; /* ncform 4.1 83/08/11 */ int yylineno =1; # define YYU(x) x # define NLSTATE yyprevious=YYNEWLINE char yytext[YYLMAX]; struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; char yysbuf[YYLMAX]; char *yysptr = yysbuf; int *yyfnd; extern struct yysvf *yyestate; int yyprevious = YYNEWLINE; yylook(){ register struct yysvf *yystate, **lsp; register struct yywork *yyt; struct yysvf *yyz; int yych; struct yywork *yyr; # ifdef LEXDEBUG int debug; # endif char *yylastch; /* start off machines */ #ifdef linux if (yyin == NULL) yyin = stdin; if (yyout == NULL) yyout = stdout; #endif # ifdef LEXDEBUG debug = 0; # endif if (!yymorfg) yylastch = yytext; else { yymorfg=0; yylastch = yytext+yyleng; } for(;;){ lsp = yylstate; yyestate = yystate = yybgin; if (yyprevious==YYNEWLINE) yystate++; for (;;){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); # endif yyt = yystate->yystoff; if(yyt == yycrank){ /* may not be any transitions */ yyz = yystate->yyother; if(yyz == 0)break; if(yyz->yystoff == yycrank)break; } *yylastch++ = yych = input(); tryagain: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"unsigned char "); allprint(yych); putchar('\n'); } # endif yyr = yyt; if ( (long)yyt > (long)yycrank){ yyt = yyr + yych; if (yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } # ifdef YYOPTIM else if((long)yyt < (long)yycrank) { /* r < yycrank */ yyt = yyr = yycrank+(yycrank-yyt); # ifdef LEXDEBUG if(debug)fprintf(yyout,"compressed state\n"); # endif yyt = yyt + yych; if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } yyt = yyr + YYU(yymatch[yych]); # ifdef LEXDEBUG if(debug){ fprintf(yyout,"try fall back character "); allprint(YYU(yymatch[yych])); putchar('\n'); } # endif if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transition */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); # endif goto tryagain; } # endif else {unput(*--yylastch);break;} contin: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"state %d char ",yystate-yysvec-1); allprint(yych); putchar('\n'); } # endif ; } # ifdef LEXDEBUG if(debug){ fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); allprint(yych); putchar('\n'); } # endif while (lsp-- > yylstate){ *yylastch-- = 0; if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ yyolsp = lsp; if(yyextra[*yyfnd]){ /* must backup */ while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ lsp--; unput(*yylastch--); } } yyprevious = YYU(*yylastch); yylsp = lsp; yyleng = yylastch-yytext+1; yytext[yyleng] = 0; # ifdef LEXDEBUG if(debug){ fprintf(yyout,"\nmatch "); sprint(yytext); fprintf(yyout," action %d\n",*yyfnd); } # endif return(*yyfnd++); } unput(*yylastch); } if (yytext[0] == 0 /* && feof(yyin) */) { yysptr=yysbuf; return(0); } yyprevious = yytext[0] = input(); if (yyprevious>0) output(yyprevious); yylastch=yytext; # ifdef LEXDEBUG if(debug)putchar('\n'); # endif } } yyback(p, m) int *p; { if (p==0) return(0); while (*p) { if (*p++ == m) return(1); } return(0); } /* the following are only used in the lex library */ yyinput(){ #ifdef linux if (yyin == NULL) yyin = stdin; #endif return(input()); } yyoutput(c) int c; { #ifdef linux if (yyout == NULL) yyout = stdout; #endif output(c); } yyunput(c) int c; { unput(c); } graywolf-0.1.4+20170307gite1bf319/src/twmc/readnets.c000066400000000000000000000601311305746555600214770ustar00rootroot00000000000000/* * Copyright (C) 1988-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley) 01/20/90"; #endif #define YYBYACC 1 /* ----------------------------------------------------------------- FILE: readnets.c <- readnets_yacc <- readnets_lex DESCRIPTION:This file contains the grammar (BNF) for the TimberWolfMC input file parser for nets. The rules for lex are in readnets_lex. The grammar for yacc is in readnets_yacc. The output of yacc (y.tab.c) is renamed to readnets.c CONTENTS: readnets( fp ) FILE *fp ; yyerror(s) char *s; yywrap() Note:readcells.c will also include the yacc parser. DATE: Aug 7, 1988 REVISIONS: Jan 29, 1989 - changed to YmsgG and added \n's. Mar 01, 1989 - modified argument to exitPgm. Mar 10, 1989 - added INSTANCETYPE code. Mar 11, 1989 - added get_total_paths for new print_paths. Mar 16, 1989 - changed data structure of netlist. Apr 2, 1989 - removed instance type. Oct 2, 1989 - made .mnet file optional. Apr 23, 1990 - now avoid crash when faulty user input. Sun Dec 16 00:42:34 EST 1990 - moved functions to initnets.c and finalized analog input format. Sun Jan 20 21:34:36 PST 1991 - ported to AIX. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) readnets.y version 3.8 3/6/92" ; #endif #include #include #include #include #include /* redefine yacc and lex globals */ #undef REJECT /* undefine TWMC macro for lex's version */ #define YYDEBUG 1 /* condition compile for yacc debug */ static INT line_countS ; static char bufferS[LRECL] ; typedef union { INT ival ; char *string ; DOUBLE fval ; } YYSTYPE; #define INTEGER 257 #define STRING 258 #define FLOAT 259 #define CAP_MATCH 260 #define CAP_UPPER_BOUND 261 #define COLON 262 #define COMMON_POINT 263 #define NET 264 #define NET_CAP_MATCH 265 #define NET_RES_MATCH 266 #define NOISY 267 #define PATH 268 #define RES_MATCH 269 #define RES_UPPER_BOUND 270 #define SENSITIVE 271 #define SHIELDING 272 #define TIMING 273 #define MAX_VOLTAGE_DROP 274 #define COMMA 275 #define YYERRCODE 256 short yylhs[] = { -1, 0, 2, 2, 3, 3, 3, 3, 4, 4, 8, 8, 10, 5, 9, 9, 11, 11, 11, 11, 11, 11, 16, 12, 13, 14, 15, 15, 15, 19, 17, 18, 18, 20, 20, 22, 22, 21, 21, 23, 23, 6, 6, 7, 7, 1, 1, 1, }; short yylen[] = { 2, 1, 1, 2, 1, 1, 1, 1, 5, 4, 2, 2, 0, 4, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 0, 5, 2, 4, 0, 1, 3, 4, 0, 1, 3, 4, 2, 2, 2, 2, 1, 1, 1, }; short yydefred[] = { 0, 0, 0, 0, 0, 0, 0, 2, 4, 5, 0, 0, 0, 46, 45, 47, 12, 41, 43, 10, 3, 42, 44, 0, 11, 0, 0, 0, 29, 26, 0, 27, 28, 0, 0, 0, 14, 16, 17, 18, 19, 20, 21, 0, 24, 0, 25, 23, 22, 15, 8, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 35, 32, 0, 0, 0, 39, 0, 36, 40, }; short yydgoto[] = { 5, 16, 6, 7, 8, 9, 10, 11, 12, 35, 25, 36, 37, 38, 39, 40, 41, 42, 52, 45, 56, 61, 57, 62, }; short yysindex[] = { -262, -245, -245, -245, -245, 0, -262, 0, 0, 0, -245, -245, -222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -257, 0, -240, -250, -251, 0, 0, -243, 0, 0, -237, -235, -240, 0, 0, 0, 0, 0, 0, 0, -232, 0, -245, 0, 0, 0, 0, 0, -245, -255, 0, -245, -245, -241, -249, -245, -245, -245, 0, -236, -245, 0, 0, -245, -245, -245, 0, -245, 0, 0, }; short yyrindex[] = { 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 54, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 29, 15, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; short yygindex[] = { 0, 7, 0, 35, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; #define YYTABLESIZE 337 short yytable[] = { 26, 33, 1, 2, 3, 54, 4, 43, 44, 17, 18, 19, 13, 14, 15, 34, 46, 21, 22, 24, 55, 27, 47, 28, 48, 50, 63, 29, 60, 37, 30, 31, 32, 33, 34, 13, 14, 15, 1, 67, 23, 20, 0, 38, 49, 0, 0, 0, 0, 0, 0, 0, 51, 0, 6, 0, 0, 0, 53, 7, 0, 58, 59, 0, 13, 64, 65, 66, 0, 9, 68, 0, 0, 69, 70, 71, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 0, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 37, 0, 37, 37, 37, 37, 37, 37, 0, 37, 37, 37, 37, 37, 38, 0, 38, 38, 38, 38, 38, 38, 0, 38, 38, 38, 38, 38, 6, 6, 6, 0, 6, 7, 7, 7, 0, 7, 13, 13, 13, 0, 13, 9, 9, 9, 0, 9, }; short yycheck[] = { 257, 0, 264, 265, 266, 260, 268, 257, 259, 2, 3, 4, 257, 258, 259, 0, 259, 10, 11, 12, 275, 261, 259, 263, 259, 257, 275, 267, 269, 0, 270, 271, 272, 273, 274, 257, 258, 259, 0, 275, 262, 6, -1, 0, 35, -1, -1, -1, -1, -1, -1, -1, 45, -1, 0, -1, -1, -1, 51, 0, -1, 54, 55, -1, 0, 58, 59, 60, -1, 0, 63, -1, -1, 66, 67, 68, -1, 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 261, -1, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 261, -1, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 261, -1, 263, 264, 265, 266, 267, 268, -1, 270, 271, 272, 273, 274, 261, -1, 263, 264, 265, 266, 267, 268, -1, 270, 271, 272, 273, 274, 264, 265, 266, -1, 268, 264, 265, 266, -1, 268, 264, 265, 266, -1, 268, 264, 265, 266, -1, 268, }; #define YYFINAL 5 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 275 #if YYDEBUG char *yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"INTEGER","STRING","FLOAT", "CAP_MATCH","CAP_UPPER_BOUND","COLON","COMMON_POINT","NET","NET_CAP_MATCH", "NET_RES_MATCH","NOISY","PATH","RES_MATCH","RES_UPPER_BOUND","SENSITIVE", "SHIELDING","TIMING","MAX_VOLTAGE_DROP","COMMA", }; char *yyrule[] = { "$accept : start_nets", "start_nets : critical_data", "critical_data : path_or_netdata", "critical_data : critical_data path_or_netdata", "path_or_netdata : single_path", "path_or_netdata : net_data", "path_or_netdata : net_cap_match", "path_or_netdata : net_res_match", "single_path : pathlist COLON INTEGER INTEGER INTEGER", "single_path : pathlist COLON INTEGER INTEGER", "pathlist : PATH string", "pathlist : pathlist string", "$$1 :", "net_data : NET string $$1 net_param_list", "net_param_list : net_option", "net_param_list : net_param_list net_option", "net_option : timing", "net_option : cap_upper_bound", "net_option : res_upper_bound", "net_option : analog_type", "net_option : voltage_drop", "net_option : common_point", "voltage_drop : MAX_VOLTAGE_DROP FLOAT", "timing : TIMING FLOAT", "cap_upper_bound : CAP_UPPER_BOUND FLOAT", "res_upper_bound : RES_UPPER_BOUND FLOAT", "analog_type : NOISY", "analog_type : SENSITIVE", "analog_type : SHIELDING", "$$2 :", "common_point : COMMON_POINT $$2 pt_list cap_match res_match", "pt_list : string string", "pt_list : pt_list COMMA string string", "cap_match :", "cap_match : cap_list", "cap_list : CAP_MATCH string string", "cap_list : cap_list COMMA string string", "res_match :", "res_match : res_list", "res_list : RES_MATCH string string", "res_list : res_list COMMA string string", "net_cap_match : NET_CAP_MATCH string", "net_cap_match : net_cap_match string", "net_res_match : NET_RES_MATCH string", "net_res_match : net_res_match string", "string : STRING", "string : INTEGER", "string : FLOAT", }; #endif #define yyclearin (yychar=(-1)) #define yyerrok (yyerrflag=0) #ifdef YYSTACKSIZE #ifndef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #endif #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 500 #define YYMAXDEPTH 500 #endif #endif int yycnprs = 0; int yydebug; int yynerrs; int yyerrflag; int yychar; short *yyssp; YYSTYPE *yyvsp; YYSTYPE yyval; YYSTYPE yylval; short yyss[YYSTACKSIZE]; YYSTYPE yyvs[YYSTACKSIZE]; #define yystacksize YYSTACKSIZE #include "readnets_l.h" /* add readnets_l.h for debug purposes */ /* ********************* #include "readnets_l.h" *******************/ /* ********************* #include "readnets_l.h" *******************/ readnets( fp ) FILE *fp ; { #ifdef YYDEBUG extern int yydebug ; yydebug = FALSE ; #endif yyin = fp ; line_countS = 0 ; init_nets() ; /* parse input file using yacc if input given */ if( fp ){ yyparse(); } cleanup_nets() ; } /* end readnets */ yyerror(s) char *s; { extern char *cktNameG ; sprintf(YmsgG,"problem reading %s.mnet:", cktNameG ); M( ERRMSG, "yacc", YmsgG ) ; sprintf(YmsgG, "line %d near '%s' : %s\n" , line_countS+1, yytext, s ); M( ERRMSG,NULL, YmsgG ) ; Ymessage_error_count() ; set_net_error() ; } yywrap() { return(1); } #define YYABORT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int yyparse() { register int yym, yyn, yystate; #if YYDEBUG register char *yys; extern char *getenv(); if (yys = getenv("YYDEBUG")) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = (-1); yyssp = yyss; yyvsp = yyvs; *yyssp = yystate = 0; yyloop: if (yyn = yydefred[yystate]) goto yyreduce; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, shifting to state %d\n", yystate, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; #ifdef lint goto yynewerror; #endif yynewerror: #if YYDEBUG { int test_state, i, expect, two_or_more ; char err_msg[BUFSIZ] ; if( yyname[yychar] ){ sprintf( err_msg, "Found %s.\nExpected ", yyname[yychar] ) ; two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } yyerror( err_msg ) ; if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } } else { sprintf( err_msg, "Found unknown token.\nExpected "); two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = 1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if((expect <= YYTABLESIZE) && (yycheck[expect] == i) && yyname[i]){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } yyerror( err_msg ) ; if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } } } #else yyerror("syntax error"); if (yycnprs) { yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } #endif #ifdef lint goto yyerrlab; #endif yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, error recovery shifting\ to state %d\n", *yyssp, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("yydebug: error recovery discarding state %d\n", *yyssp); #endif if (yyssp <= yyss) goto yyabort; --yyssp; --yyvsp; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, error recovery discards token %d (%s)\n", yystate, yychar, yys); } #endif yychar = (-1); goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("yydebug: state %d, reducing by rule %d (%s)\n", yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; yyval = yyvsp[1-yym]; switch (yyn) { case 8: { /* pathlist COLON lowerBound upperBound priority*/ end_path( yyvsp[-2].ival, yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 9: { end_path( yyvsp[-1].ival, yyvsp[0].ival, 1 ) ; } break; case 10: { add_path( STARTPATH, yyvsp[0].string ) ; } break; case 11: { add_path( CONTPATH, yyvsp[0].string ) ; } break; case 12: { init_analog( yyvsp[0].string ) ; } break; case 22: { set_max_voltage_drop( yyvsp[0].fval ) ; } break; case 24: { set_cap_upper_bound( yyvsp[0].fval ) ; } break; case 25: { set_res_upper_bound( yyvsp[0].fval ) ; } break; case 26: { set_net_type( NOISY_NET ) ; } break; case 27: { set_net_type( SENSITIVE_NET ) ; } break; case 28: { set_net_type( SHIELDING_NET ) ; } break; case 29: { add_common_pt(); } break; case 31: { add2common( yyvsp[-1].string, yyvsp[0].string ) ; } break; case 32: { add2common( yyvsp[-1].string, yyvsp[0].string ) ; } break; case 35: { common_cap( yyvsp[-1].string, yyvsp[0].string ) ; } break; case 36: { common_cap( yyvsp[-1].string, yyvsp[0].string ) ; } break; case 39: { common_res( yyvsp[-1].string, yyvsp[0].string ) ; } break; case 40: { common_res( yyvsp[-1].string, yyvsp[0].string ) ; } break; case 41: { start_net_capmatch( yyvsp[0].string ) ; } break; case 42: { add_net_capmatch( yyvsp[0].string ) ; } break; case 43: { start_net_resmatch( yyvsp[0].string ) ; } break; case 44: { add_net_resmatch( yyvsp[0].string ) ; } break; case 45: { yyval.string = yyvsp[0].string ; } break; case 46: { /* convert integer to string */ /* this allows integers to be used as strings */ /* a kluge but timberwolf's old parser supported it */ sprintf( bufferS,"%d", yyvsp[0].ival ) ; /* now clone string */ yyval.string = (char *) Ystrclone( bufferS ) ; } break; case 47: { /* convert float to string */ /* this allows floats to be used as strings */ /* a kluge but timberwolf's old parser supported it */ sprintf( bufferS,"%f", yyvsp[0].fval ) ; /* now clone string */ yyval.string = (char *) Ystrclone( bufferS ) ; } break; } yyssp -= yym; yystate = *yyssp; yyvsp -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state 0 to\ state %d\n", YYFINAL); #endif yystate = YYFINAL; *++yyssp = YYFINAL; *++yyvsp = yyval; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state %d \ to state %d\n", *yyssp, yystate); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate; *++yyvsp = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: return (1); yyaccept: return (0); } graywolf-0.1.4+20170307gite1bf319/src/twmc/readnets.h000066400000000000000000000050551305746555600215100ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: readnets.h DESCRIPTION:This file redefines global variable of yacc and lex so that we can have more than one parser in TimberWolfMC. CONTENTS: macro redefinitions for parser in readnets. DATE: Oct 19, 1988 REVISIONS: Sun Dec 16 00:40:28 EST 1990 - moved net routines to initnets.c and added analog functions. Thu Mar 7 01:48:21 EST 1991 - added more definitions for byacc. ----------------------------------------------------------------- */ /* ***************************************************************** static char SccsId[] = "@(#) readnets.h version 3.6 3/6/92" ; ***************************************************************** */ #include #define STARTPATH 1 /* flag for start of path */ #define CONTPATH 0 /* flag for continuing path */ #define yyact NET_yyact #define yyback NET_yyback #define yybgin NET_yybgin #define yychar NET_yychar #define yychk NET_yychk #define yycrank NET_yycrank #define yycnprs NET_yycnprs #define yydebug NET_yydebug #define yydef NET_yydef #define yyerrflag NET_yyerrflag #define yyerror NET_yyerror #define yyestate NET_yyestate #define yyexca NET_yyexca #define yyextra NET_yyextra #define yyfnd NET_yyfnd #define yyin NET_yyin #define yyinput NET_yyinput #define yyleng NET_yyleng #define yylex NET_yylex #define yylineno NET_yylineno #define yylook NET_yylook #define yylsp NET_yylsp #define yylstate NET_yylstate #define yylval NET_yylval #define yymatch NET_yymatch #define yymorfg NET_yymorfg #define yynerrs NET_yynerrs #define yyolsp NET_yyolsp #define yyout NET_yyout #define yyoutput NET_yyoutput #define yypact NET_yypact #define yyparse NET_yyparse #define yypgo NET_yypgo #define yyprevious NET_yyprevious #define yyreds NET_yyreds #define yyr2 NET_yyr2 #define yysbuf NET_yysbuf #define yysptr NET_yysptr #define yysvec NET_yysvec #define yytchar NET_yytchar #define yytext NET_yytext #define yytoks NET_yytoks #define yytop NET_yytop #define yyunput NET_yyunput #define yyv NET_yyv #define yyval NET_yyval #define yyvstop NET_yyvstop #define yywrap NET_yywrap /* for byacc */ #define yyrule NET_yyrule #define yyname NET_yyname #define yytable NET_yytable #define yycheck NET_yycheck #define yydgoto NET_yydgoto #define yydefred NET_yydefred #define yygindex NET_yygindex #define yyrindex NET_yyrindex #define yysindex NET_yysindex #define yylen NET_yylen #define yylhs NET_yylhs graywolf-0.1.4+20170307gite1bf319/src/twmc/readnets_l.h000066400000000000000000000366021305746555600220250ustar00rootroot00000000000000#ifdef linux # include #else # include "stdio.h" #endif # define U(x) ((x)&0377) # define NLSTATE yyprevious=YYNEWLINE # define BEGIN yybgin = yysvec + 1 + # define INITIAL 0 # define YYLERR yysvec # define YYSTATE (yyestate-yysvec-1) # define YYOPTIM 1 # define YYLMAX 200 # define output(c) putc(c,yyout) # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} # define yymore() (yymorfg=1) # define ECHO fprintf(yyout, "%s",yytext) # define REJECT { nstr = yyreject(); goto yyfussy;} int yyleng; extern char yytext[]; int yymorfg; extern char *yysptr, yysbuf[]; int yytchar; #ifdef linux FILE *yyin = NULL, *yyout = NULL; #else FILE *yyin ={stdin}, *yyout ={stdout}; #endif extern int yylineno; struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops;}; struct yysvf *yyestate; extern struct yysvf yysvec[], *yybgin; /* ----------------------------------------------------------------- FILE: readnets_lex DESCRIPTION:rules for lexical analyzer in readnets. This lexical analyzer uses a binary search to reduce the size of the f.a. generated by lex. Thanks to Gary Richey who showed me the trick. See chapter 3 of "Introduction to Compiler Construction with UNIX" by Schreiner & Friedman for more details. CONTENTS: lex rules - screen() DATE: Oct 19, 1988 - original coding static char SccsId[] = "@(#) readnets.l version 3.9 4/18/91" ; REVISIONS: Feb 9, 1990 - expanded ASCII character set. Apr 23, 1990 - added Cstyle comments. Sun Dec 16 00:41:42 EST 1990 - added max_voltage_drop and added comma to input format. Thu Dec 20 00:01:20 EST 1990 - updated FLOAT def. Mon Jan 21 22:31:24 PST 1991 - added ASCII charset for alphanum. Thu Mar 14 16:13:06 CST 1991 - added missing characters. Fri Mar 22 20:03:52 CST 1991 - made letter more general. Thu Apr 18 01:43:35 EDT 1991 - moved placement of COLON ----------------------------------------------------------------- */ #undef YYLMAX #define YYLMAX 2000 /* comments may be at most 2000 characters */ #define token(x) x /* makes it look like regular lex */ #define END(v) (v-1 + sizeof(v) / sizeof( v[0] ) ) /* for table lookup */ static INT screen() ; static INT check_line_count() ; # define YYNEWLINE 10 yylex(){ int nstr; extern int yyprevious; while((nstr = yylook()) >= 0) yyfussy: switch(nstr){ case 0: if(yywrap()) return(0); break; case 1: { /* C-style comments over multiple lines */ check_line_count(yytext) ; } break; case 2: { /* convert to an integer */ yylval.ival = atoi( yytext ) ; return (INTEGER); } break; case 3: { /* convert to an integer */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 4: { /* convert to an integer */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 5: { return(COLON); } break; case 6: { return( screen() ) ; } break; case 7: { return(COMMA); } break; case 8: { line_countS++;} break; case 9: ; break; case 10: { return( token(yytext[0]) ) ;} break; case -1: break; default: fprintf(yyout,"bad switch yylook %d",nstr); } return(0); } /* end of yylex */ /* reserved word screener */ /* ----------------------------------------------------------------- The following is table of the reserved words - Table must be in alphabetical order for binary search to work properly. ----------------------------------------------------------------- */ static struct rw_table { /* reserved word table */ char *rw_name ; /* pattern */ INT rw_yylex ; /* lex token number */ } rwtable[] = { "cap_match", token(CAP_MATCH), "cap_upper_bound", token(CAP_UPPER_BOUND), "common_point", token(COMMON_POINT), "max_voltage_drop", token(MAX_VOLTAGE_DROP), "net", token(NET), "net_cap_match", token(NET_CAP_MATCH), "net_res_match", token(NET_RES_MATCH), "noisy", token(NOISY), "path", token(PATH), "res_match", token(RES_MATCH), "res_upper_bound", token(RES_UPPER_BOUND), "sensitive", token(SENSITIVE), "shielding", token(SHIELDING), "timing", token(TIMING) } ; static INT screen() { INT c ; struct rw_table *low = rwtable, /* ptr to beginning */ *mid , *high = END(rwtable) ; /* ptr to end */ /* binary search to look thru table to find pattern match */ while( low <= high){ mid = low + (high-low) / 2 ; if( (c = strcmp(mid->rw_name, yytext) ) == STRINGEQ){ return( mid->rw_yylex ) ; /* return token number */ } else if( c < 0 ){ low = mid + 1 ; } else { high = mid - 1 ; } } /* at this point we haven't found a match so we have a string */ /* save the string by making copy */ yylval.string = (char *) Ystrclone( yytext ) ; return (STRING); } /* end screen function */ static INT check_line_count( s ) char *s ; { if( s ){ if( strlen(s) >= YYLMAX ){ sprintf(YmsgG, "comment beginning at line %d ",line_countS+1 ); M( ERRMSG, "lex", YmsgG ) ; sprintf(YmsgG,"exceeds maximum allowed length:%d chars.\n", YYLMAX ); M( MSG, NULL, YmsgG ) ; setErrorFlag() ; } for( ;*s;s++ ){ if( *s == '\n'){ line_countS++; } } } } /* end check_line_count */ int yyvstop[] ={ 0, 9, 0, 9, 0, 10, 0, 9, 10, 0, 8, 0, 6, 10, 0, 6, 10, 0, 6, 7, 10, 0, 3, 6, 10, 0, 6, 10, 0, 2, 10, 0, 5, 6, 10, 0, 9, 0, 6, 0, 3, 6, 0, 2, 6, 0, 6, 0, 3, 6, 0, 2, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 4, 6, 0, 6, 0, 6, 0, 1, 6, 0, 1, 0, 6, 0, 1, 6, 0, 1, 0, 0}; # define YYTYPE unsigned char struct yywork { YYTYPE verify, advance; } yycrank[] ={ 0,0, 0,0, 1,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,4, 1,5, 4,13, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 4,13, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 1,7, 1,8, 10,17, 1,9, 1,10, 1,11, 22,22, 29,35, 30,36, 34,28, 35,29, 36,29, 0,0, 0,0, 7,15, 1,12, 7,16, 7,16, 7,16, 7,16, 7,16, 7,16, 7,16, 7,16, 7,16, 7,16, 1,6, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 6,14, 9,15, 9,15, 9,15, 9,15, 9,15, 9,15, 9,15, 9,15, 9,15, 9,15, 11,18, 0,0, 11,19, 11,19, 11,19, 11,19, 11,19, 11,19, 11,19, 11,19, 11,19, 11,19, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 16,18, 11,20, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 0,0, 0,0, 0,0, 0,0, 17,21, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 16,20, 17,21, 17,21, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 11,20, 0,0, 18,18, 18,18, 18,18, 18,18, 18,18, 18,18, 18,18, 18,18, 18,18, 18,18, 0,0, 0,0, 0,0, 17,22, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 16,20, 18,20, 17,23, 17,22, 17,22, 0,0, 17,22, 17,24, 17,22, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 19,18, 17,22, 19,19, 19,19, 19,19, 19,19, 19,19, 19,19, 19,19, 19,19, 19,19, 19,19, 17,22, 0,0, 0,0, 0,0, 18,20, 0,0, 0,0, 20,25, 0,0, 20,25, 0,0, 19,20, 20,26, 20,26, 20,26, 20,26, 20,26, 20,26, 20,26, 20,26, 20,26, 20,26, 21,21, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 23,28, 21,27, 21,21, 21,21, 0,0, 21,21, 21,21, 21,21, 23,28, 23,28, 0,0, 0,0, 0,0, 19,20, 0,0, 0,0, 0,0, 21,21, 25,26, 25,26, 25,26, 25,26, 25,26, 25,26, 25,26, 25,26, 25,26, 25,26, 21,21, 0,0, 0,0, 0,0, 23,29, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 23,30, 23,29, 23,29, 0,0, 23,29, 23,31, 23,29, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 23,29, 26,26, 26,26, 26,26, 26,26, 26,26, 26,26, 26,26, 26,26, 26,26, 26,26, 23,29, 27,28, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 28,21, 0,0, 27,32, 27,28, 27,28, 0,0, 27,28, 27,33, 27,28, 28,27, 28,21, 28,21, 0,0, 28,21, 28,34, 28,21, 0,0, 32,21, 27,28, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 28,21, 32,27, 32,21, 32,21, 27,28, 32,21, 32,37, 32,21, 0,0, 0,0, 0,0, 28,21, 0,0, 0,0, 0,0, 0,0, 0,0, 32,21, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 32,21, 0,0, 0,0, 0,0, 0,0}; struct yysvf yysvec[] ={ 0, 0, 0, yycrank+-1, 0, yyvstop+1, yycrank+0, yysvec+1, yyvstop+3, yycrank+0, 0, yyvstop+5, yycrank+3, 0, yyvstop+7, yycrank+0, 0, yyvstop+10, yycrank+38, 0, yyvstop+12, yycrank+12, yysvec+6, yyvstop+15, yycrank+0, yysvec+6, yyvstop+18, yycrank+117, yysvec+6, yyvstop+22, yycrank+4, yysvec+6, yyvstop+26, yycrank+129, yysvec+6, yyvstop+29, yycrank+0, yysvec+6, yyvstop+32, yycrank+0, yysvec+4, yyvstop+36, yycrank+0, yysvec+6, yyvstop+38, yycrank+139, yysvec+6, yyvstop+40, yycrank+151, yysvec+6, yyvstop+43, yycrank+-212, 0, yyvstop+46, yycrank+184, yysvec+6, yyvstop+48, yycrank+223, yysvec+6, yyvstop+51, yycrank+245, yysvec+6, yyvstop+53, yycrank+-270, yysvec+17, 0, yycrank+-3, yysvec+17, yyvstop+55, yycrank+-310, 0, yyvstop+57, yycrank+0, yysvec+17, yyvstop+59, yycrank+281, yysvec+6, yyvstop+61, yycrank+321, yysvec+6, yyvstop+63, yycrank+-347, yysvec+23, 0, yycrank+-354, yysvec+17, 0, yycrank+-4, yysvec+17, yyvstop+66, yycrank+-5, yysvec+17, yyvstop+68, yycrank+0, yysvec+6, yyvstop+70, yycrank+-371, yysvec+17, 0, yycrank+0, 0, yyvstop+73, yycrank+6, 0, 0, yycrank+7, yysvec+6, yyvstop+75, yycrank+8, yysvec+6, yyvstop+77, yycrank+0, yysvec+34, yyvstop+80, 0, 0, 0}; struct yywork *yytop = yycrank+440; struct yysvf *yybgin = yysvec+1; char yymatch[] ={ 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 011 ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'*' ,'+' ,',' ,'+' ,'.' ,'/' , '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , '0' ,'0' ,':' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 0}; char yyextra[] ={ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0}; /* ncform 4.1 83/08/11 */ int yylineno =1; # define YYU(x) x # define NLSTATE yyprevious=YYNEWLINE char yytext[YYLMAX]; struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; char yysbuf[YYLMAX]; char *yysptr = yysbuf; int *yyfnd; extern struct yysvf *yyestate; int yyprevious = YYNEWLINE; yylook(){ register struct yysvf *yystate, **lsp; register struct yywork *yyt; struct yysvf *yyz; int yych; struct yywork *yyr; # ifdef LEXDEBUG int debug; # endif char *yylastch; #ifdef linux if (yyin == NULL) yyin = stdin; if (yyout == NULL) yyout = stdout; #endif /* start off machines */ # ifdef LEXDEBUG debug = 0; # endif if (!yymorfg) yylastch = yytext; else { yymorfg=0; yylastch = yytext+yyleng; } for(;;){ lsp = yylstate; yyestate = yystate = yybgin; if (yyprevious==YYNEWLINE) yystate++; for (;;){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); # endif yyt = yystate->yystoff; if(yyt == yycrank){ /* may not be any transitions */ yyz = yystate->yyother; if(yyz == 0)break; if(yyz->yystoff == yycrank)break; } *yylastch++ = yych = input(); tryagain: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"unsigned char "); allprint(yych); putchar('\n'); } # endif yyr = yyt; if ( (long)yyt > (long)yycrank){ yyt = yyr + yych; if (yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } # ifdef YYOPTIM else if((long)yyt < (long)yycrank) { /* r < yycrank */ yyt = yyr = yycrank+(yycrank-yyt); # ifdef LEXDEBUG if(debug)fprintf(yyout,"compressed state\n"); # endif yyt = yyt + yych; if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } yyt = yyr + YYU(yymatch[yych]); # ifdef LEXDEBUG if(debug){ fprintf(yyout,"try fall back character "); allprint(YYU(yymatch[yych])); putchar('\n'); } # endif if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transition */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); # endif goto tryagain; } # endif else {unput(*--yylastch);break;} contin: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"state %d char ",yystate-yysvec-1); allprint(yych); putchar('\n'); } # endif ; } # ifdef LEXDEBUG if(debug){ fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); allprint(yych); putchar('\n'); } # endif while (lsp-- > yylstate){ *yylastch-- = 0; if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ yyolsp = lsp; if(yyextra[*yyfnd]){ /* must backup */ while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ lsp--; unput(*yylastch--); } } yyprevious = YYU(*yylastch); yylsp = lsp; yyleng = yylastch-yytext+1; yytext[yyleng] = 0; # ifdef LEXDEBUG if(debug){ fprintf(yyout,"\nmatch "); sprint(yytext); fprintf(yyout," action %d\n",*yyfnd); } # endif return(*yyfnd++); } unput(*yylastch); } if (yytext[0] == 0 /* && feof(yyin) */) { yysptr=yysbuf; return(0); } yyprevious = yytext[0] = input(); if (yyprevious>0) output(yyprevious); yylastch=yytext; # ifdef LEXDEBUG if(debug)putchar('\n'); # endif } } yyback(p, m) int *p; { if (p==0) return(0); while (*p) { if (*p++ == m) return(1); } return(0); } /* the following are only used in the lex library */ yyinput(){ #ifdef linux if (yyin == NULL) yyin = stdin; #endif return(input()); } yyoutput(c) int c; { #ifdef linux if (yyout == NULL) yyout = stdout; #endif output(c); } yyunput(c) int c; { unput(c); } graywolf-0.1.4+20170307gite1bf319/src/twmc/readpar.c000066400000000000000000000471021305746555600213130ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: readpar.c DESCRIPTION:read parameter file CONTENTS: readpar( ) DATE: Jan 30, 1988 REVISIONS: Mar 8, 1988 - added lambda and init_acc ; Oct 27, 1988 - changed to minimal standard random number generator. Nov 25, 1988 - added timeFactor initialization. Feb 20, 1989 - added no.graphics keyword Mar 01, 1989 - added no.graphics.wait keyword. Mar 13, 1989 - added tw_fast and tw_slow parameters. May 11, 1989 - moved doGraphicsG initialization to main.c May 18, 1989 - modified pad placement parameters. May 24, 1989 - removed doPlacementG. May 25, 1989 - added graphFilesG switch. Sep 19, 1989 - added no.graphics.update switch. Oct 3, 1989 - added scale_dataG and .mpar output fix. Oct 20, 1989 - changed track spacing to track pitch to make it easier on the user. Nov 28, 1989 - made scaling user data automatic. Apr 23, 1990 - rewrote parsing to read one line at a time. May 15, 1990 - made error messages easier to understand. Nov 23, 1990 - now use library utility to read par files. Fri Jan 25 18:09:20 PST 1991 - removed unnecessary globals. Sat Feb 23 00:27:37 EST 1991 - now handle wildcarding. Thu Mar 7 03:59:10 EST 1991 - added check for core. Tue Mar 12 17:06:56 CST 1991 - add check for track spacing. Thu Apr 18 01:27:23 EDT 1991 - added new design rule functions and cleaned up unused keywords. Sun May 5 14:22:52 EDT 1991 - now user can set origin. Wed Jun 5 16:29:10 CDT 1991 - added test for vertical_path weight. Fri Oct 18 00:15:59 EDT 1991 - now scale block when calling TimberWolf recursively. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) readpar.c version 3.20 11/23/91" ; #endif #include #include #include #include #include #include #define DEFAULTLAMBDA 0.1 #define INIT_ACCEPTANCE 0.99999 #define COMMENT '#' static BOOL abortS = FALSE ; static BOOL readparamS = FALSE ; static BOOL graphFileS ; static BOOL originGivenS = FALSE ; static BOOL sc_outputS = FALSE ; static INT gOffsetXS = INT_MIN ; static INT gOffsetYS = INT_MIN ; static INT gridXS = INT_MIN ; static INT gridYS = INT_MIN ; static init_read_par(); static readparam(); static process_readpar(); static err_msg(); readpar() { init_read_par() ; readparam( TWMC ) ; readparam( USER ) ; process_readpar() ; } static init_read_par() { /* set the default values */ offsetG = 0 ; layersFactorG = 1 ; totNetLenG = 0 ; randVarG = -1 ; wireEstimateOnlyG = 0 ; lapFactorG = 1.0; timeFactorG = 1.0; cost_onlyG = FALSE ; maxWeightG = 2 ; baseWeightG = 1 ; chipaspectG = -1.0 ; track_spacingXG = -1 ; track_spacingYG = -1 ; doPartitionG = FALSE ; doChannelGraphG = FALSE ; doGlobalRouteG = FALSE ; doCompactionG = FALSE ; coreGivenG = FALSE ; wait_for_userG = FALSE ; defaultTracksG = 0 ; restartG = FALSE ; contiguousG = TRUE ; gridCellsG = TRUE ; min_pad_spacingG = 0 ; init_accG = INIT_ACCEPTANCE ; padspacingG = UNIFORM_PADS ; external_pad_programG = FALSE ; graphFileS = FALSE ; vertical_wire_weightG = -1.0 ; vertical_path_weightG = 1.0 ; /* set default speed */ set_tw_speed( 1.0 ) ; /* initialize routing tiles to NULL */ init_routing_tiles() ; /* assume no origin given default to 0, 0 */ x_originG = 0 ; y_originG = 0 ; } /* end init_read_par */ static readparam( parfile ) INT parfile ; { INT test ; INT speed ; INT pins ; INT line ; INT length ; INT numtokens ; BOOL onNotOff ; BOOL wildcard ; char design[LRECL] ; char **tokens ; char *lineptr ; /* always read the user parameter file - avoid having two of */ /* them so chop off the _io suffix in the case of partitioning */ if( parfile == USER ){ length = strlen( cktNameG ) ; /* look for _io as the last 3 characters special case */ strcpy( design, cktNameG ) ; if( strcmp( cktNameG+length-3, "_io" ) == STRINGEQ ){ design[length-3] = EOS ; } Yreadpar_init( design, parfile, TWMC, FALSE ) ; } else { Yreadpar_init( cktNameG, parfile, TWMC, FALSE ) ; } OUT1( "\n\n" ) ; while( tokens = Yreadpar_next( &lineptr, &line, &numtokens, &onNotOff, &wildcard )){ readparamS = TRUE ; if( numtokens == 0 ){ /* skip over empty lines */ continue ; } else if( strcmp( tokens[0], "initialT" ) == STRINGEQ ){ if( numtokens == 2 ){ TG = atof( tokens[1] ) ; } else { err_msg("initialT") ; } } else if( strcmp( tokens[0], "cost_only" ) == STRINGEQ ){ if( onNotOff ){ cost_onlyG = TRUE ; } else { cost_onlyG = FALSE ; } } else if( strcmp( tokens[0], "restart" ) == STRINGEQ ){ if( onNotOff ){ restartG = TRUE ; } else { restartG = FALSE ; } } else if( strcmp( tokens[0], "debug" ) == STRINGEQ ){ if( onNotOff ){ YsetDebug( TRUE ) ; } else { YsetDebug( FALSE ) ; } } else if( strcmp( tokens[0], "graph" ) == STRINGEQ ){ if( onNotOff ){ graphFileS = TRUE ; } else { graphFileS = FALSE ; } } else if( strcmp( tokens[0], "random.seed" ) == STRINGEQ ){ if( numtokens == 2 ) { randVarG = atoi(tokens[1]) ; Yset_random_seed( randVarG ) ; } else { err_msg("random.seed") ; } } else if( strcmp( tokens[0], "chip.aspect.ratio" ) == STRINGEQ ){ if( numtokens == 2 ) { chipaspectG = atof( tokens[1] ) ; } else { err_msg("chip.aspect.ratio") ; } } else if( strcmp( tokens[0],"default.tracks.per.channel")==STRINGEQ){ if( numtokens == 2 ) { defaultTracksG = atoi( tokens[1] ) ; } else { err_msg("default.tracks.per.channel") ; } } else if( strcmp( tokens[0], "wire.estimation.only" ) == STRINGEQ ){ if( onNotOff ){ wireEstimateOnlyG = TRUE ; } else { wireEstimateOnlyG = FALSE ; } } else if( strcmp( tokens[0], "do.channel.graph" ) == STRINGEQ ){ if( onNotOff ){ doChannelGraphG = TRUE ; } else { doChannelGraphG = FALSE ; } } else if( strcmp( tokens[0], "do.global.route" ) == STRINGEQ ){ if( onNotOff ){ doGlobalRouteG = TRUE ; } else { doGlobalRouteG = FALSE ; } } else if( strcmp( tokens[0], "do.partition" ) == STRINGEQ ){ if( onNotOff ){ doPartitionG = TRUE ; } else { doPartitionG = FALSE ; } } else if( strcmp( tokens[0], "no.graphics" ) == STRINGEQ ){ if( onNotOff ){ doGraphicsG = FALSE ; } else { doGraphicsG = TRUE ; } } else if( strcmp( tokens[0], "graphics.wait" ) == STRINGEQ ){ if( onNotOff ){ wait_for_userG = TRUE ; } else { wait_for_userG = FALSE ; } } else if( strcmp( tokens[0], "sc_output_files" ) == STRINGEQ ){ if( onNotOff ){ sc_outputS = TRUE ; } else { sc_outputS = FALSE ; } } else if( strcmp( tokens[0], "no.graphics.update" ) == STRINGEQ ){ if( onNotOff ){ set_dump_ratio( 160 ) ; } else { set_dump_ratio( 1 ) ; } } else if( strcmp( tokens[0], "do.compaction" ) == STRINGEQ ){ if( numtokens == 2 ) { doCompactionG = atoi( tokens[1] ) ; } else { err_msg("do.compaction") ; } } else if( strcmp( tokens[0], "core" ) == STRINGEQ ){ if( numtokens == 5 ){ blocklG = atoi( tokens[1] ) ; blockbG = atoi( tokens[2] ) ; blockrG = atoi( tokens[3] ) ; blocktG = atoi( tokens[4] ) ; if( blocklG > blockrG ){ M( ERRMSG, "readpar", "core left is greater than core right\n" ) ; abortS = TRUE ; } if( blockbG > blocktG ){ M( ERRMSG, "readpar", "core bottom is greater than core top\n" ) ; abortS = TRUE ; } coreGivenG = TRUE ; } else if( numtokens == 6 && strcmp( tokens[1], "initially" ) == STRINGEQ ){ blocklG = atoi( tokens[2] ) ; blockbG = atoi( tokens[3] ) ; blockrG = atoi( tokens[4] ) ; blocktG = atoi( tokens[5] ) ; init_fixcell( atoi( tokens[2] ), atoi( tokens[3] ), atoi( tokens[4] ), atoi( tokens[5] ) ) ; } else { err_msg("the core definition") ; } } else if( strcmp( tokens[0], "origin" ) == STRINGEQ ){ if( numtokens == 3 ){ x_originG = atoi( tokens[1] ) ; y_originG = atoi( tokens[2] ) ; originGivenS = TRUE ; } else { err_msg("the core definition") ; } } else if( strcmp( tokens[0], "gridOffsetX" ) == STRINGEQ ){ if( numtokens == 2 ) { gOffsetXS = atoi( tokens[1] ) ; } else { err_msg("gridOffsetX") ; } } else if( strcmp( tokens[0], "gridOffsetY" ) == STRINGEQ ){ if( numtokens == 2 ) { gOffsetYS = atoi( tokens[1] ) ; } else { err_msg("gridOffsetY") ; } } else if( strcmp( tokens[0], "gridX" ) == STRINGEQ ){ if( numtokens == 2 ) { gridXS = atoi( tokens[1] ) ; } else { err_msg("gridX") ; } } else if( strcmp( tokens[0], "gridY" ) == STRINGEQ ){ if( numtokens == 2 ) { gridYS = atoi( tokens[1] ) ; } else { err_msg("gridY") ; } } else if( strcmp( tokens[0], "fast" ) == STRINGEQ ){ if( numtokens == 2 ) { speed = atoi( tokens[1] ) ; } else { err_msg("fast") ; continue ; } if( speed == 0 ){ err_msg("fast") ; } else { set_tw_speed( 1.0 / (DOUBLE) speed ) ; } } else if( strcmp( tokens[0], "slow" ) == STRINGEQ ){ if( numtokens == 2 ) { speed = atoi( tokens[1] ) ; } else { err_msg("slow") ; continue ; } if( speed == 0 ){ err_msg("slow") ; } else { set_tw_speed( (DOUBLE) speed ) ; } } else if( strcmp( tokens[0], "init_acc" ) == STRINGEQ ){ if( numtokens == 2 ) { init_accG = atof( tokens[1] ) ; } else { err_msg("init_acc") ; } } else if( strcmp( tokens[0], "print_pins" ) == STRINGEQ ){ if( numtokens == 2 ) { pins = atoi( tokens[1] ) ; set_print_pin( pins ) ; } else { err_msg("print_pins") ; } } else if( strcmp( tokens[0], "placepads" ) == STRINGEQ ){ if( onNotOff ){ external_pad_programG = TRUE ; } else { external_pad_programG = FALSE ; } } else if( strcmp( tokens[0], "contiguous_pad_groups" ) == STRINGEQ ){ if( onNotOff ){ contiguousG = TRUE ; } else { contiguousG = FALSE ; } } else if( strcmp( tokens[0], "minimum_pad_space" ) == STRINGEQ ){ if( numtokens == 2 ) { min_pad_spacingG = atoi( tokens[1] ); } else { err_msg("minimum space between pads") ; } } else if( strcmp( tokens[0], "padspacing" ) == STRINGEQ ){ if( numtokens == 2 ) { if( strcmp( tokens[1] , "uniform" ) == STRINGEQ ) { padspacingG = UNIFORM_PADS ; } else if( strcmp( tokens[1] , "variable" ) == STRINGEQ ) { padspacingG = VARIABLE_PADS ; } else if( strcmp( tokens[1] , "abut" ) == STRINGEQ ) { padspacingG = ABUT_PADS ; } else if( strcmp( tokens[1] , "exact" ) == STRINGEQ ) { padspacingG = EXACT_PADS ; } else { OUT1("Unexpected padspacing keyword in the .mpar file\n"); abortS = TRUE ; } } else { err_msg("padspacing") ; } } else if( strcmp( tokens[0],"vertical_wire_weight")==STRINGEQ){ if( numtokens == 2 ) { vertical_wire_weightG = atof( tokens[1] ) ; } else { err_msg("vertical_wire_weight") ; } } else if( strcmp( tokens[0],"vertical_path_weight")==STRINGEQ){ if( numtokens == 2 ) { vertical_path_weightG = atof( tokens[1] ) ; if( vertical_wire_weightG < 0.0 ){ /* this means vertical wire_weight has not been */ /* assign yet set to path weight as default */ vertical_wire_weightG = vertical_path_weightG ; } } else { err_msg("vertical_wire_weight") ; } } else if( strcmp( tokens[0],"wiring_reduction")==STRINGEQ){ if( numtokens == 2 ) { set_wiring_reduction( atof( tokens[1] ) ) ; } else { err_msg("wiring_reduction") ; } /*** catch all ***/ } else if(!(wildcard)) { if( parfile == USER ){ sprintf( YmsgG, "unexpected keyword in the %s.par file at line:%d\n\t%s\n", cktNameG, line, lineptr ); M( ERRMSG, "readpar", YmsgG ) ; } else { sprintf( YmsgG, "Unexpected keyword in the %s.mpar file at line:%d\n\t%s\n", cktNameG, line, lineptr ); M( ERRMSG, "readpar", YmsgG ) ; } Ymessage_error_count() ; abortS = TRUE ; } } } /* end readpar */ static process_readpar() { char *layer ; /* name of layer */ INT i ; /* counter */ INT pitch ; /* the pitch of the layer */ INT numv_layers ; /* number of vertical layers */ INT numh_layers ; /* number of horizontal layers */ INT num_layers ; /* total number of layers */ if( !(readparamS)){ M( ERRMSG, "process_readpar", "No parameter files found. Must exit\n\n" ) ; YexitPgm( FAIL ) ; } Yplot_control( graphFileS ) ; if( coreGivenG && scale_dataG ){ blockbG /= scale_dataG ; blocklG /= scale_dataG ; blockrG /= scale_dataG ; blocktG /= scale_dataG ; } if( originGivenS && scale_dataG ){ x_originG /= scale_dataG ; y_originG /= scale_dataG ; } numv_layers = 0 ; numh_layers = 0 ; num_layers = Yreadpar_numlayers() ; for( i = 1; i <= num_layers; i++ ){ layer = Yreadpar_id2layer( i ) ; pitch = (INT) Yreadpar_pitch( layer ) ; if( Yreadpar_layer_HnotV( layer ) ){ track_spacingYG += pitch ; numh_layers++ ; } else { track_spacingXG += pitch ; numv_layers++ ; } } /* get the average pitch of all the layers */ if( numv_layers > 0 ){ track_spacingXG++ ; /* to account for the -1 initialization */ track_spacingXG /= numv_layers ; if( track_spacingXG == 0 ){ track_spacingXG == 1 ; } if( scale_dataG ){ track_spacingXG = ceil( (DOUBLE) track_spacingXG / (DOUBLE)scale_dataG ) ; } } if( numh_layers > 0 ){ track_spacingYG++ ; /* to account for the -1 initialization */ track_spacingYG /= numh_layers ; if( track_spacingYG == 0 ){ track_spacingYG == 1 ; } if( scale_dataG ){ track_spacingYG = ceil( (DOUBLE) track_spacingYG / (DOUBLE)scale_dataG ) ; } } if( gridXS >= 0 || gridYS >= 0 || gOffsetXS >= 0 || gOffsetYS >= 0 ) { gridGivenG = TRUE ; if( !(gridXS >= 0 && gridYS >= 0 && gOffsetXS >= 0 && gOffsetYS >= 0 ) ) { OUT1("Error: It appears as though the grid is\n"); OUT1("not fully specified\n"); abortS = TRUE ; } } else { gridGivenG = FALSE ; gridXS = track_spacingXG ; gridYS = track_spacingYG ; gOffsetXS = 0 ; gOffsetYS = 0 ; } Ygrid_setx( gridXS, gOffsetXS ) ; Ygrid_sety( gridYS, gOffsetYS ) ; if( track_spacingXG < 0 ) { M( ERRMSG, "readpar", "Vertical track pitch could not be calculated from design rules\n"); M( ERRMSG, NULL, "Check the design rules in parameter file\n\n") ; abortS = TRUE ; } if( track_spacingYG < 0 ) { M( ERRMSG, "readpar", "Horizontal track pitch could not be calculated from design rules\n"); M( ERRMSG, NULL, "Check the design rules in parameter file\n\n") ; abortS = TRUE ; } if( track_spacingXG == 0 ) { M( ERRMSG, "readpar","Vertical track pitch must not be zero\n"); M( ERRMSG, NULL, "Check the design rules in parameter file\n\n") ; abortS = TRUE ; } if( track_spacingYG == 0 ) { M( ERRMSG, "readpar","Horizontal track pitch must not be zero\n"); M( ERRMSG, NULL, "Check the design rules in parameter file\n\n") ; abortS = TRUE ; } if( vertical_path_weightG < 0.0 || vertical_wire_weightG < 0.0 ){ M( ERRMSG, "readpar","Vertical_path_weight missing or specified incorrectly\n"); abortS = TRUE ; } if( coreGivenG && originGivenS ) { M( ERRMSG, "readpar", "Both origin and core region have been specified.\n"); M( ERRMSG, NULL, "Either add the keyword initially to core or\n"); M( ERRMSG, NULL, "only specify at a time\n\n") ; abortS = TRUE ; } if( chipaspectG < 0.0 ) { OUT1("chip.aspect.ratio was not entered "); OUT1("in the .mpar file\n"); abortS = TRUE ; } if( !cost_onlyG ) { if( init_accG < 0.0 ) { OUT1("init_acc must be a positive floating point number\n"); abortS = TRUE ; } } if( restartG ) { OUT1("TimberWolf instructed to attempt "); OUT2("restart of circuit:<%s>\n", cktNameG ) ; } if( !cost_onlyG ) { OUT1("TimberWolf instructed to do "); OUT2("placement of circuit:<%s>\n", cktNameG ) ; } if( doChannelGraphG ) { OUT1("TimberWolf instructed to generate "); OUT2("channel graph for circuit:<%s>\n", cktNameG ) ; if( cost_onlyG ) { OUT1("TimberWolf assumes input files: "); OUT3("<%s.geo> and <%s.pin> are present in\n",cktNameG, cktNameG ); } } if( doGlobalRouteG ) { if( doChannelGraphG ) { if( defaultTracksG < 0 ) { OUT1("default.tracks.per.channel \n"); OUT1("was not entered in .mpar file\n"); abortS = TRUE ; } else { OUT2("default.tracks.per.channel: %d\n",defaultTracksG); } } OUT1("TimberWolf instructed to do "); OUT2("global route for circuit:<%s>\n", cktNameG ) ; if( ! doChannelGraphG ) { OUT1("TimberWolf assumes input files: "); OUT3("<%s.gph> and <%s.twf> are present in ", cktNameG, cktNameG ); OUT1("the working directory\n") ; } } if( doCompactionG ) { OUT1("TimberWolf instructed to do "); OUT2("post-placement compaction for circuit:<%s>\n",cktNameG); if( !(doChannelGraphG && doGlobalRouteG) ) { OUT1("Error: TimberWolf cannot do compaction "); OUT1("without request to also do:\n"); OUT1("\tdoChannelGraph and doGlobalRoute - "); OUT1("Hence, request is cancelled\n"); doCompactionG = FALSE ; } } OUT2("track.pitch.x: %d\n" , track_spacingXG ) ; OUT2("track.pitch.y: %d\n" , track_spacingYG ) ; OUT2("chip.aspect.ratio: %g\n" , chipaspectG ) ; OUT2("init_acc: %4.2f\n", init_accG ) ; if( abortS ){ M( ERRMSG, "read_par", "Trouble with parameter file\n" ) ; sprintf( YmsgG, "Please read %s.mout for details\n\n",cktNameG ) ; M( ERRMSG, NULL, YmsgG ) ; YexitPgm( FAIL ) ; } FLUSHOUT() ; return ; } /* end process_readpar */ static err_msg( keyword ) char *keyword ; { OUT2("The value for %s was", keyword ); OUT1(" not properly entered in the .mpar file\n"); abortS = TRUE ; }/* end err_msg */ BOOL sc_output() { return( sc_outputS ) ; } /* end sc_output */ graywolf-0.1.4+20170307gite1bf319/src/twmc/reconfig.c000066400000000000000000000143421305746555600214710ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: reconfig.c DESCRIPTION:reconfigures the core area during simulated annealing run. It is called from uloop by the core area controller. CONTENTS: reconfigure( numbinX, numbinY, newCoreArea ) INT numbinX, numbinY, newCoreArea ; DATE: Sept 13, 1988 REVISIONS: Jan 20, 1989 - added findcost call to update new wirelength after reconfiguration. Mon Feb 4 02:18:42 EST 1991 - update for wire estimation algorithm. Thu Apr 18 01:26:43 EDT 1991 - grid cells if requested. Sun May 5 14:23:51 EDT 1991 - added reorigin and now allow user to set origin. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) reconfig.c version 3.6 5/5/91" ; #endif #include #include #define UPDATE (BOOL) FALSE /* don't initialize updateFixedCells */ reconfigure( numbinX, numbinY, newCoreArea ) INT numbinX ; INT numbinY ; DOUBLE newCoreArea ; { DOUBLE factor ; INT xlength, ylength ; if( coreGivenG == FALSE ) { blockrG = blocktG = (INT)( sqrt( newCoreArea ) ) + 1 ; /* * Take into account the aspect ratio requested by the user */ blocktG = (INT)( sqrt(chipaspectG) * (DOUBLE) blocktG ) + 1 ; blockrG = (INT)( 1.0 / sqrt(chipaspectG) * (DOUBLE) blockrG ) + 1; } xlength = blockrG - blocklG ; ylength = blocktG - blockbG ; slopeXG = (DOUBLE)(maxWeightG - baseWeightG) / ( (DOUBLE) xlength * 0.5 ) ; slopeYG = (DOUBLE)(maxWeightG - baseWeightG) / ( (DOUBLE) ylength * 0.5 ) ; basefactorG = (DOUBLE) baseWeightG ; factor = 0.5 * aveChanWidG /(DOUBLE)xlength / (DOUBLE) ylength ; /* now calculate factor for x and y directions taking wiring */ /* into account */ wireFactorXG = factor * 2 * track_spacingXG / (track_spacingXG + track_spacingYG ) ; wireFactorYG = factor * 2 * track_spacingYG / (track_spacingXG + track_spacingYG ) ; if( coreGivenG == FALSE ){ blocklG = x_originG ; blockbG = y_originG ; blockrG = blocklG + xlength ; blocktG = blockbG + ylength ; } if( gridGivenG ){ grid_cells() ; } placepads() ; /* calculate the core configuration constants for wire estimation */ blockmxG = (blockrG + blocklG) / 2 ; blockmyG = (blocktG + blockbG) / 2 ; halfXspanG = (blockrG - blocklG) / 2 ; halfYspanG = (blocktG - blockrG) / 2 ; binWidthXG = (blockrG - blocklG) / numbinX ; if( (blockrG - blocklG - binWidthXG * numbinX) >= numbinX / 2 ) { binWidthXG++ ; } binXOffstG = blocklG + 1 - binWidthXG ; binWidthYG = (blocktG - blockbG) / numbinY ; if( (blocktG - blockbG - binWidthYG * numbinY) >= numbinY / 2 ) { binWidthYG++ ; } binYOffstG = blockbG + 1 - binWidthYG ; updateFixedCells(UPDATE) ; /* place fixed cells then load */ loadbins(FALSE) ; /* wireArea not known */ bdxlengthG = blockrG - blocklG ; bdylengthG = blocktG - blockbG ; OUT3("bdxlength:%d bdylength:%d\n",bdxlengthG,bdylengthG); /* update for wire estimation algorithm */ resize_wire_params() ; /* update cost */ funccostG = findcost() ; return ; } /* end reconfigure */ reorigin() { CELLBOXPTR cellptr ; TILEBOXPTR tileptr ; INT l, r, b, t, cell ; INT xcenter, ycenter ; INT xorigin, yorigin ; INT xmax, ymax ; INT deltax, deltay ; /* find bounding box of all core cells */ xorigin = INT_MAX ; yorigin = INT_MAX ; xmax = INT_MIN ; ymax = INT_MIN ; for( cell = 1 ; cell <= numcellsG ; cell++ ){ cellptr = cellarrayG[cell] ; xcenter = cellptr->xcenter ; ycenter = cellptr->ycenter ; for( tileptr=cellptr->tiles;tileptr;tileptr = tileptr->next ) { l = tileptr->left ; r = tileptr->right ; b = tileptr->bottom ; t = tileptr->top ; Ytranslate( &l,&b,&r,&t,cellptr->orient) ; l += xcenter ; r += xcenter ; b += ycenter ; t += ycenter ; /* save bounding box of all tiles */ xorigin = MIN( l, xorigin ) ; yorigin = MIN( b, yorigin ) ; xmax = MAX( r, xmax ) ; ymax = MAX( t, ymax ) ; } } /* bounding box computation complete */ /* now get necessary delta to origin core cells */ deltax = x_originG - xorigin ; deltay = y_originG - yorigin ; /* update the positions of all the cells */ /* so that the core is origined at x_originG, y_originG */ for( cell = 1 ; cell <= numcellsG ; cell++ ){ cellptr = cellarrayG[cell] ; cellptr->xcenter += deltax ; cellptr->ycenter += deltax ; } /* end cell update */ placepads() ; blockmxG = (blockrG + blocklG) / 2 ; blockmyG = (blocktG + blockbG) / 2 ; bdxlengthG = blockrG - blocklG ; bdylengthG = blocktG - blockbG ; } /* end reorigin */ graywolf-0.1.4+20170307gite1bf319/src/twmc/rmain.c000066400000000000000000000072731305746555600210100ustar00rootroot00000000000000/* * Copyright (C) 1990-1991 Yale University * Copyright (C) 2014 Ruben Undheim * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: rmain.c DESCRIPTION:This file now contain calls the global router mickey. CONTENTS: DATE: Feb 28, 1990 REVISIONS: Sun Dec 16 00:36:43 EST 1990 - Modified for Dahe's new version of the global router. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) rmain.c version 3.6 2/23/91" ; #endif #include #include #include #include #include #include "config-build.h" #define GROUTEPROG "Mickey" #define GROUTEPATH "../Mickey" rmain( constraint_flag ) BOOL constraint_flag ; { INT closegraphics() ; char filename[LRECL] ; char *Yrelpath() ; char *pathname ; char *twdir ; /* path of TimberWolf directory */ char *getenv() ; /* used to get TWDIR environment variable */ FILE *fp ; /* first build .gpar file for global router */ sprintf( filename, "%s.gpar", cktNameG ) ; fp = TWOPEN( filename, "w", ABORT ) ; switch( get_circuit_type() ){ case NO_CKT_TYPE: case DIGITAL: fprintf( fp, "digital.circuit\n" ) ; break ; case ANALOG: fprintf( fp, "analog.circuit\n" ) ; break ; case MIXED: fprintf( fp, "mixed.circuit\n" ) ; break ; } fprintf( fp, "limit_iteration 99999\n" ) ; if( constraint_flag ){ fprintf( fp, "objective 2\n" ) ; } else { fprintf( fp, "objective 1\n" ) ; } TWCLOSE( fp ) ; /* now call the global router */ /* find the path of compactor relative to main program */ pathname = Yrelpath( argv0G, GROUTEPATH ) ; if( !(YfileExists(pathname))){ if( twdir = TWFLOWDIR ){ sprintf( filename, "%s/bin/%s", twdir, GROUTEPROG ) ; pathname = Ystrclone( filename ) ; } } sprintf( YmsgG, "%s %s", pathname, cktNameG ) ; M( MSG, NULL, YmsgG ) ; M( MSG, NULL, "\n" ) ; /* Ysystem will kill program if catastrophe occurred */ Ysystem( GROUTEPROG, ABORT, YmsgG, closegraphics ) ; Ysafe_free( pathname ) ; /* free name created in Yrelpath */ /* ############# end of gengraph execution ############# */ } /* end gmain */ graywolf-0.1.4+20170307gite1bf319/src/twmc/savewolf.c000066400000000000000000000260071305746555600215240ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: savewolf.c DESCRIPTION:restart mechanism routines CONTENTS: savewolf() DATE: Jan 29, 1988 REVISIONS: Dec 3, 1988 - added forced save flag. Jan 25, 1989 - changed placement of aspect ratio field so that softcell restarts will work properly. Also changed msg to YmsgG. Dec 17, 1989 - now save instances correctly. Feb 7, 1989 - fixed error in softcell sites. Feb 8, 1989 - force recalculation of boundaries when you read in new data. Apr 23, 1990 - save pin positions in restart file. May 15, 1990 - moved cpu time to library. Oct 14, 1990 - fixed restart in annealing. Mon Feb 4 02:19:36 EST 1991 - made HPI more robust. Thu Mar 7 01:50:35 EST 1991 - now save wireest params. Sat Apr 27 01:10:45 EDT 1991 - fixed problem with aspect ratio calculation. Wed May 1 19:23:32 EDT 1991 - fixed pin placement and aspect ratio initialization in restart. Sun May 5 14:31:12 EDT 1991 - replaced config3 with reorigin. Mon Sep 16 22:23:04 EDT 1991 - fixed for R6000. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) savewolf.c version 3.12 9/16/91" ; #endif #include #include #include #include #define MAXTIMEBEFORESAVE 600.0 /* seconds before new save 10min. */ savewolf( forceSave ) BOOL forceSave ; /* if true save parameters regardless of time */ { INT m ; FILE *fp ; char filename[LRECL] ; char file1[LRECL] ; char file2[LRECL] ; INT cell , terminal ; INT count ; CELLBOXPTR cellptr ; PINBOXPTR *sarray ; PINBOXPTR pin ; DOUBLE Ycpu_time(); DOUBLE current_time; static DOUBLE last_time = 0.0; #ifndef VMS /* make sure another checkpoint is worthwhile !! */ current_time = Ycpu_time(); if( !(forceSave) ){ /* avoid return when forced to save file */ if( (current_time - last_time) < MAXTIMEBEFORESAVE ) { return; } } last_time = current_time; sprintf( filename , "%s.mtmp" , cktNameG ) ; fp = TWOPEN( filename , "w", ABORT ) ; #else sprintf( filename , "%s.msav" , cktNameG ) ; fp = TWOPEN( filename , "w", ABORT ) ; sprintf( filename , "%s.sav;-2" , cktNameG ) ; delete( filename ) ; #endif if( scale_dataG ){ m = scale_dataG ; } else { m = 1 ; } save_uloop( fp ) ; save_window( fp ) ; save_wireest( fp ) ; fprintf(fp,"# configuration parameters:\n") ; fprintf(fp,"#numcells %d\n", numcellsG ) ; fprintf(fp,"%u\n", Yget_random_var() ) ; fprintf(fp,"%d %d\n", m*(blocktG-blockbG), m*(blockrG-blocklG) ) ; fprintf(fp,"%d %d\n", m*blockmxG, m*blockmyG ) ; fprintf(fp,"%d %d\n",m*binWidthXG,m*binXOffstG ) ; fprintf(fp,"%d %d\n",m*binWidthYG,m*binYOffstG ) ; HPO(fp,slopeXG) ; HPO(fp,slopeYG) ; HPO(fp,baseWeightG) ; HPO(fp,wireFactorXG) ; HPO(fp,wireFactorYG) ; HPO(fp,aveChanWidG) ; HPO(fp,lapFactorG) ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = cellarrayG[ cell ] ; fprintf( fp , "%d %d %d %d\n", cell , cellptr->orient , cellptr->xcenter*m, cellptr->ycenter*m ) ; if( cellptr->instptr ){ fprintf( fp , "%d\n", cellptr->cur_inst ) ; } if( cellptr->softflag ) { fprintf( fp , " %lf\n" , cellptr->aspect ); count = 0 ; for( pin = cellptr->pinptr; pin; pin = pin->nextpin ){ fprintf( fp, "%d %d ", m*pin->txpos, m*pin->typos ) ; if( (++count % 15 ) == 0 ){ fprintf( fp, "\n" ) ; } } fprintf( fp, "\n" ) ; } } TWCLOSE( fp ) ; #ifdef UNIX sprintf(file1, "%s.mtmp", cktNameG); sprintf(file2, "%s.msav", cktNameG); rename(file1, file2); #endif return ; } /* end savewolf */ /* ***************************************************************** RESTART TIMBERWOLFMC ROUTINE */ BOOL TW_oldinput( fp ) FILE *fp ; { #define HOWMANY 0 INT i, cell, orient, site, terminal; INT xcenter , ycenter, error ; INT oleft , oright , obottom , otop , Hdiv2 , Wdiv2 ; INT number_of_cells, inst ; DOUBLE aspect , aspFactor , val ; DOUBLE percentDone ; DOUBLE eval_ratio( P1(INT iterationG) ) ; CELLBOXPTR ptr ; TILEBOXPTR tileptr1 ; PINBOXPTR *sarray ; /* array of the current softpins */ PINBOXPTR term ; INSTBOXPTR instptr ; BOUNBOXPTR bounptr ; VERTBOXPTR vert ; INT *xorig ; INT *xnew ; INT *yorig ; INT *ynew ; INT howmany ; error = 0 ; error += read_uloop( fp ) ; error += read_window( fp ) ; error += read_wireest( fp ) ; fscanf(fp,"%[ #:a-zA-Z]\n",YmsgG ); /* throw away comment */ fscanf( fp, "%[ #:a-zA-Z]%d\n", YmsgG, &number_of_cells ) ; if( number_of_cells != numcellsG ){ M(ERRMSG,"TW_oldinput","Number of cells in restart file in error\n"); /* abort at this time no sense going on */ return( FALSE ) ; } fscanf( fp, "%u", &randVarG ) ; Yset_random_seed( randVarG ) ; fscanf( fp, "%d %d\n", &blocktG, &blockrG ) ; /* set blockl and blockb to zero anticipating call to placepads */ blocklG = blockbG = 0 ; fscanf( fp, "%d %d\n", &blockmxG, &blockmyG ) ; fscanf( fp, "%d %d\n", &binWidthXG, &binXOffstG ) ; fscanf( fp, "%d %d\n", &binWidthYG, &binYOffstG ) ; HPI(fp,&slopeXG) ; HPI(fp,&slopeYG) ; HPI(fp,&baseWeightG) ; HPI(fp,&wireFactorXG) ; HPI(fp,&wireFactorYG) ; HPI(fp,&aveChanWidG) ; HPI(fp,&lapFactorG) ; while( fscanf( fp , " %d %d %d %d ", &cell , &orient , &xcenter , &ycenter ) == 4 ) { ptr = cellarrayG[ cell ] ; ptr->orient = orient ; ptr->xcenter = xcenter ; ptr->ycenter = ycenter ; ptr->boun_valid = FALSE ; if( instptr = ptr->instptr ){ fscanf( fp , "%d", &inst ) ; ptr->cur_inst = inst ; /* update tiles */ ptr->tiles = instptr->tile_inst[inst] ; ptr->numtiles = instptr->numtile_inst[inst] ; /* swap in the new sites */ /* delay recalculation of bounding box views until needed */ ptr->bounBox = instptr->bounBox[inst] ; ptr->numsides = instptr->numsides[inst] ; ptr->vertices = instptr->vert_inst[inst] ; } else { inst = 0 ; } if( ptr->softflag ) { fscanf( fp , "%lf" , &aspect ) ; ptr->aspect = aspect ; for( term = ptr->pinptr; term; term = term->nextpin ){ fscanf( fp, "%d %d", &(term->txpos), &(term->typos) ) ; term->txpos_orig[inst] = term->txpos ; term->typos_orig[inst] = term->typos ; } howmany = (INT) ptr->softpins[HOWMANY] ; /* set each pin's correct instance */ for( i = 1 ; i <= howmany; i++ ){ term = ptr->softpins[i] ; term->softinfo = term->soft_inst[inst] ; } } if( ptr->softflag == 1 && ptr->aspUB > 0.01 + ptr->aspLB ) { /* determine aspect ratio orientation */ aspFactor = sqrt( aspect / ptr->orig_aspect ) ; /* use original bounding box to calculate changes */ bounptr = ptr->bounBox[8] ; /* original bbox */ oleft = bounptr->l ; obottom = bounptr->b ; oright = bounptr->r ; otop = bounptr->t ; val = (DOUBLE) (otop - obottom) * aspFactor ; Hdiv2 = ROUND( val ) / 2 ; val = (DOUBLE) (oright - oleft) / aspFactor ; Wdiv2 = ROUND( val ) / 2 ; /* * Time to compute the new coordinates for the cell * since its aspect ratio has changed. Do it for * the orient 0 version and then use the routines * from readcells() to transfer for other orients. */ for( tileptr1 = ptr->tiles;tileptr1;tileptr1 = tileptr1->next ){ val = (DOUBLE)(tileptr1->orig_left - oleft) / aspFactor ; tileptr1->left = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(tileptr1->orig_right - oleft) / aspFactor ; tileptr1->right = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(tileptr1->orig_bottom - obottom) * aspFactor; tileptr1->bottom = ROUND( val ) - Hdiv2 ; val = (DOUBLE)(tileptr1->orig_top - obottom) * aspFactor ; tileptr1->top = ROUND( val ) - Hdiv2 ; } /* modify the vertices of the cell for the softpin moves */ vert = ptr->vertices ; xorig = vert->x_orig ; xnew = vert->x ; yorig = vert->y_orig ; ynew = vert->y ; for( i = 1; i <= ptr->numsides; i++ ){ val = (DOUBLE)(xorig[i] - oleft) / aspFactor ; xnew[i] = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(yorig[i] - obottom) * aspFactor ; ynew[i] = ROUND( val ) - Hdiv2 ; } } for( term = ptr->pinptr ; term ; term = term->nextpin ) { term->txpos = term->txpos_orig[inst] ; term->typos = term->typos_orig[inst] ; term->xpos = term->txpos + xcenter ; term->ypos = term->typos + ycenter ; } } if( cell != numcellsG ){ /* abort restart */ error++ ; M(ERRMSG,"TW_oldinput", "Number of cell in restart file don't match number of cells in .cel file\n") ; } if( error ){ /* abort restart */ return( FALSE ) ; } else { /* a valid restart - find out where we are */ if( iterationG <= LASTTEMP ){ /* we are still annealing */ init_control(FALSE); /*** set controller to old values. ***/ /* reset the annealing controllers and reconfigure bins */ percentDone = eval_ratio( iterationG ) ; /* **** core area controller **** */ coreFactorG = calc_core_factor( percentDone ) ; /* **** overlap penalty controller **** */ lapFactorG = calc_lap_factor( percentDone ) ; /* **** timing penalty controller **** */ timeFactorG = calc_time_factor( percentDone ) ; } else { /* we are in placement refinement */ reorigin() ; } return( TRUE ) ; } } /* end TW_oldinput */ HPO(fp,d) FILE *fp; /* high precision output */ DOUBLE d; { fprintf(fp,"%34.32le\n",d); } /* end HPO */ HPI(fp,d) FILE *fp; /* high precision input */ DOUBLE *d; { INT numread ; numread = (INT) fscanf(fp,"%s\n",YmsgG); if( numread != 1 ){ M( ERRMSG, "HPI", "Could not read data. FATAL must abort\n" ) ; closegraphics() ; YexitPgm( PGMFAIL ) ; } *d = atof( YmsgG ) ; } /* end HPI */ graywolf-0.1.4+20170307gite1bf319/src/twmc/scrapnet.c000066400000000000000000000067041305746555600215170ustar00rootroot00000000000000/* * Copyright (C) 1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: scrapnet.c DESCRIPTION:ignore a net during annealing if it has too many connections DATE: Feb 7, 1990 REVISIONS: ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) scrapnet.c version 3.3 9/5/90" ; #endif #include #include scrapnet() { NETBOXPTR dimptr ; PINBOXPTR netptr ; INT *vector , criticalMass , count , temp , net , cell ; INT average_cells_per_net ; INT num_cell_for_net ; vector = (INT *) Ysafe_malloc( (1 + totalcellsG) * sizeof(INT) ) ; temp = (INT) ( 0.70 * (DOUBLE) numcellsG ) ; criticalMass = ( temp > 8 ) ? temp : 8 ; /* first calculate the average number of cells net is connected */ /* in order to readjust critical mass in strange situations */ num_cell_for_net = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { for( cell = 1 ; cell <= totalcellsG ; cell++ ) { vector[cell] = 0 ; } count = 0 ; dimptr = netarrayG[net] ; for( netptr = dimptr->pins ; netptr ; netptr = netptr->next ) { cell = netptr->cell ; if( vector[cell] == 0 ) { vector[cell] = 1 ; count++ ; } } num_cell_for_net += count ; } average_cells_per_net = (INT) ceil( (DOUBLE)num_cell_for_net / (DOUBLE) numnetsG ) ; /* critical mass must at least be the average */ criticalMass = MAX( criticalMass, average_cells_per_net ) ; /* now it safe to discard nets */ for( net = 1 ; net <= numnetsG ; net++ ) { for( cell = 1 ; cell <= numcellsG ; cell++ ) { vector[cell] = 0 ; } count = 0 ; dimptr = netarrayG[net] ; for( netptr = dimptr->pins ; netptr ; netptr = netptr->next ) { cell = netptr->cell ; if( cell <= numcellsG ) { if( vector[cell] == 0 ) { vector[cell] = 1 ; count++ ; } } } if( count > criticalMass ) { dimptr->skip = 1 ; } } Ysafe_free( vector ) ; return ; } graywolf-0.1.4+20170307gite1bf319/src/twmc/selectpin.c000066400000000000000000000042201305746555600216550ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: selectpin.c DESCRIPTION:attempts single pin move, if unsuccessful attempts pairwise pin flip. CONTENTS: BOOL selectpin( acellptr ) CELLBOXPTR acellptr ; DATE: Feb 5, 1988 REVISIONS: July 21, 1988 - modified selectpin to work with Jimmy's controller. Mar 20, 1989 - rewrote to work with new data structure ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) selectpin.c version 3.3 9/5/90" ; #endif #include #include BOOL selectpin( acellptr ) CELLBOXPTR acellptr ; { } graywolf-0.1.4+20170307gite1bf319/src/twmc/setpwates.c000066400000000000000000000076471305746555600217260ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: setpwates.c DESCRIPTION:Adde pin weights to all the tiles for wirelength estimation. CONTENTS: setpwates() DATE: Apr 2, 1989 - added header and instance code. REVISIONS: May 14, 1989 - set weights to zero for stdcell case. Mon Feb 4 02:20:39 EST 1991 - updated for new wire estimator NOTE that standard cell weights are -2 as a flag. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) setpwates.c version 3.4 2/4/91" ; #endif #include #include setpwates() { TILEBOXPTR tileptr ; CELLBOXPTR cptr ; INSTBOXPTR instptr ; INT cell ; INT i ; INT numinstances ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cptr = cellarrayG[cell] ; if( instptr = cptr->instptr ){ numinstances = instptr->numinstances ; } else { numinstances = 1 ; } for( i=0; i < numinstances; i++ ){ if( instptr ){ tileptr=instptr->tile_inst[i] ; } else { tileptr=cptr->tiles ; } if( cptr->celltype == STDCELLTYPE ){ if( new_wire_estG ){ for( ;tileptr;tileptr=tileptr->next ){ /* no area estimation for stdcells */ /* make the weight negative as a flag in wireestxy2 */ tileptr->lweight = -2.0 ; tileptr->rweight = -2.0 ; tileptr->bweight = -2.0 ; tileptr->tweight = -2.0 ; } /* end for loop */ } else { for( ;tileptr;tileptr=tileptr->next ){ /* no area estimation for stdcells */ tileptr->lweight = 0.0 ; tileptr->rweight = 0.0 ; tileptr->bweight = 0.0 ; tileptr->tweight = 0.0 ; } /* end for loop */ } } else if( new_wire_estG ){ /* in this case these weights have been set in watesides */ continue ; } else { for( ;tileptr;tileptr=tileptr->next ){ if( tileptr->lweight > pinsPerLenG ) { tileptr->lweight /= pinsPerLenG ; } else { tileptr->lweight = 1.0 ; } if( tileptr->rweight > pinsPerLenG ) { tileptr->rweight /= pinsPerLenG ; } else { tileptr->rweight = 1.0 ; } if( tileptr->bweight > pinsPerLenG ) { tileptr->bweight /= pinsPerLenG ; } else { tileptr->bweight = 1.0 ; } if( tileptr->tweight > pinsPerLenG ) { tileptr->tweight /= pinsPerLenG ; } else { tileptr->tweight = 1.0 ; } } /* end for loop */ } /* end test of celltype */ } /* end instance loop */ } return ; } /* end setpwates */ graywolf-0.1.4+20170307gite1bf319/src/twmc/sortpad.c000066400000000000000000000227111305746555600213500ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: sortpad.c DESCRIPTION:This file contains the utility routines to sort pads for the new pad routines. CONTENTS: DATE: Aug 12, 1988 REVISIONS: Sun Jan 20 21:34:36 PST 1991 - ported to AIX. Sat Feb 23 00:17:28 EST 1991 - added placepads algorithm. Tue Mar 12 17:05:03 CST 1991 - fixed initialization problem with permutation. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) sortpad.c version 3.6 3/12/91" ; #endif #include #include #include static INT compare_pads(); static INT sort_by_pos(); static install_pad_groups(); static permute_pads(); sort_pads() { INT i ; /* pad counter */ INT pos ; /* position in place array */ INT compare_pads() ; /* how to sort the pads initially */ INT sort_by_pos() ; /* how to sort the pads */ PADBOXPTR pad ; /* current pad */ /* first perform an initial sort to order the pads by side, hierarchy, */ /* and position on the side. */ Yquicksort( &(sortarrayG[1]), totalpadsG, sizeof(PADBOXPTR), compare_pads ); D( "placepads/after_sort", print_pads("pads after initial sort\n",sortarrayG, totalpadsG ) ; ) ; /* Now make sure the pads are permuted correctly */ for( i = 1; i <= totalpadsG; i++ ){ pad = sortarrayG[i]; if( pad->hierarchy == ROOT ){ permute_pads( pad ) ; } } /* NOW INSTALL THE PAD GROUPS IN THEIR PROPER ORDER. There are 2 cases: */ /* CASE I CONTIGUOUS INSURE THAT GROUP REMAIN INTACT */ pos = 1 ; for( i = 1; i <= totalpadsG; i++ ){ pad = sortarrayG[i]; if( pad->hierarchy == ROOT || pad->hierarchy == NONE ){ install_pad_groups( pad, &pos ) ; } } D( "placepads/after_install", print_pads("pads after install\n",placearrayG,numpadsG); ) ; if(!(contiguousG)){ /* CASE II - LEAVES ARE ALIGNED LIKE ORDINARY PADS IF THEY HAVE NO */ /* CONSTRAINTS SUCH AS ORDER OR PERMUTE. **/ Yquicksort( &(placearrayG[1]), numpadsG, sizeof(PADBOXPTR), sort_by_pos ) ; D( "placepads/after_ncontsort", print_pads("pads after noncontiguous sort\n",placearrayG,numpadsG); ) ; } } /* end SortPads */ /* ***************************************************************** */ /*** compare_pads() RETURNS TRUE IF ARG1 > ARG2 BY ITS OWN RULES **/ static INT compare_pads( padptr1, padptr2 ) PADBOXPTR *padptr1, *padptr2 ; { PADBOXPTR pad1, pad2; pad1 = *padptr1 ; pad2 = *padptr2 ; if( pad1->padside != pad2->padside) { return( pad1->padside - pad2->padside ) ; } if( pad1->hierarchy != pad2->hierarchy ){ /*** MOVE ROOTS TO THE BEGINNING OF ARRAY MOVE */ /* LEAVES ARE SEPARATED, ROOTS ARE MERGED **/ if( pad1->hierarchy == SUBROOT ){ return( 1 ) ; } else if( pad2->hierarchy == SUBROOT ){ return( 0 ) ; } else if( pad1->hierarchy == LEAF ){ return( 1 ) ; } else if( pad2->hierarchy == LEAF ){ return( 0 ) ; } } if( pad1->position == pad2->position ){ return( pad1->tiebreak - pad2->tiebreak ) ; } else { return( pad1->position - pad2->position ) ; } } /* end compare_pads */ /* ***************************************************************** */ static INT sort_by_pos( padptr1, padptr2 ) PADBOXPTR *padptr1, *padptr2 ; { PADBOXPTR pad1, pad2; BOOL pad1fixed, pad2fixed ; pad1 = *padptr1 ; pad2 = *padptr2 ; if( pad1->padside != pad2->padside) { return( pad1->padside - pad2->padside ) ; } if( pad1->ordered || pad1->permute ){ pad1fixed = TRUE ; } else { pad1fixed = FALSE ; } if( pad2->ordered || pad2->permute ){ pad2fixed = TRUE ; } else { pad2fixed = FALSE ; } if( pad1fixed && pad2fixed && !(contiguousG) ){ return( 0 ) ; } else if( pad1fixed && contiguousG ){ return( 0 ) ; } else if( pad2fixed && contiguousG ){ return( 1 ) ; } else if( pad1->position == pad2->position ){ return( pad1->tiebreak - pad2->tiebreak ) ; } else { return( pad1->position - pad2->position ) ; } } /* end sort_by_pos */ /* ***************************************************************** */ static install_pad_groups( pad, position ) PADBOXPTR pad ; INT *position ; { INT i ; /* pad counter */ INT howmany ; /* number of pads in group */ INT initial_position ; /* position of next open place in placearray */ INT sort_by_pos() ; /* how to sort the pads */ PADBOXPTR child ; /* current child */ PADBOXPTR *temparray ; /* temporary array to sort pads */ initial_position = *position ; if( pad->padtype == PADCELLTYPE ){ placearrayG[initial_position] = pad ; *position = ++initial_position ; } else { howmany = pad->children[HOWMANY] ; temparray = (PADBOXPTR *) Yvector_alloc( 1,howmany,sizeof(PADBOXPTR) ) ; for( i = 1 ;i <= howmany ; i++ ){ child = padarrayG[ pad->children[i] ] ; temparray[i] = child ; } /* now sort the subroots or leaves to obey both order constraints */ /* and permutation constraints. Otherwise try to sort by opt. pos.*/ Yquicksort( &(temparray[1]), howmany, sizeof(PADBOXPTR), sort_by_pos ) ; /* now that we have subroots or leaves in correct order */ /* look at next level down */ for( i = 1 ;i <= howmany ; i++ ){ child = temparray[ i ] ; install_pad_groups( child, position ) ; } Yvector_free( temparray, 1, sizeof(PADBOXPTR) ) ; } } /* end install_pad_groups */ /* ***************************************************************** */ static permute_pads( pad ) PADBOXPTR pad ; { INT tmp ; /* used to reverse permutable pads */ INT j, k ; /* used to reverse pads */ INT i ; /* padcounter */ INT howmany ; /* number of children in current padgroup */ INT max_pos ; /* max. value of the ideal positions of pad in pg */ INT min_pos ; /* min. value of the ideal positions of pad in pg */ INT forward_cost ; /* cost to place pads in current order */ INT bakward_cost ; /* cost to place pads in reverse order */ INT proposed_fpos ; /* proposed uniformly spaced pos in forward order */ INT proposed_bpos ; /* proposed uniformly spaced pos in bakward order */ INT *array ; /* sort the children */ DOUBLE spacing ; /* spacing if we place pads in pg uniformly */ PADBOXPTR child ; /* current child */ if( pad->permute ){ /* first calculate span of padgroup */ howmany = pad->children[HOWMANY] ; ASSERTNRETURN( howmany >= 2,"permute_pads", "Must have at least 2 pads in a padgroup\n"); child = padarrayG[pad->children[1]]; min_pos = child->position ; max_pos = child->position ; for( i = 2; i <= howmany ; i++ ){ child = padarrayG[pad->children[i]]; min_pos = MIN( child->position, min_pos ) ; max_pos = MAX( child->position, max_pos ) ; } /* now find the cost if we evenly space the pads over that region */ spacing = (DOUBLE) (max_pos - min_pos) / (DOUBLE) (howmany - 1) ; forward_cost = 0 ; bakward_cost = 0 ; for( i = 1; i <= howmany ; i++ ){ child = padarrayG[pad->children[i]]; proposed_fpos = min_pos + ROUND( (i - 1) * spacing ) ; proposed_bpos = max_pos - ROUND( (i - 1) * spacing ) ; forward_cost += ABS( child->position - proposed_fpos ) ; bakward_cost += ABS( child->position - proposed_bpos ) ; } if( bakward_cost < forward_cost ) { /* we need to reverse the permutation */ array = pad->children + 1; j = howmany - 1; k = 0; while( k < j ){ tmp = array[j]; array[j--] = array[k]; array[k++] = tmp; } } } /*** NEED TO CHECK THE CHILDREN REGARDLESS OF THE PERMUTABILITY OF THE PARENT ROOT */ for( i = 1; i <= pad->children[HOWMANY]; i++ ){ child = padarrayG[pad->children[i]]; if( child->hierarchy == SUBROOT){ permute_pads( child ) ; } } } /* end permute_pads */ /* ***************************************************************** */ graywolf-0.1.4+20170307gite1bf319/src/twmc/sortpin.c000066400000000000000000000066411305746555600213760ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: sortpin.c DESCRIPTION:Sort pins to use with incremental bounding box routines. CONTENTS: DATE: Mar 27, 1989 REVISIONS: May 2, 1990 - added verify_pad_pins as an error checking mechanism to insure that pad pins are inside the channel graph. Sun Jan 20 21:34:36 PST 1991 - ported to AIX. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) sortpin.c version 3.7 10/18/91" ; #endif #include #include #include static INT comparePin() ; sortpins() { INT j , n , cell ; CELLBOXPTR ptr ; PINBOXPTR pin, *xpptr ; /* static INT comparePin() ;*/ INT maxpins ; /* find maximum number of pins on a cell for allocation */ maxpins = INT_MIN ; for( cell = 1 ; cell <= totalcellsG ; cell++ ) { ptr = cellarrayG[ cell ] ; maxpins = MAX( ptr->numpins, maxpins ) ; } /* allocate array for sort */ xpptr = (PINBOXPTR *) Ysafe_malloc((maxpins+1) * sizeof(PINBOXPTR) ) ; /* now go thru all cells sorting pins */ for( cell = 1 ; cell <= totalcellsG ; cell++ ) { ptr = cellarrayG[ cell ] ; n = 0 ; for( pin = ptr->pinptr ; pin ; pin = pin->nextpin ) { xpptr[ n++ ] = pin ; } /* net number then by pin name */ Yquicksort( (char *)xpptr, n, sizeof(PINBOXPTR),comparePin ) ; /* terminate list */ xpptr[ n ] = NIL(PINBOXPTR) ; ptr->pinptr = xpptr[ 0 ] ; for( j = 0 ; j < n ; j++ ) { xpptr[j]->nextpin = xpptr[j+1] ; } } Ysafe_free( xpptr ) ; } /* end sortpins */ static INT comparePin( pinA , pinB ) PINBOXPTR *pinA , *pinB ; { /* first sort by net number */ if( (*pinA)->net != (*pinB)->net ){ return( (*pinA)->net - (*pinB)->net ) ; } else { /* if nets are equal sort by pinname */ return( strcmp( (*pinA)->pinname,(*pinB)->pinname ) ) ; } } /* end comparePin */ graywolf-0.1.4+20170307gite1bf319/src/twmc/temp.h000066400000000000000000000042321305746555600206440ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) temp.h (Yale) version 3.4 2/4/91" FILE: temp.c DESCRIPTION:definitions for temperature control CONTENTS: DATE: Mar 01, 1989 REVISIONS: Mon Feb 4 02:21:54 EST 1991 - added MINTUPDATE def. ----------------------------------------------------------------- */ #ifndef TEMP_H #define TEMP_H #define RATIOUPPERBOUND 0.15 /* control to find Tratio */ #define RATIOLOWERBOUND 0.05 /* control to find Tratio */ #define LOWTEMPRATIO 0.05 /* low temp anneal acceptance ratio */ #define EPSILON 0.000001 /* error tolerance */ #define DEFAULTTEMP 5.0 /* default temp for low temp anneal */ #define FINISHED 0.99999 /* round to 1.0 we are finished */ /* Definitions for heuristic temperature scheduler */ /* ----------------------------------------------------------------- The temperature regions are defined as follows: Iterations Purpose -2 - 0 Initialization 1 - HIGHTEMP High temperature regime exponential decay HIGHTEMP+1 - MEDTEMP Critical temp. 0.44 - range limiter MEDTEMP+1 - LASTTEMP Low temperature regime exponential decay. ----------------------------------------------------------------------- */ #define INIT_ITERATION -2 /* initialization iteration */ #define HIGHTEMP 23.00 /* last iteration of high temp regime */ #define MEDTEMP 81.00 /* last iteration of range limiter */ #define LOWTEMP 125.0 /* temperature @ 6% acceptance rate */ #define TURNOFFT 125.0 /* iteration of neg. feddback turnoff */ #define LASTTEMP 155.00 /* last iteration */ #define CRITRATIO 0.44 /* critical ratio */ #define LOWRATIO 0.06 /* temperature for controler turn off */ #define ACCEPTDAMPFACTOR 0.025 /* damping factor for acceptance rate*/ #define ACCEPTDAMPFACTOR2 0.25 /* damping factor for low temp's */ #define NUMTUPDATES 400 /* max number of T updates per iteration*/ #define MINTUPDATE 14 /* mininum # moves before update */ #endif /* TEMP_H */ graywolf-0.1.4+20170307gite1bf319/src/twmc/tidialog.h000066400000000000000000000044211305746555600214730ustar00rootroot00000000000000static TWDIALOGBOX dialogS[53] = { 1,5,8," ACCEPT ",2,3,0, 1,25,8," CANCEL ",2,2,0, 2,15,9,"Edit Cell",0,3,0, 3,5,13,"Name",0,4,0, 4,5,12,"Number",0,4,0, 5,5,8,"Xcenter:",0,4,0, 5,14,8,"10",1,4,0, 6,5,8,"Ycenter:",0,4,0, 6,14,8,"10",1,4,0, 7,5,7,"Orient:",3,4,10, 7,14,2,"1 ",2,4,1, 7,16,2,"2 ",2,4,1, 7,18,2,"3 ",2,4,1, 7,20,2,"4 ",2,4,1, 7,22,2,"5 ",2,4,1, 7,24,2,"6 ",2,4,1, 7,26,2,"7 ",2,4,1, 7,28,2,"8 ",2,4,1, 9,5,19,"Valid orientations",0,4,0, 10,7,1,"1",3,4,20, 10,14,5,"valid",2,6,2, 10,25,7,"invalid",2,3,2, 11,7,1,"2",3,4,23, 11,14,5,"valid",2,6,3, 11,25,7,"invalid",2,3,3, 12,7,1,"3",3,4,26, 12,14,5,"valid",2,6,4, 12,25,7,"invalid",2,3,4, 13,7,1,"4",3,4,29, 13,14,5,"valid",2,6,5, 13,25,7,"invalid",2,3,5, 14,7,1,"5",3,4,32, 14,14,5,"valid",2,6,6, 14,25,7,"invalid",2,3,6, 15,7,1,"6",3,4,35, 15,14,5,"valid",2,6,7, 15,25,7,"invalid",2,3,7, 16,7,1,"7",3,4,38, 16,14,5,"valid",2,6,8, 16,25,7,"invalid",2,3,8, 17,7,1,"8",3,4,41, 17,14,5,"valid",2,6,9, 17,25,7,"invalid",2,3,9, 19,5,5,"Fixed",3,4,44, 19,14,3,"on ",2,6,10, 19,25,3,"off",2,3,10, 21,1,35,"To change case fields put pointer",0,4,0, 22,1,35,"in window and click. To change",0,4,0, 23,1,35,"input fields put pointer in window",0,4,0, 24,1,35,"and back up over current contents",0,4,0, 25,1,35,"using the delete key. After modifying",0,4,0, 26,1,35,"the field, hit the return key.",0,4,0, 0,0,0,0,0,0,0 } ; /* timberwolf to ice view translations */ INT tw2ice(orient) INT orient; { switch (orient){ case 0: return(1); case 1: return(7); case 2: return(5); case 3: return(3); case 4: return(8); case 5: return(6); case 6: return(2); case 7: return(4); } } INT ice2tw(orient) INT orient; { switch (orient){ case 1: return(0); case 2: return(6); case 3: return(3); case 4: return(7); case 5: return(2); case 6: return(5); case 7: return(1); case 8: return(4); } } /* end ice2tw */ graywolf-0.1.4+20170307gite1bf319/src/twmc/twstats.c000066400000000000000000000122651305746555600214100ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: twstats.c DESCRIPTION:user statistic information CONTENTS: twstats( ) prnt_netinfo( ) DATE: Feb 29, 1988 REVISIONS: Jan 30, 1989 - added number of net info at beginning of run. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) twstats.c version 3.3 9/5/90" ; #endif #include #include #define MAXPININFO 100 static INT maxpinS = 0 ; twstats() { INT temp ; DOUBLE reduction ; OUT3("\nInitial Wiring Cost: %d Final Wiring Cost: %d\n", icostG , fcostG ) ; if( icostG != 0 ) { temp = 100 - (INT)( (DOUBLE)fcostG / (DOUBLE)icostG * 100.0 ) ; OUT2("############ Percent Wire Cost Reduction: %d\n\n", temp ) ; } OUT3("\nInitial Wire Length: %d Final Wire Length: %d\n", iwireG, fwireG ) ; if( icostG != 0 ) { temp = 100 - (INT)( (DOUBLE) fwireG / (DOUBLE) iwireG * 100.0 ) ; OUT2("*********** Percent Wire Length Reduction: %d\n\n", temp ) ; } OUT3("\nInitial Horiz. Wire: %d Final Horiz. Wire: %d\n", iwirexG , fwirexG ) ; if( iwirexG != 0 ) { temp = 100 - (INT)( (DOUBLE)fwirexG / (DOUBLE)iwirexG * 100.0 ) ; OUT2("$$$$$$$$$ Percent H-Wire Length Reduction: %d\n\n", temp ) ; } OUT3("\nInitial Vert. Wire: %d Final Vert. Wire: %d\n", iwireyG , fwireyG ) ; if( iwireyG != 0 ) { temp = 100 - (INT)( (DOUBLE)fwireyG / (DOUBLE)iwireyG * 100.0 ) ; OUT2("@@@@@@@@@ Percent V-Wire Length Reduction: %d\n\n", temp ) ; } OUT1("\nStatistics:\n"); OUT2("Number of Cells: %d\n", numcellsG ); OUT2("Number of Pads: %d\n", numpadsG ); OUT2("Number of Nets: %d \n", numnetsG ) ; OUT2("Number of Pins: %d \n", numpinsG ) ; /* write wire reduction to log file */ if( avg_funcG > 0 ){ reduction = (DOUBLE) avg_funcG / (DOUBLE) fwireG ; sprintf( YmsgG, "TimberWolfMC reduction:%4.4le", reduction ) ; Ylog_start( cktNameG, YmsgG ) ; } return ; } static INT printPinS = 0 ; set_print_pin( pin ) INT pin ; { printPinS = pin ; } prnt_netinfo() { SHORT numpins ; INT net_pin_num[ MAXPININFO+1 ] ; INT n, net, cell ; NETBOXPTR dimptr ; PINBOXPTR termptr ; if( printPinS ){ OUT2("\n\nPIN LISTING MODE ON FOR NETS WITH %d PINS\n", printPinS ) ; OUT1( "-----------------------------------------\n" ) ; } for( n = 1 ; n <= MAXPININFO ; n++ ) { net_pin_num[ n ] = 0 ; } for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[ net ] ; /* count the number of pins on a net */ numpins = 0 ; for( termptr=dimptr->pins;termptr;termptr=termptr->next){ numpins++ ; } dimptr->numpins = numpins ; /* save the result */ if( printPinS ){ if( numpins == printPinS ){ OUT4( "A net with %d pin[s]:net%d - %s\n" , printPinS, net, netarrayG[net]->nname ) ; for( termptr=dimptr->pins;termptr;termptr=termptr->next){ cell = termptr->cell ; OUT4( "\tpinname:%s cellname:%s cellnum:%d\n", termptr->pinname, cellarrayG[cell]->cname, cell ) ; } } } /* record the maximum number of pins for later use */ maxpinS = MAX( maxpinS, numpins ) ; if( numpins > MAXPININFO ) { net_pin_num[ MAXPININFO ]++ ; } else { net_pin_num[ numpins ]++ ; } } for( n = 1 ; n < MAXPININFO ; n++ ) { if( net_pin_num[ n ] ){ OUT3( "The number of nets with %2d pins is %d\n", n , net_pin_num[ n ] ) ; } } OUT3( "The number of nets with %d pins or more is %d\n", MAXPININFO,net_pin_num[ MAXPININFO ] ) ; OUT2( "The total number of nets is: %d\n", numnetsG ) ; OUT2( "The maximum number of pins on a single net is: %d\n", maxpinS ) ; } /* end prnt_netinfo */ get_max_pin() { return( maxpinS ) ; } /* end get_max_pin */ graywolf-0.1.4+20170307gite1bf319/src/twmc/uaspect.c000066400000000000000000000211741305746555600213420ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: uaspect.c DESCRIPTION:change aspect ratio of cell CONTENTS: BOOL uaspect( int, DOUBLE ) INT a ; DOUBLE newAspect ; DATE: Jan 30, 1988 REVISIONS: Jul 22, 1988 - deleted aspect0 field in CELLBOX record. Aug 25, 1988 - calls to ufixpin and usoftpin changed. Oct 22, 1988 - changed to sqrt of overlap penalty Apr 3, 1989 - modified to allow multiple tiles for aspect ratio change. Apr 23, 1990 - modified for the new pin code. Sat Apr 27 01:09:01 EDT 1991 - fixed problem with aspect ratio and added aspect ratio initialization. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) uaspect.c version 3.5 4/27/91" ; #endif #include #include #include #include #define NEWVERTICES TRUE BOOL uaspect( a , newAspect ) INT a ; DOUBLE newAspect ; { CELLBOXPTR acellptr ; TILEBOXPTR atileptr ; PINBOXPTR pin ; MOVEBOXPTR newtile ; BOUNBOXPTR bounptr ; VERTBOXPTR vert ; SOFTBOXPTR spin ; DOUBLE aspFactor , val ; INT cost, newpenalty, newbinpenal ; INT Hdiv2, Wdiv2 ; INT site, aorient ; INT i, inst ; INT oleft, obottom, oright, otop ; INT newtimepenalty, newtimepenal ; INT *xorig ; INT *xnew ; INT *yorig ; INT *ynew ; acellptr = cellarrayG[ a ] ; aorient = acellptr->orient ; inst = acellptr->cur_inst ; /* determine aspect ratio orientation */ aspFactor = sqrt( newAspect / acellptr->orig_aspect ) ; /* use original bounding box to calculate changes */ bounptr = acellptr->bounBox[8] ; /* original bbox */ oleft = bounptr->l ; obottom = bounptr->b ; oright = bounptr->r ; otop = bounptr->t ; val = (DOUBLE) (otop - obottom) * aspFactor ; Hdiv2 = ROUND( val ) / 2 ; val = (DOUBLE) (oright - oleft) / aspFactor ; Wdiv2 = ROUND( val ) / 2 ; /* calculate the new aspect ratio of softtiles */ i = 1 ; new_apos0G->numtiles = acellptr->numtiles ; new_apos0G->loaded_previously = TRUE ; for( atileptr = acellptr->tiles;atileptr;atileptr = atileptr->next ){ newtile = new_aposG[i++] ; val = (DOUBLE)(atileptr->orig_left - oleft) / aspFactor; newtile->l = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(atileptr->orig_right - oleft) / aspFactor; newtile->r = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(atileptr->orig_bottom - obottom) * aspFactor; newtile->b = ROUND( val ) - Hdiv2 ; val = (DOUBLE)(atileptr->orig_top - obottom) * aspFactor; newtile->t = ROUND( val ) - Hdiv2 ; newtile->lw = atileptr->lweight ; newtile->rw = atileptr->rweight ; newtile->bw = atileptr->bweight ; newtile->tw = atileptr->tweight ; } /* end calculation of new tiles */ /* modify the vertices of the cell for the softpin moves */ vert = acellptr->vertices ; xorig = vert->x_orig ; xnew = vert->x_new ; yorig = vert->y_orig ; ynew = vert->y_new ; for( i = 1; i <= acellptr->numsides; i++ ){ val = (DOUBLE)(xorig[i] - oleft) / aspFactor ; xnew[i] = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(yorig[i] - obottom) * aspFactor ; ynew[i] = ROUND( val ) - Hdiv2 ; } newbinpenal = binpenalG ; newbinpenal += overlap( /* old_apos, new_apos */ ) ; /* scale new penalty for feedback circuit */ newpenalty = (INT) ( lapFactorG * sqrt( (DOUBLE) newbinpenal ) ) ; /* -------------- update the position of all pins --------------------- */ /* update the positions of all the hardpins first */ for( pin = acellptr->pinptr ; pin ; pin = pin->nextpin ) { if( pin->type == HARDPINTYPE ){ val = (DOUBLE)(pin->txpos_orig[inst] - oleft) / aspFactor ; pin->txpos_new = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(pin->typos_orig[inst] - obottom) * aspFactor ; pin->typos_new = ROUND( val ) - Hdiv2 ; } } /* now determine placement of pins using new vertices for the cell */ placepin( a, NEWVERTICES ) ; cost = funccostG ; clear_net_set() ; /* reset set to mark nets that have changed position */ cost += unet( acellptr->pinptr ) ; newtimepenal = timingpenalG ; newtimepenal += calc_incr_time( a ) ; ASSERT( newtimepenal == dcalc_full_penalty(),"uaspect","Timing woes\n") ; /* scale new timing penalty */ newtimepenalty = (INT) ( timeFactorG * (DOUBLE) newtimepenal ) ; if( acceptt( funccostG + penaltyG + timingcostG - cost - newpenalty - newtimepenalty )){ /* update current terminal positions from original positions */ for( pin = acellptr->pinptr ; pin ; pin = pin->nextpin ) { pin->txpos = pin->txpos_new ; pin->typos = pin->typos_new ; if( pin->type != HARDPINTYPE ){ pin->txpos_orig[inst] = pin->txpos ; pin->typos_orig[inst] = pin->typos ; } } upin_accept( acellptr->pinptr ) ; /* update the aspect ratio of softtile */ for( atileptr = acellptr->tiles;atileptr;atileptr = atileptr->next ){ val = (DOUBLE)(atileptr->orig_left - oleft) / aspFactor; atileptr->left = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(atileptr->orig_right - oleft) / aspFactor; atileptr->right = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(atileptr->orig_bottom - obottom) * aspFactor; atileptr->bottom = ROUND( val ) - Hdiv2 ; val = (DOUBLE)(atileptr->orig_top - obottom) * aspFactor; atileptr->top = ROUND( val ) - Hdiv2 ; } /* end calculation of new tiles */ /* delay recalculation of bounding box views until needed */ acellptr->boun_valid = FALSE ; /* update the vertices of the cell by swapping arrays */ xnew = vert->x_new ; vert->x_new = vert->x ; vert->x = xnew ; ynew = vert->y_new ; vert->y_new = vert->y ; vert->y = ynew ; update_overlap( /* old_aposG */ ) ; update_time( a ) ; /* save the current aspect ratio */ acellptr->aspect = newAspect ; funccostG = cost ; penaltyG = newpenalty ; binpenalG = newbinpenal ; timingcostG = newtimepenalty ; timingpenalG = newtimepenal ; return (ACCEPT) ; } else { return (REJECT) ; } } /* end uaspect */ initialize_aspect_ratios() { INT i ; /* counter */ INT binX, binY ; /* set initial bins */ CELLBOXPTR cptr ; /* current cell pointer */ if( numsoftG > 0 || numstdcellG > 0 ){ TG = 1.0e30; /*** set to VERY HIGH temperature. ***/ /* first determine number of softcell with uncommitted pins */ for( i=1;i<=totalcellsG;i++ ){ cptr = cellarrayG[i] ; if( cptr->celltype == SOFTCELLTYPE || cptr->celltype == STDCELLTYPE ){ if( cptr->aspect < cptr->aspLB || cptr->aspect > cptr->aspUB ){ /* setup for uaspect */ new_apos0G->cell = old_apos0G->cell = i ; old_apos0G->orient = new_apos0G->orient = cptr->orient ; new_apos0G->xcenter = old_apos0G->xcenter = cptr->xcenter ; new_apos0G->ycenter = old_apos0G->ycenter = cptr->ycenter ; /* calculate bin for move determination */ binX = SETBINX(cptr->xcenter) ; binY = SETBINY(cptr->ycenter) ; newbptrG = binptrG[binX][binY] ; newCellListG = newbptrG->cells ; /* now set initial aspect ratio */ if(!(uaspect( i,(cptr->aspLB + cptr->aspUB) / 2.0))){ M( WARNMSG,"initialize_aspect_ratio", "Failed in aspect ratio initialization. Trying again\n" ) ; i-- ; } } } } } } /* end initialize_aspect_ratios */ graywolf-0.1.4+20170307gite1bf319/src/twmc/uinst.c000066400000000000000000000264021305746555600210370ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: uinst.c DESCRIPTION:change cell instance CONTENTS: DATE: Apr 4, 1989 - original coding WPS REVISIONS: Oct 3, 1989 - fixed problem with overlap calculation. Apr 23, 1990 - modified to work with new softpin code. Mon Feb 4 02:22:36 EST 1991 - fixed problem with numsides not being set. Sat Apr 27 01:10:04 EDT 1991 - fixed problem with aspect ratio calculation. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) uinst.c version 3.9 11/23/91" ; #endif #include #include #include #include #define NEWVERTICES TRUE #define HOWMANY 0 BOOL uinst( /* old_apos, new_apos */ ) /* MOVEBOXPTR *old_apos, *new_apos ; */ { CELLBOXPTR acellptr ; PINBOXPTR anewtermptr, pin ; BOUNBOXPTR bounptr ; MOVEBOXPTR newtile ; /* temp pointer for easier access */ VERTBOXPTR vert ; /* the vertices of the cell */ TILEBOXPTR tptr ; /* temp pointer for tiles */ INSTBOXPTR instptr ; /* pointer to the cells instance box */ DOUBLE aspFactor ; DOUBLE val ; INT cost , newpenalty, newbinpenal, newtimepenalty, newtimepenal ; INT a, i ; INT lastinst, newinst ; INT aorient, axcenter, aycenter ; INT oleft, obottom, oright, otop ; INT Hdiv2, Wdiv2 ; INT *xorig, *xnew, *yorig, *ynew ; INT numsides, howmany ; /* ----------------------------------------------------------------- global information is stored in element zero of position arrays set a's MOVEBOX record - new position records have been initialized in uloop(). */ a = new_apos0G->cell ; acellptr = cellarrayG[a] ; anewtermptr = acellptr->pinptr ; aorient = acellptr->orient ; instptr = acellptr->instptr ; lastinst = instptr->numinstances - 1 ; do { newinst = PICK_INT( 0, lastinst ) ; } while( newinst == acellptr->cur_inst ) ; clear_net_set() ; /* reset set to mark nets that have changed position */ newbinpenal = binpenalG ; /* these are common to both soft and hard cell moves */ acellptr->numsides = instptr->numsides[newinst] ; vert = acellptr->vertices = instptr->vert_inst[newinst] ; if( acellptr->softflag ){ /* ---------------------------------------------------------------- Load old_aposG normally but we must load new_aposG with new tiles. Install the new tiles in new_aposG - make sure we count all tiles. In the case of soft cells adjust aspect ratio so it coincides with current ratio to maximize chance move will get accepted. ------------------------------------------------------------------ */ /* determine aspect ratio orientation */ aspFactor = sqrt( acellptr->aspect / acellptr->orig_aspect ) ; /* use original bounding box to calculate changes */ bounptr = instptr->bounBox[newinst][8] ; /* original bbox */ oleft = bounptr->l ; obottom = bounptr->b ; oright = bounptr->r ; otop = bounptr->t ; val = (DOUBLE) (otop - obottom) * aspFactor ; Hdiv2 = ROUND( val ) / 2 ; val = (DOUBLE) (oright - oleft) / aspFactor ; Wdiv2 = ROUND( val ) / 2 ; /* calculate the new aspect ratio of softtiles */ i = 0 ; new_apos0G->numtiles = instptr->numtile_inst[newinst] ; new_apos0G->loaded_previously = TRUE ; for( tptr = instptr->tile_inst[newinst];tptr;tptr = tptr->next ){ newtile = new_aposG[++i] ; val = (DOUBLE)(tptr->orig_left - oleft) / aspFactor; newtile->l = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(tptr->orig_right - oleft) / aspFactor; newtile->r = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(tptr->orig_bottom - obottom) * aspFactor; newtile->b = ROUND( val ) - Hdiv2 ; val = (DOUBLE)(tptr->orig_top - obottom) * aspFactor; newtile->t = ROUND( val ) - Hdiv2 ; newtile->lw = tptr->lweight ; newtile->rw = tptr->rweight ; newtile->bw = tptr->bweight ; newtile->tw = tptr->tweight ; } /* end calculation of new tiles */ /* ---------------------------------------------------------------- Modify the vertices of the cell for the softpin moves. Temporarily set the vertices field and number of sides of the instance to the new instance so that calculations in placepin.c will work properly. We must set this back if we fail. ------------------------------------------------------------------ */ xorig = vert->x_orig ; xnew = vert->x_new ; yorig = vert->y_orig ; ynew = vert->y_new ; for( i = 1, numsides=instptr->numsides[newinst]; i <= numsides; i++ ){ val = (DOUBLE)(xorig[i] - oleft) / aspFactor ; xnew[i] = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(yorig[i] - obottom) * aspFactor ; ynew[i] = ROUND( val ) - Hdiv2 ; } } else { /* hard or custom cell */ /* ---------------------------------------------------------------- Load old_aposG normally but we must load new_aposG with new tiles. Install the new tiles in new_aposG - make sure we count all tiles ------------------------------------------------------------------ */ i = 0 ; new_apos0G->numtiles = instptr->numtile_inst[newinst] ; new_apos0G->loaded_previously = TRUE ; for( tptr = instptr->tile_inst[newinst];tptr;tptr = tptr->next ){ newtile = new_aposG[++i] ; newtile->l = tptr->left ; newtile->r = tptr->right ; newtile->b = tptr->bottom ; newtile->t = tptr->top ; newtile->lw = tptr->lweight ; newtile->rw = tptr->rweight ; newtile->bw = tptr->bweight ; newtile->tw = tptr->tweight ; } /* end calculation of new tiles */ } /* end loading tiles into movebox */ newbinpenal += overlap( /* old_aposG, new_aposG */ ) ; /* scale new penalty for feedback circuit */ newpenalty = (INT) ( lapFactorG * sqrt( (DOUBLE) newbinpenal ) ) ; /* -------------- update the position of all pins --------------------- */ axcenter = acellptr->xcenter ; aycenter = acellptr->ycenter ; if( acellptr->softflag ){ /* ****** the soft pin case ****** */ for( pin = anewtermptr ; pin ; pin = pin->nextpin ) { if( pin->type == HARDPINTYPE ){ val = (DOUBLE)(pin->txpos_orig[newinst]-oleft) / aspFactor ; pin->txpos_new = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(pin->typos_orig[newinst]-obottom) * aspFactor ; pin->typos_new = ROUND( val ) - Hdiv2 ; } } howmany = (INT) acellptr->softpins[HOWMANY] ; /* set each pin's correct instance */ for( i = 1 ; i <= howmany; i++ ){ pin = acellptr->softpins[i] ; pin->softinfo = pin->soft_inst[newinst] ; } /* now determine placement of pins using new vertices for the cell */ placepin( a, NEWVERTICES ) ; } else { /* ****** the hard pin case ****** */ for( pin = anewtermptr ; pin ; pin = pin->nextpin ) { pin->txpos_new = pin->txpos_orig[newinst] ; pin->typos_new = pin->typos_orig[newinst] ; netarrayG[ pin->net ]->nflag = TRUE ; pin->flag = TRUE ; /* rel position is a macro which calculates absolute pin loc */ /* defined in relpos.h */ REL_POS( aorient, pin->newx, pin->newy, /* result global */ pin->txpos_new, pin->typos_new, /* cell relative */ axcenter, aycenter ) ; /* cell center */ } } cost = funccostG ; cost += unet( anewtermptr ) ; newtimepenal = timingpenalG ; newtimepenal += calc_incr_time( a ) ; ASSERT( newtimepenal == dcalc_full_penalty(),NULL,NULL) ; /* scale new timing penalty */ newtimepenalty = (INT) ( timeFactorG * (DOUBLE) newtimepenal ) ; /* ------------------------------------------------------------------ Note: we don't take overfill into account here because changing instance may upset overfill and it is a small worry. When we change to deterministic pin placement, problem will be eliminated. ----------------------------------------------------------------- */ if( acceptt( funccostG + penaltyG + timingcostG - cost - newpenalty - newtimepenalty )){ acellptr->cur_inst = newinst ; upin_accept( anewtermptr ) ; /* update current terminal positions from original positions */ for( pin = anewtermptr ; pin ; pin = pin->nextpin ) { pin->txpos = pin->txpos_new ; pin->typos = pin->typos_new ; if( pin->type != HARDPINTYPE ){ pin->txpos_orig[newinst] = pin->txpos ; pin->typos_orig[newinst] = pin->typos ; } } /* update tiles */ acellptr->tiles = instptr->tile_inst[newinst] ; acellptr->numtiles = instptr->numtile_inst[newinst] ; if( acellptr->softflag ){ /* update the aspect ratio of softtile */ for( tptr = acellptr->tiles;tptr;tptr = tptr->next ){ val = (DOUBLE)(tptr->orig_left - oleft) / aspFactor; tptr->left = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(tptr->orig_right - oleft) / aspFactor; tptr->right = ROUND( val ) - Wdiv2 ; val = (DOUBLE)(tptr->orig_bottom - obottom) * aspFactor; tptr->bottom = ROUND( val ) - Hdiv2 ; val = (DOUBLE)(tptr->orig_top - obottom) * aspFactor; tptr->top = ROUND( val ) - Hdiv2 ; } /* end calculation of new tiles */ /* update the vertices of the cell by swapping arrays */ xnew = vert->x_new ; vert->x_new = vert->x ; vert->x = xnew ; ynew = vert->y_new ; vert->y_new = vert->y ; vert->y = ynew ; } /* delay recalculation of bounding box views until needed */ acellptr->bounBox = instptr->bounBox[newinst] ; acellptr->boun_valid = FALSE ; update_overlap( /* old_aposG */ ) ; update_time( a ) ; funccostG = cost ; penaltyG = newpenalty ; binpenalG = newbinpenal ; timingcostG = newtimepenalty ; timingpenalG = newtimepenal ; return (ACCEPT) ; } else { /* we failed we must set vertices back if it is a soft cell */ lastinst = acellptr->cur_inst ; acellptr->vertices = instptr->vert_inst[lastinst] ; acellptr->numsides = instptr->numsides[lastinst] ; if( acellptr->softflag ){ /* set each pin's correct instance */ for( i = 1 ; i <= howmany; i++ ){ pin = acellptr->softpins[i] ; pin->softinfo = pin->soft_inst[lastinst] ; } } return (REJECT) ; } } /* end uinst */ graywolf-0.1.4+20170307gite1bf319/src/twmc/uloop.c000066400000000000000000001120331305746555600210270ustar00rootroot00000000000000/* * Copyright (C) 1988-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: uloop.c DESCRIPTION:inner loop of the simulated annealing algorithm. CONTENTS: uloop( limit ) INT limit ; make_movebox() ; save_uloop( fp ) FILE *fp ; INT read_uloop( fp ) FILE *fp ; DATE: Feb 5, 1988 REVISIONS: July 21, 1988 - reversed order of softpin and aspect ratio moves to work with controller. Sept 12, 1988 - rewrote cell move generation strategy. Sept 24, 1988 - added testloop code that is added initStatCollection and getStatistics ; Oct 20, 1988 - turn off bin controller when percentDone = 1.0 Oct 27, 1988 - handle 3 of 4 fixed cases. Modified controller Now use only active cells in choice of cell. Nov 14, 1988 - changed output format for easier reading. Nov 25, 1988 - changed sequence of aspect ratio changes. - modified negative feedback for better control. Dec 3, 1988 - added timing driven code. Dec 6, 1988 - fixed a bug in updating penalty. Jan 15, 1988 - added curve fit controller, changed overfill negative feedback control, and fixed GRAPHHEADING for new CRICKETGRAPH program. Jan 25, 1989 - added softPinArrayG to make soft pin moves more efficient. Cleaned up move selection strategy. Changed msg to YmsgG. Softpin moves are used during partitioning but overfill is not used. Removed extraneous call to placepads. Feb 25, 1989 - changed cell selection to get more cell moves at lower temperatures. Made percentDone a static variable so it could be used in calc_new_core which was added so that the same code could be called at any time to change the aspect ratio. Also added X11 graphics calls. Fixed problem with negative iterations Feb 26, 1989 - added wait for user feature. Feb 28, 1989 - updated schedule constants. Mar 02, 1989 - moved schedule constants to temp.h for consistency. Removed extraneous variables. Removed iter_count from call-now global. Moved negative feedback code to penalties.c. Mar 11, 1989 - added graphics conditional compile and always leave controller on. Mar 14, 1989 - began instance coding. Apr 20, 1989 - added partition coding. May 1, 1989 - fixed problem with cell in different classes trying to be swapped. Now we try another move correctly. May 18, 1989 - update forceGrid. May 24, 1989 - moved forceGrid to prboard. Jun 21, 1989 - fixed problem with move_box initialization. Sep 25, 1989 - made move box structure dynamic with respect to number of tiles. Apr 23, 1990 - now correctly handle the timing constant thru the use of delta change in timing cost. May 15, 1990 - fixed problem with standard cell macros. Sun Jan 20 21:34:36 PST 1991 - ported to AIX. Mon Feb 4 02:23:33 EST 1991 - added MINTUPDATE def. Sun May 5 14:59:39 EDT 1991 - now all moves influence temperature scheduler. Wed Jun 5 16:31:51 CDT 1991 - fixed problem with controller initialization Mon Aug 5 18:06:17 CDT 1991 - eliminated special partitioning case. Sat Nov 23 21:21:49 EST 1991 - began working with automatically setting move strategy. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) uloop.c version 3.14 4/6/92" ; #endif #include #include #include #include #define TMIN 1E-6 #define HOWMANY 0 extern INT pick_position() ; /* ----------------------------------------------------------------- important global definitions - defined in custom.h MOVEBOXPTR *old_aposG, *new_aposG, *old_bposG, *new_bposG ; MOVEBOXPTR old_apos0G, new_apos0G, old_bpos0G, new_bpos0G ; usite routines use these globals - used arguments are commented. */ /* define the cell moves */ #define NUMSELECT 16 /* the cell move general categories */ #define CELL_MOVE 1 #define ROTATION_MOVE 2 #define ASPECT_MOVE 3 #define PIN_MOVE 4 #define INSTANCE_MOVE 5 #define GROUP_MOVE 6 #define NUMBER_MOVE_TYPES 6 #define MOVE_ARRAY_SIZE NUMBER_MOVE_TYPES+1 /* the possible cell moves */ #define NULL_MOVE 0 #define SINGLE_CELL_MOVE 1 #define SINGLE_CELL_MOVE_AND_ROTATE 2 #define PAIRWISE_CELL_SWAP 3 #define PAIRWISE_CELL_SWAP_AND_ROTATION 4 #define ROTATION 5 #define ASPECT_RATIO_CHANGE 6 #define SOFT_PIN_MOVE 7 #define GROUP_CELL_MOVE 8 #define CELL_INSTANCE_CHANGE 9 #define NUMBER_MOVES 10 static INT move_cntS = 0 ; static INT acc_cntS = 0 ; static INT dumpRatioS = 1 ; /* update screen after each outerloop */ static INT dumpCountS = 0 ; /* count number of outer loops */ static DOUBLE total_costS, a_ratioS = 1.0 ; static DOUBLE desired_ratioS = 1.0 ; static BOOL controlOnS = TRUE ; static BOOL firstTimeS = TRUE ; /* for graphics control */ /* statistic collection */ static DOUBLE totalwireS ; static DOUBLE totalpenalS ; static DOUBLE num_dtimeS ; /* number of delta time samples */ static DOUBLE avg_dtimeS ; /* average random delta time */ static DOUBLE num_dfuncS ; /* number of delta wirelength samples */ static DOUBLE avg_dfuncS ; /* average random delta wirelength */ static output_move_table(); static INT TempSelectSoftS[11] = { 0, GROUP_MOVE, GROUP_MOVE, CELL_MOVE, CELL_MOVE, ASPECT_MOVE, ASPECT_MOVE, ROTATION_MOVE, PIN_MOVE, CELL_MOVE, CELL_MOVE } ; static INT TempSelectHardS[11] = { 0, GROUP_MOVE, GROUP_MOVE, CELL_MOVE, CELL_MOVE, GROUP_MOVE, CELL_MOVE, CELL_MOVE, ROTATION_MOVE, ROTATION_MOVE, ROTATION_MOVE } ; /* ***************************************************************** uloop - inner loop of simulated annealing algorithm. */ uloop( limit ) INT limit ; { CELLBOXPTR acellptr , bcellptr ; DOUBLE range , newAspect ; DOUBLE calc_core_factor(), calc_lap_factor() ; DOUBLE calc_time_factor() ; DOUBLE percentDone ; DOUBLE coin_toss ; INT a , b ; INT attempts, i ; INT move_acceptted ; INT binX , binY, bpos, numcells_in_bin ; INT xb , yb , axcenter , aycenter ; INT newaor, newbor, aorient , borient ; INT proposed_move, selection, *moveSelection ; INT lowerBound, upperBound ; INT flip[NUMBER_MOVES] ; INT att[NUMBER_MOVES] ; DOUBLE move_size[MOVE_ARRAY_SIZE] ; BOOL acc_move ; BOOL asp_move_possible ; FIXEDBOXPTR fixptr ; BOOL checkbinList() ; /* temperature control definitions */ INT m1 = 1, m2 = 1; DOUBLE dCp = 0.0; DOUBLE temp, eval_ratio() ; INT temp_timer, time_to_update ; /* keeps track of when to update T */ DOUBLE iter_time, accept_deviation, calc_acceptance_ratio() ; INT old_time, old_func ; /* keep track of previous value of penalties */ INT delta_time, delta_func ; /* delta penalties */ if( activecellsG <= 0 ){ M( WARNMSG, "uloop", "No active cells found. Aborting placement\n" ) ; cost_onlyG = TRUE ; restartG = TRUE ; return ; } flipsG = 0 ; attempts = 0 ; for( i = 1; i < NUMBER_MOVES; i++ ){ flip[i] = 0 ; att[i] = 0 ; if( i <= NUMBER_MOVE_TYPES ){ move_size[i] = 0.0 ; } } /* end for( i = 0;... */ /* number of moves before temperature update */ time_to_update = attmaxG / NUMTUPDATES ; if( time_to_update < MINTUPDATE ) { time_to_update = MINTUPDATE ; } temp_timer = 0 ; /* initialize timer */ acc_cntS = 0 ; /* initialize the counters if necessary */ if( iterationG <= 0 ){ old_time = timingpenalG ; old_func = funccostG ; } /* ----------------------------------------------------------------- DETERMINATION OF MOVE SELECTION POSSIBILITES. Determin move selection based on whether we have custom cells(hard) or undetermined cells( soft). Hard cells can't change aspect ratio or move pins around so these moves possibilities should be removed from consideration. However, if a single soft cell is present we must allow these possibilities. */ if( numsoftG > 0 || numstdcellG > 0 ){ moveSelection = TempSelectSoftS ; } else { moveSelection = TempSelectHardS ; } /* determine lowerBound based on temp */ /* skip over group moves */ if( ratioG > 0.34 ){ lowerBound = 1 ; } else if( ratioG > 0.17 ){ lowerBound = 2 ; } else { lowerBound = 3 ; } /* determine upperBound based on temp */ /* skip over group moves */ /* linearize so moves turn on slowly */ upperBound = 11 - (INT) (10.0 * ratioG) ; upperBound = (upperBound <= 10) ? upperBound : 10 ; upperBound = (upperBound >= 4) ? upperBound : 4 ; /* end move selection possibilities */ /* ----------------------------------------------------------------- BEGINNING OF ANNEALING INNER LOOP. */ while( attempts < limit ) { D( "uloop/bin", checkbinList() ; ) ; /* randomly pick cell an active cell a */ a = PICK_INT( 1, activecellsG ) ; /* initialize position records for use in overlap.c */ /* delay assignment to b record until needed */ /* see below */ acellptr = activeCellarrayG[ a ] ; /* now that we have a point to a cell record */ /* get cell number from record */ a = acellptr->cellnum ; new_apos0G->cell = old_apos0G->cell = a ; old_apos0G->orient = acellptr->orient ; axcenter = new_apos0G->xcenter = old_apos0G->xcenter = acellptr->xcenter ; aycenter = new_apos0G->ycenter = old_apos0G->ycenter = acellptr->ycenter ; MOVE_PICK: do { if( quickrouteG ){ proposed_move = PICK_INT( 1, NUMBER_MOVE_TYPES ) ; } else { /* randomly pick a number 1..number elements in moveSelection */ selection = PICK_INT( lowerBound, upperBound ) ; /* find out what the move is */ proposed_move = moveSelection[selection] ; } switch( proposed_move ){ case CELL_MOVE: if( acellptr->group ){ if( acellptr->celltype == GROUPCELLTYPE ){ /* pick new group position using */ /* exponential distribution */ pick_position(&xb,&yb,axcenter,aycenter); /* load move record with coordinates to move to */ /* first keep same orientation */ new_apos0G->xcenter = xb ; new_apos0G->ycenter = yb ; new_apos0G->orient = acellptr->orient ; /* group moves not implemented yet */ proposed_move = 0 ; break ; /* go to end of case statement */ } else { /* CELL OF A GROUP */ /* we must keep cell with group */ fixptr = acellptr->group->fixed ; /* pick new cell position using */ /* exponential distribution */ pick_neighborhood(&xb,&yb,axcenter,aycenter,fixptr) ; } } else if( fixptr = acellptr->fixed ){ /* two cases - fixed at point ii)fixed in neighborhood */ if( fixptr->fixedType == POINTFLAG ){ /* if a cell is fixed at a point, */ /* try a rotation only */ /* calculate bin for move determination */ binX = SETBINX(axcenter) ; binY = SETBINY(aycenter) ; newCellListG = binptrG[binX][binY]->cells ; proposed_move = ROTATION ; /* we are finished break out of case */ break ; } else { /* cell center is fixed in a neighborhood */ /* pick new cell position using */ /* exponential distribution */ pick_neighborhood(&xb,&yb,axcenter,aycenter,fixptr) ; } } else { /* a normal cell move */ /* pick new cell position using */ /* exponential distribution */ pick_position(&xb,&yb,axcenter,aycenter); } /* end pick cell position */ /* load move record with coordinates to move to */ /* first keep same orientation */ new_apos0G->xcenter = xb ; new_apos0G->ycenter = yb ; new_apos0G->orient = acellptr->orient ; /* calculate bin for move determination */ /* if bin is empty - single cell move */ binX = SETBINX(xb) ; binY = SETBINY(yb) ; newbptrG = binptrG[binX][binY] ; newCellListG = newbptrG->cells ; numcells_in_bin = newCellListG[0] ; /* if no cells in this bin attempt single cell move */ /* or cell a is the only cell in this bin - note 2 is */ /* first bin which holds cells */ if( numcells_in_bin == 0 || (numcells_in_bin == 1 && newCellListG[1] == a) ){ proposed_move = SINGLE_CELL_MOVE ; } else { proposed_move = PAIRWISE_CELL_SWAP ; } break ; case ROTATION_MOVE: /* calculate bin for move determination */ binX = SETBINX(axcenter) ; binY = SETBINY(aycenter) ; newCellListG = binptrG[binX][binY]->cells ; proposed_move = ROTATION ; break ; case ASPECT_MOVE: if( acellptr->softflag && acellptr->aspUB > 0.01 + acellptr->aspLB ){ proposed_move = ASPECT_RATIO_CHANGE ; } else { proposed_move = 0 ; } break ; case PIN_MOVE: /* to make pin moves more efficient, use softPinArrayG */ /* which keeps track of all softcells which have pins */ /* which can move. softPinArrayG[0] holds size of array */ if( (INT) softPinArrayG[HOWMANY] > 0 ){ proposed_move = SOFT_PIN_MOVE ; /* pick one of the soft cells */ selection = PICK_INT( 1, (INT) softPinArrayG[HOWMANY] ); /* now get cellptr */ acellptr = softPinArrayG[selection] ; } else { /* if no soft pins are available give up */ proposed_move = 0 ; } break ; case INSTANCE_MOVE: if( acellptr->instptr ){ proposed_move = CELL_INSTANCE_CHANGE ; } else { proposed_move = 0 ; } break ; case GROUP_MOVE: /* not implemented yet */ proposed_move = 0 ; break ; } /* end switch */ } while( !(proposed_move) ) ; /* *********** NOW EVALUATE THE PROPOSED MOVE ********* */ MOVE_START:switch( proposed_move ){ case SINGLE_CELL_MOVE: /* first try moving cell */ if( acc_move = usite1( /* old_apos, new_apos */ ) ) { flipsG++ ; flip[SINGLE_CELL_MOVE]++ ; acc_cntS++ ; } att[SINGLE_CELL_MOVE]++ ; if( quickrouteG ){ move_size[CELL_MOVE] += ABS(d_costG) ; } break ; case SINGLE_CELL_MOVE_AND_ROTATE: /* try a rotation of cell and move */ new_apos0G->orient = newOrient( acellptr , 4 ) ; if( new_apos0G->orient >= 0 ) { if( acc_move = usite1( /* old_apos, new_apos */ ) ) { flipsG++ ; flip[SINGLE_CELL_MOVE_AND_ROTATE]++ ; acc_cntS++ ; } att[SINGLE_CELL_MOVE_AND_ROTATE]++ ; if( quickrouteG ){ move_size[CELL_MOVE] += ABS(d_costG) ; } } break ; case PAIRWISE_CELL_SWAP: /* make sure we don't pick cell a if a exists in this bin */ do { bpos = PICK_INT( 1, newCellListG[0] ) ; b = newCellListG[bpos] ; } while ( a == b ) ; bcellptr = cellarrayG[b] ; /* now check classes */ if( acellptr->class != bcellptr->class ){ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - This is an invalid move but don't want to count as a move. Because break won't get us out of loop we need to use goto. Try another type of move for this cell. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ goto MOVE_PICK ; } new_bpos0G->cell = old_bpos0G->cell = b ; old_bpos0G->xcenter = bcellptr->xcenter ; old_bpos0G->ycenter = bcellptr->ycenter ; old_bpos0G->orient = new_bpos0G->orient = bcellptr->orient ; new_apos0G->xcenter = bcellptr->xcenter ; new_apos0G->ycenter = bcellptr->ycenter ; new_bpos0G->xcenter = acellptr->xcenter ; new_bpos0G->ycenter = acellptr->ycenter ; /* first try exchanging a and b positions */ if( acc_move = usite2( /*old_apos,new_apos,old_bpos,new_bpos*/ )) { acc_cntS++ ; flipsG++ ; flip[PAIRWISE_CELL_SWAP]++ ; } att[PAIRWISE_CELL_SWAP]++ ; if( quickrouteG ){ move_size[CELL_MOVE] += ABS(d_costG) ; } break ; case PAIRWISE_CELL_SWAP_AND_ROTATION: /* try again with opposite orientation types. Remember old orientation in case of neworient failure. */ aorient = acellptr->orient ; borient = bcellptr->orient ; newaor = new_apos0G->orient = newOrient( acellptr , 4 ) ; newbor = new_bpos0G->orient = newOrient( bcellptr , 4 ) ; if( newaor >= 0 || newbor >= 0 ) { if( newaor < 0 ) { new_apos0G->orient = aorient ; } else if( newbor < 0 ) { new_bpos0G->orient = borient ; } /* try rotation and move of both cells */ /* make sure new_apos is correct not changed by */ /* previous call of usite2 */ new_apos0G->xcenter = bcellptr->xcenter ; new_apos0G->ycenter = bcellptr->ycenter ; new_bpos0G->xcenter = acellptr->xcenter ; new_bpos0G->ycenter = acellptr->ycenter ; if( acc_move = usite2( /* old_apos, new_apos, old_bpos, new_bpos */ )){ acc_cntS++ ; flipsG++ ; flip[PAIRWISE_CELL_SWAP_AND_ROTATION]++ ; } att[PAIRWISE_CELL_SWAP_AND_ROTATION]++ ; if( quickrouteG ){ move_size[CELL_MOVE] += ABS(d_costG) ; } } /* end pairwise_cell_swap_and rotation */ break ; case ROTATION: /* try rotation of cell only */ /* set coordinates back to original place */ new_apos0G->xcenter = acellptr->xcenter ; new_apos0G->ycenter = acellptr->ycenter ; /* calculate bin for move determination */ binX = SETBINX(axcenter) ; binY = SETBINY(aycenter) ; newCellListG = binptrG[binX][binY]->cells ; new_apos0G->orient = newOrient( acellptr , 8 ) ; if( new_apos0G->orient >= 0 ) { /* set coordinates back to original place */ if( acc_move = usite1( /* old_apos, new_apos */ ) ) { flipsG++ ; acc_cntS++ ; flip[ROTATION]++ ; } att[ROTATION]++ ; if( quickrouteG ){ move_size[ROTATION_MOVE] += ABS(d_costG) ; } } break ; case ASPECT_RATIO_CHANGE: /* * The goal here is to generate a new * aspect ratio for the cell. */ range = acellptr->aspUB - acellptr->aspLB; newAspect = range * ((DOUBLE)RAND / (DOUBLE) 0x7fffffff) + acellptr->aspLB ; /* insure cell center and orientation is correct */ new_apos0G->orient = acellptr->orient ; new_apos0G->xcenter = acellptr->xcenter ; new_apos0G->ycenter = acellptr->ycenter ; /* need to make sure we count right number of tiles */ /* see overlap.c - calc_wBins for details */ new_apos0G->numtiles = acellptr->numtiles ; if( acc_move = uaspect( a , newAspect ) ) { flipsG++ ; acc_cntS++ ; flip[ASPECT_RATIO_CHANGE]++ ; } att[ASPECT_RATIO_CHANGE]++ ; if( quickrouteG ){ move_size[ASPECT_MOVE] += ABS(d_costG) ; } break ; case SOFT_PIN_MOVE: if( upinswap( acellptr->cellnum ) ){ flipsG++ ; flip[SOFT_PIN_MOVE]++ ; acc_cntS++ ; if( d_costG == 0 ){ /* there are two many of these moves make them */ /* track with acceptance rate */ coin_toss = ROLL_THE_DICE() ; if( coin_toss > desired_ratioS ){ /* make this a reject instead */ acc_cntS-- ; flip[SOFT_PIN_MOVE]-- ; flipsG-- ; } } } att[SOFT_PIN_MOVE]++ ; if( quickrouteG ){ move_size[PIN_MOVE] += ABS(d_costG) ; } break ; case GROUP_CELL_MOVE: /* to be implemented */ break ; case CELL_INSTANCE_CHANGE: new_apos0G->orient = acellptr->orient ; new_apos0G->xcenter = acellptr->xcenter ; new_apos0G->ycenter = acellptr->ycenter ; D( "twmc/instance", checkcost() ) ; if( acc_move = uinst( /* old_apos, new_apos */) ) { flipsG++ ; flip[CELL_INSTANCE_CHANGE]++ ; acc_cntS++ ; } att[CELL_INSTANCE_CHANGE]++ ; if( quickrouteG ){ move_size[INSTANCE_MOVE] += ABS(d_costG) ; } D( "twmc/instance", checkcost() ) ; break ; } /* end switch */ /* *********** END OF PROPOSED MOVE EVALUATION ********* */ attempts++ ; /* see if user has requested an interuption for graphics */ if( doGraphicsG && iterationG >= -1 ){ /* at iteration = -1 we wait for user to continue if requested */ if( iterationG == -1 && wait_for_userG && firstTimeS ){ G( TWmessage( "TimberWolfMC waiting for your response" ) ) ; G( process_graphics() ) ; firstTimeS = FALSE ; /* otherwise see if user has interupted program */ /* G( ) is NOGRAPHICS conditional compile */ } else G( if( TWinterupt() ) ){ G( process_graphics() ) ; } } /* ----------------------------------------------------------- Update annealing schedule */ /* if debug on check cost after each move */ D( "uloop/incr.", checkcost() ); D( "uloop/every_move", static BOOL debugVarL = FALSE ; if( debugVarL ){ G( process_graphics() ) ; } else { G( draw_the_data() ) ; } ) ; if (iterationG <= 0 ) { /* statistic collection for overlap and pinFactor determination */ avg_funcG = (avg_funcG * avgsG + funccostG) / (avgsG + 1.0) ; avgsG += 1.0 ; totalwireS += (DOUBLE) funccostG ; totalpenalS += (DOUBLE) penaltyG ; delta_time = ABS( old_time - timingpenalG ) ; if( delta_time != 0 ){ /* calculate a running average of the delta timing penalty */ num_dtimeS += 1.0 ; avg_dtimeS = (avg_dtimeS * (num_dtimeS - 1.0) + (DOUBLE) delta_time) / num_dtimeS ; /* calculate a running average of the delta wiring penalty */ delta_func = ABS( old_func - funccostG ) ; num_dfuncS += 1.0 ; avg_dfuncS = (avg_dfuncS * (num_dfuncS - 1.0) + (DOUBLE) delta_func) / num_dfuncS ; } /* now update the old values of the timing and wirelength */ old_time = timingpenalG ; old_func = funccostG ; if (iterationG != 0.0 ){ /* stay at a high temperature */ continue; } /* lower temperature to starting point from infinite temp. */ /* do this to get starting temperature correct */ if (d_costG >= 0){ /*** d_cost is the -ve of the actual d_cost ***/ m1 ++; } else { dCp -= d_costG; m2 ++; } temp = (init_accG * attempts - m1) / m2; if (temp <= 0.0) { TG *= 0.9; } else { TG = -dCp / (m2 * log(temp)); } continue; /*** initialization phase. JL **/ } /* ----------------------------------------------------------------- Update temperature using negative feedback to control the acceptance ratio in accordance to curve fit schedule. Calc_acceptance_ratio returns desired acceptance ratio give the iteration. The damped error term (deviation) is then applied to correct the temperature T. Update_window_size controls the range limiter. We avoid updating T during initialization, we use exact schedule to compute starting T. The temp_timer allows us to update temperature inside the inner loop of the annealing algorithm. We use counter to avoid use of mod function for speed. We can either pick from incremental a_ratio or cummulative ratio. ------------------------------------------------------------------ */ if( ++temp_timer >= time_to_update || attempts >= attmaxG ) { a_ratioS = (DOUBLE) acc_cntS / (DOUBLE) temp_timer;/*incremental*/ temp_timer = 0 ; /* reset counter */ acc_cntS = 0; /* reset incremental timer */ iter_time = (DOUBLE) iterationG + (DOUBLE) attempts / (DOUBLE) attmaxG ; /* maintain desired ratio from iteration to iteration */ desired_ratioS = calc_acceptance_ratio( iter_time ) ; accept_deviation = desired_ratioS - a_ratioS ; #ifdef NEEDED Yplot_heading( 0, "graph_T", "iter","pre_def","post_dev", "run_avg","calc_dev", "meas_dev","T", NULL ) ; Yplot( 0, "graph_T", "%d", iterationG, "%4.2le", accept_deviation ) ; Yplot( 0, "graph_T", "%d", iterationG, "%4.4le %4.4le %4.4le %4.4le %4.4le", accept_deviation, running_avg, calc_acceptance_ratio(iter_time), a_ratioS, TG ); Yplot_flush( "graph_T" ) ; #endif if( iterationG <= (INT) HIGHTEMP ) { /* no change to damping factor */ } else if( iterationG <= (INT) TURNOFFT ) { accept_deviation *= ACCEPTDAMPFACTOR ; } else { accept_deviation *= ACCEPTDAMPFACTOR2 ; } TG *= 1.0 + accept_deviation ; TG = MAX( TG, TMIN ) ; /* to avoid floating point errors */ update_window_size( iter_time ) ; } /* End of annealing schedule update ----------------------------------------------------------- */ /* ******************************************************* Now if moves were rejected and they were single cell or pairwise cell moves, try the same moves but with rotations. We think it makes sense to try another move with rotation if the move without rotation failed. Goto takes us not to beginning of loop but to top of move selection switch. We need to fall to bottom of loop so that the statistics are updated. ******************************************************** */ if( !(acc_move) ){ /* move wasn't accepted */ switch( proposed_move ){ case SINGLE_CELL_MOVE: proposed_move = SINGLE_CELL_MOVE_AND_ROTATE ; goto MOVE_START ; case SINGLE_CELL_MOVE_AND_ROTATE: /* - - - - - - - - - - - - - - - - - - - - - - - - - - If we fail rotation and move, propose to try either aspect ratio change or/and instance change depending on what moves are allowed. If both are allowed roll the dice. - - - - - - - - - - - - - - - - - - - - - - - - - - - */ if( acellptr->softflag && acellptr->aspUB > 0.01 + acellptr->aspLB ){ asp_move_possible = TRUE ; } else { asp_move_possible = FALSE ; } if( asp_move_possible && acellptr->instptr ){ /* roll the dice */ if( PICK_INT( 0, 1 ) ){ proposed_move = ASPECT_RATIO_CHANGE ; } else { proposed_move = CELL_INSTANCE_CHANGE ; } goto MOVE_START ; } else if( acellptr->instptr ){ proposed_move = CELL_INSTANCE_CHANGE ; goto MOVE_START ; } else if( asp_move_possible){ proposed_move = ASPECT_RATIO_CHANGE ; goto MOVE_START ; } else { /* done sequence */ break ; } case PAIRWISE_CELL_SWAP: proposed_move = PAIRWISE_CELL_SWAP_AND_ROTATION ; goto MOVE_START ; case PAIRWISE_CELL_SWAP_AND_ROTATION: /* done sequence */ break ; case ROTATION: /* done sequence */ break ; case ASPECT_RATIO_CHANGE: /* if we fail aspect ratio change propose pin change */ if( acellptr->numpins > 0 ){ /* end of sequence try only one so we don't due */ /* too much work at high T. */ /* proposed_move = SOFT_PIN_MOVE ; */ proposed_move = 0 ; goto MOVE_START ; } else { /* done sequence */ break ; } case SOFT_PIN_MOVE: /* done sequence */ break ; case GROUP_CELL_MOVE: /* done sequence */ break ; case CELL_INSTANCE_CHANGE: /* done sequence */ break ; } /* end switch */ } } /* ****** END OF ANNEALING INNER LOOP **************** */ /* verify incremental and current costs after each iteration */ D( "uloop", checkcost() ) ; if( !(++dumpCountS % dumpRatioS) ){ G( setGraphicWindow() ) ; G( draw_the_data() ) ; } /* ----------------------------------------------------------------- Use negative feedback to control relative ratio between penalties */ /* first get percentage of the task we have completed - temp */ percentDone = eval_ratio( iterationG ) ; if( percentDone >= FINISHED ){ /* turn off controller when percent done is 1.0 */ /* controlOn is initialize to TRUE and once turned off cannot */ /* get turned back on */ /* controlOnS = FALSE ; */ } if( controlOnS ){ /* **** core area controller **** */ coreFactorG = calc_core_factor( percentDone ) ; /* **** overlap penalty controller **** */ lapFactorG = calc_lap_factor( percentDone ) ; /* **** timing penalty controller **** */ timeFactorG = calc_time_factor( percentDone ) ; } /* end negative feedback controller code */ /* reset penalties */ penaltyG = (INT) (lapFactorG * sqrt( (DOUBLE) binpenalG ) ) ; timingcostG = (INT) (timeFactorG * (DOUBLE) timingpenalG ) ; total_costS = (DOUBLE) (funccostG + penaltyG + timingcostG ) ; ratioG = ( (DOUBLE) flipsG / (DOUBLE) attempts ) ; FLUSHOUT() ; if( quickrouteG ){ output_move_table( flip, att, move_size ) ; } /* ----------------------------------------------------------------- now output statistics for this temperature. */ OUT1("\nI T funccost binpen x lapFact = penalty cost coreFactor\n"); OUT2("%3d ",iterationG ); OUT2("%4.2le ",TG ); OUT2("%4.2le ",(DOUBLE) funccostG ); OUT2("%4.2le ",(DOUBLE) binpenalG ); OUT2("%4.2le ",lapFactorG ); OUT2("%4.2le ",(DOUBLE) penaltyG ); OUT2("%4.2le ",total_costS ); OUT2("%4.2le\n",coreFactorG ); OUT1("timeFactor timepenal timecost var perDone\n"); OUT2("%4.2le ",(DOUBLE) timeFactorG ); OUT2("%4.2le ",(DOUBLE) timingpenalG ); OUT2("%4.2le ",(DOUBLE) timingcostG ); OUT2("%4.2le\n ",percentDone ); OUT1(" flip1 flipo flip0 flipp flipa flip2 flipo2 flipi flips ratio\n"); OUT3("%3d/%3d ",flip[SINGLE_CELL_MOVE],att[SINGLE_CELL_MOVE] ); OUT3("%3d/%3d ",flip[SINGLE_CELL_MOVE_AND_ROTATE], att[SINGLE_CELL_MOVE_AND_ROTATE] ); OUT3("%3d/%3d ",flip[ROTATION],att[ROTATION] ); OUT3("%3d/%3d ",flip[SOFT_PIN_MOVE],att[SOFT_PIN_MOVE] ); OUT3("%3d/%3d ",flip[ASPECT_RATIO_CHANGE],att[ASPECT_RATIO_CHANGE] ); OUT3("%3d/%3d ",flip[PAIRWISE_CELL_SWAP],att[PAIRWISE_CELL_SWAP] ); OUT3("%3d/%3d ",flip[PAIRWISE_CELL_SWAP_AND_ROTATION], att[PAIRWISE_CELL_SWAP_AND_ROTATION] ); OUT3("%3d/%3d ",flip[CELL_INSTANCE_CHANGE],att[CELL_INSTANCE_CHANGE] ); OUT3(" %3d/%3d ",flipsG,attempts ); OUT2(" %4.2f\n\n",ratioG ); FLUSHOUT() ; /* GRAPH( graphFileName, xVarformat, xVar, yVarformat, yVars... ) */ Yplot_heading( 0, "graph", "iter","funccost","binpenal", "percentDone","lapFactor","coreFactor", "ratio", "T", "totalcost", NULL ) ; Yplot( 0, "graph", "%d", iterationG, "%d %d %d %4.2le %4.2le %4.2le %4.2le %4.2le %4.2le", funccostG,binpenalG,percentDone,lapFactorG, coreFactorG, ratioG, TG, total_costS ) ; Yplot_flush( "graph" ) ; return ; } /* end uloop */ /* ***************************************************************** */ /* initializes random wiring and overlap statistics */ initStatCollection() { avgsG = 0.0 ; avg_funcG = 0.0 ; totalwireS = 0.0 ; totalpenalS = 0.0 ; avg_dtimeS = 0.0 ; num_dtimeS = 0.0 ; avg_dfuncS = 0.0 ; num_dfuncS = 0.0 ; ratioG = 1.0 ; } /* end initStatCollection */ /* ***************************************************************** */ getStatistics( totalWire, totalPenalty, avg_time, avg_func ) DOUBLE *totalWire, *totalPenalty, *avg_time, *avg_func ; { *totalWire = totalwireS ; *totalPenalty = totalpenalS ; *avg_time = avg_dtimeS ; *avg_func = avg_dfuncS ; } /* end getStatistics */ /* ***************************************************************** make_movebox - ALLOCATE MEMORY FOR MOVE RECORDS move boxes - old_aposG[0] holds info for old cell ie orient cell old_aposG[1..n] holds tile information for old cell. new_aposG[1..n] holds tile information for new cell. softcells only use old_aposG[1] and new_aposG[1] since they can have only one tile. */ make_movebox() { INT i ; INT maxtiles ; maxtiles = get_tile_count() ; /* allocate four arrays of moveboxs */ old_aposG = (MOVEBOXPTR *) Ysafe_malloc( maxtiles * sizeof(MOVEBOXPTR) ); for( i = 0; i< maxtiles ; i++ ){ old_aposG[i] = (MOVEBOXPTR) Ysafe_malloc( sizeof(MOVEBOX) ) ; old_aposG[i]->loaded_previously = FALSE ; } old_apos0G = old_aposG[0] ; new_aposG = (MOVEBOXPTR *) Ysafe_malloc( maxtiles * sizeof(MOVEBOXPTR) ); for( i = 0; i< maxtiles ; i++ ){ new_aposG[i] = (MOVEBOXPTR) Ysafe_malloc( sizeof(MOVEBOX) ) ; new_aposG[i]->loaded_previously = FALSE ; } new_apos0G = new_aposG[0] ; old_bposG = (MOVEBOXPTR *) Ysafe_malloc( maxtiles * sizeof(MOVEBOXPTR) ); for( i = 0; i< maxtiles ; i++ ){ old_bposG[i] = (MOVEBOXPTR) Ysafe_malloc( sizeof(MOVEBOX) ) ; old_bposG[i]->loaded_previously = FALSE ; } old_bpos0G = old_bposG[0] ; new_bposG = (MOVEBOXPTR *) Ysafe_malloc( maxtiles * sizeof(MOVEBOXPTR) ); for( i = 0; i< maxtiles ; i++ ){ new_bposG[i] = (MOVEBOXPTR) Ysafe_malloc( sizeof(MOVEBOX) ) ; new_bposG[i]->loaded_previously = FALSE ; } new_bpos0G = new_bposG[0] ; } /* end function make_movebox */ /* ***************************************************************** save_uloop - save uloop parameters for restart */ save_uloop( fp ) FILE *fp ; { fprintf(fp,"# uloop parameters:\n") ; fprintf(fp,"%d %d %d\n",iterationG,acc_cntS,move_cntS); fprintf(fp,"%f %f\n",a_ratioS,total_costS); } /* end save_uloop */ /* ***************************************************************** read_uloop - read uloop parameters for restart */ INT read_uloop( fp ) FILE *fp ; { INT error = 0 ; fscanf(fp,"%[ #:a-zA-Z]\n",YmsgG ); /* throw away comment */ fscanf(fp,"%ld %ld %ld\n",&iterationG,&acc_cntS,&move_cntS); fscanf(fp,"%lf %lf\n",&a_ratioS,&total_costS); /* try to detect errors in file */ if( acc_cntS < 0 ){ M(ERRMSG,"read_uloop","Restart file: acc_cntS negative\n") ; error++ ; } if( move_cntS < 0 ){ M(ERRMSG,"read_uloop","Restart file: move_cnt negative\n") ; error++ ; } if( a_ratioS < 0.0 ){ M(ERRMSG,"read_uloop","Restart file: a_ratio negative\n") ; error++ ; } if( a_ratioS > 1.0 ){ M(ERRMSG,"read_uloop","Restart file: a_ratio >1\n") ; error++ ; } if( iterationG < 1 ){ M(ERRMSG,"read_uloop","Restart file: iteration count <1\n") ; error++ ; /* one error */ } return(error) ; } /* end read_uloop */ set_dump_ratio( count ) { dumpRatioS = count ; } /* end dump_ratio */ static output_move_table( flip, att, move_size ) INT *flip, *att ; DOUBLE *move_size ; { INT i ; INT a[MOVE_ARRAY_SIZE] ; /* attempts for the individual moves */ INT f[MOVE_ARRAY_SIZE] ; /* flips for the individual moves */ FILE *fp ; DOUBLE Qm[MOVE_ARRAY_SIZE] ; DOUBLE P[MOVE_ARRAY_SIZE] ; DOUBLE Qsum ; char filename[LRECL] ; sprintf( filename, "%s.mset", cktNameG ) ; fp = TWOPEN( filename, "a", ABORT ) ; fprintf( fp, "I:%d ", iterationG ) ; /* first calculate f (flip) and a (attempts) from indivial vectors */ f[CELL_MOVE] = flip[SINGLE_CELL_MOVE] + flip[SINGLE_CELL_MOVE_AND_ROTATE] + flip[PAIRWISE_CELL_SWAP_AND_ROTATION] + flip[PAIRWISE_CELL_SWAP] ; a[CELL_MOVE] = att[SINGLE_CELL_MOVE] + att[SINGLE_CELL_MOVE_AND_ROTATE] + att[PAIRWISE_CELL_SWAP] + att[PAIRWISE_CELL_SWAP_AND_ROTATION] ; f[ROTATION_MOVE] = flip[ROTATION] ; a[ROTATION_MOVE] = att[ROTATION] ; f[ASPECT_MOVE] = flip[ASPECT_RATIO_CHANGE] ; a[ASPECT_MOVE] = att[ASPECT_RATIO_CHANGE] ; f[PIN_MOVE] = flip[SOFT_PIN_MOVE] ; a[PIN_MOVE] = att[SOFT_PIN_MOVE] ; f[GROUP_MOVE] = flip[GROUP_CELL_MOVE] ; a[GROUP_MOVE] = att[GROUP_CELL_MOVE] ; f[INSTANCE_MOVE] = flip[CELL_INSTANCE_CHANGE] ; a[INSTANCE_MOVE] = att[CELL_INSTANCE_CHANGE] ; for( i = 1; i <= NUMBER_MOVE_TYPES; i++ ){ /* only output moves that were attempted */ fprintf( fp, "%d:%d/%d %4.2le ", i, f[i], a[i], move_size[i] ) ; } fprintf( fp, "\n" ) ; /* ************************************************************** Calculate the percentages Qm = #accepted_moves * average_move_size --------------------------------------- # attempted_moves (for this move type) where average_move_size is move_size[i] / a[i]. ***************************************************************** */ Qsum = 0.0 ; for( i = 1; i <= NUMBER_MOVE_TYPES; i++ ){ if( a[i] ){ Qm[i] = f[i] * move_size[i] / (DOUBLE) a[i] / (DOUBLE) a[i] ; } else { Qm[i] = 0.0 ; } Qsum += Qm[i] ; } /* end for( i = 1;... */ for( i = 1; i <= NUMBER_MOVE_TYPES; i++ ){ P[i] = Qm[i]/Qsum ; fprintf( fp, "Qm[%d]=%4.2le P[%d]=%4.2le ", i, Qm[i], i, Qm[i]/Qsum ) ; } /* end for( i = 1;... */ fprintf( fp, "\n" ) ; /* PLOT THE RESULTS TO SEE TRENDS */ Yplot_heading( 0, "graph_prob", "iter","P[1]","P[2]","P[3]", "P[4]", "P[5]", "P[6]", NULL ) ; for( i = 1; i <= NUMBER_MOVE_TYPES; i++ ){ Yplot( 0, "graph_prob", "%d", iterationG, "%4.2le", P[i] ) ; } Yplot_flush( "graph_prob" ) ; TWCLOSE( fp ) ; } /* end output_move_table */ graywolf-0.1.4+20170307gite1bf319/src/twmc/uloop.new000077500000000000000000001026211305746555600214030ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: uloop.c DESCRIPTION:inner loop of the simulated annealing algorithm. CONTENTS: uloop( limit ) INT limit ; make_movebox() ; save_uloop( fp ) FILE *fp ; INT read_uloop( fp ) FILE *fp ; DATE: Feb 5, 1988 REVISIONS: July 21, 1988 - reversed order of softpin and aspect ratio moves to work with controller. Sept 12, 1988 - rewrote cell move generation strategy. Sept 24, 1988 - added testloop code that is added initStatCollection and getStatistics ; Oct 20, 1988 - turn off bin controller when percentDone = 1.0 Oct 27, 1988 - handle 3 of 4 fixed cases. Modified controller Now use only active cells in choice of cell. Nov 14, 1988 - changed output format for easier reading. Nov 25, 1988 - changed sequence of aspect ratio changes. - modified negative feedback for better control. Dec 3, 1988 - added timing driven code. Dec 6, 1988 - fixed a bug in updating penalty. Jan 15, 1988 - added curve fit controller, changed overfill negative feedback control, and fixed GRAPHHEADING for new CRICKETGRAPH program. Jan 25, 1989 - added softPinArrayG to make soft pin moves more efficient. Cleaned up move selection strategy. Changed msg to YmsgG. Softpin moves are used during partitioning but overfill is not used. Removed extraneous call to placepads. Feb 25, 1989 - changed cell selection to get more cell moves at lower temperatures. Made percentDone a static variable so it could be used in calc_new_core which was added so that the same code could be called at any time to change the aspect ratio. Also added X11 graphics calls. Fixed problem with negative iterations Feb 26, 1989 - added wait for user feature. Feb 28, 1989 - updated schedule constants. Mar 02, 1989 - moved schedule constants to temp.h for consistency. Removed extraneous variables. Removed iter_count from call-now global. Moved negative feedback code to penalties.c. Mar 11, 1989 - added graphics conditional compile and always leave controller on. Mar 14, 1989 - began instance coding. Apr 20, 1989 - added partition coding. May 1, 1989 - fixed problem with cell in different classes trying to be swapped. Now we try another move correctly. May 18, 1989 - update forceGrid. May 24, 1989 - moved forceGrid to prboard. Jun 21, 1989 - fixed problem with move_box initialization. Sep 25, 1989 - made move box structure dynamic with respect to number of tiles. Apr 23, 1990 - now correctly handle the timing constant thru the use of delta change in timing cost. May 15, 1990 - fixed problem with standard cell macros. Sun Jan 20 21:34:36 PST 1991 - ported to AIX. Mon Feb 4 02:23:33 EST 1991 - added MINTUPDATE def. Sun May 5 14:59:39 EDT 1991 - now all moves influence temperature scheduler. Wed Jun 5 16:31:51 CDT 1991 - fixed problem with controller initialization ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "%Z% %M% version %I% %G%" ; #endif #include #include #include #include #define TMIN 1E-6 #define HOWMANY 0 #define pick_pos( a, b, c, d ) ( (*which_pickS)(a,b,c,d) ) extern INT pick_position() ; static INT (*which_pickS)() = pick_position ;/* which new position func */ /* ----------------------------------------------------------------- important global definitions - defined in custom.h MOVEBOXPTR *old_aposG, *new_aposG, *old_bposG, *new_bposG ; MOVEBOXPTR old_apos0G, new_apos0G, old_bpos0G, new_bpos0G ; usite routines use these globals - used arguments are commented. */ #define NUMBER_MOVES 10 /* define the cell moves */ #define NUMSELECT 16 /* the cell move general categories */ #define CELL_MOVE 1 #define ROTATION_MOVE 2 #define ASPECT_MOVE 3 #define PIN_MOVE 4 #define GROUP_MOVE 5 /* the possible cell moves */ #define NULL_MOVE 0 #define SINGLE_CELL_MOVE 1 #define SINGLE_CELL_MOVE_AND_ROTATE 2 #define PAIRWISE_CELL_SWAP 3 #define PAIRWISE_CELL_SWAP_AND_ROTATION 4 #define ROTATION 5 #define ASPECT_RATIO_CHANGE 6 #define SOFT_PIN_MOVE 7 #define GROUP_CELL_MOVE 8 #define CELL_INSTANCE_CHANGE 9 static INT move_cntS = 0 ; static INT acc_cntS = 0 ; static INT dumpRatioS = 1 ; /* update screen after each outerloop */ static INT dumpCountS = 0 ; /* count number of outer loops */ static DOUBLE total_costS, a_ratioS = 1.0 ; static DOUBLE TratioS = 0.0 ; static BOOL controlOnS = TRUE ; static BOOL firstTimeS = TRUE ; /* for graphics control */ /* statistic collection */ static DOUBLE totalwireS ; static DOUBLE totalpenalS ; static DOUBLE num_dtimeS ; /* number of delta time samples */ static DOUBLE avg_dtimeS ; /* average random delta time */ static DOUBLE num_dfuncS ; /* number of delta wirelength samples */ static DOUBLE avg_dfuncS ; /* average random delta wirelength */ static INT TempSelectSoftS[11] = { NULL, GROUP_MOVE, GROUP_MOVE, CELL_MOVE, CELL_MOVE, ASPECT_MOVE, ASPECT_MOVE, ROTATION_MOVE, PIN_MOVE, CELL_MOVE, CELL_MOVE } ; static INT TempSelectHardS[11] = { NULL, GROUP_MOVE, GROUP_MOVE, CELL_MOVE, CELL_MOVE, GROUP_MOVE, CELL_MOVE, CELL_MOVE, ROTATION_MOVE, ROTATION_MOVE, ROTATION_MOVE } ; /* ***************************************************************** uloop - inner loop of simulated annealing algorithm. */ uloop( limit ) INT limit ; { CELLBOXPTR acellptr , bcellptr ; DOUBLE range , newAspect ; DOUBLE calc_core_factor(), calc_lap_factor() ; DOUBLE calc_time_factor() ; DOUBLE percentDone ; INT a , b ; INT attempts, i ; INT move_acceptted ; INT binX , binY, bpos, numcells_in_bin ; INT xb , yb , axcenter , aycenter ; INT newaor, newbor, aorient , borient ; INT proposed_move, selection, *moveSelection ; INT lowerBound, upperBound ; BOOL checkbinList() ; BOOL acc_move ; BOOL asp_move_possible ; FIXEDBOXPTR fixptr ; INT flip[NUMBER_MOVES+1] ; INT att[NUMBER_MOVES+1] ; DOUBLE move_size[NUMBER_MOVES+1] ; /* temperature control definitions */ INT m1 = 1, m2 = 1; DOUBLE dCp = 0.0; DOUBLE temp, eval_ratio() ; INT temp_timer, time_to_update ; /* keeps track of when to update T */ DOUBLE iter_time, accept_deviation, calc_acceptance_ratio() ; INT old_time, old_func ; /* keep track of previous value of penalties */ INT delta_time, delta_func ; /* delta penalties */ if( activecellsG <= 0 ){ M( WARNMSG, "uloop", "No active cells found. Aborting placement\n" ) ; cost_onlyG = TRUE ; restartG = TRUE ; return ; } attempts = 0 ; flipsG = 0 ; for( i = 0; i <= NUMBER_MOVES; i++ ){ flip[i] = 0 ; att[i] = 0 ; move_size[i] = 0.0 ; } /* number of moves before temperature update */ time_to_update = attmaxG / NUMTUPDATES ; if( time_to_update < MINTUPDATE ) { time_to_update = MINTUPDATE ; } temp_timer = 0 ; /* initialize timer */ acc_cntS = 0 ; /* initialize the counters if necessary */ if( iterationG <= 0 ){ old_time = timingpenalG ; old_func = funccostG ; } /* ----------------------------------------------------------------- DETERMINATION OF MOVE SELECTION POSSIBILITES. Determin move selection based on whether we have custom cells(hard) or undetermined cells( soft). Hard cells can't change aspect ratio or move pins around so these moves possibilities should be removed from consideration. However, if a single soft cell is present we must allow these possibilities. */ if( numsoftG > 0 || numstdcellG > 0 ){ moveSelection = TempSelectSoftS ; } else { moveSelection = TempSelectHardS ; } /* determine lowerBound based on temp */ /* skip over group moves */ if( ratioG > 0.34 ){ lowerBound = 1 ; } else if( ratioG > 0.17 ){ lowerBound = 2 ; } else { lowerBound = 3 ; } /* determine upperBound based on temp */ /* skip over group moves */ /* linearize so moves turn on slowly */ upperBound = 11 - (INT) (10.0 * ratioG) ; upperBound = (upperBound <= 10) ? upperBound : 10 ; upperBound = (upperBound >= 4) ? upperBound : 4 ; /* end move selection possibilities */ /* ----------------------------------------------------------------- BEGINNING OF ANNEALING INNER LOOP. */ while( attempts < limit ) { D( "uloop/bin", checkbinList() ; ) ; /* randomly pick cell an active cell a */ a = PICK_INT( 1, activecellsG ) ; /* initialize position records for use in overlap.c */ /* delay assignment to b record until needed */ /* see below */ acellptr = activeCellarrayG[ a ] ; /* now that we have a point to a cell record */ /* get cell number from record */ a = acellptr->cellnum ; new_apos0G->cell = old_apos0G->cell = a ; old_apos0G->orient = acellptr->orient ; axcenter = new_apos0G->xcenter = old_apos0G->xcenter = acellptr->xcenter ; aycenter = new_apos0G->ycenter = old_apos0G->ycenter = acellptr->ycenter ; MOVE_PICK: do { if( quickrouteG ){ proposed_move = PICK_INT( 1, 5 ) ; } else { /* randomly pick a number 1..number elements in moveSelection */ selection = PICK_INT( lowerBound, upperBound ) ; /* find out what the move is */ proposed_move = moveSelection[selection] ; } switch( proposed_move ){ case CELL_MOVE: if( acellptr->group ){ if( acellptr->celltype == GROUPCELLTYPE ){ /* pick new group position using */ /* exponential distribution */ pick_position(&xb,&yb,axcenter,aycenter); /* load move record with coordinates to move to */ /* first keep same orientation */ new_apos0G->xcenter = xb ; new_apos0G->ycenter = yb ; new_apos0G->orient = acellptr->orient ; /* group moves not implemented yet */ proposed_move = NULL ; break ; /* go to end of case statement */ } else { /* CELL OF A GROUP */ /* we must keep cell with group */ fixptr = acellptr->group->fixed ; /* pick new cell position using */ /* exponential distribution */ pick_neighborhood(&xb,&yb,axcenter,aycenter,fixptr) ; } } else if( fixptr = acellptr->fixed ){ /* two cases - fixed at point ii)fixed in neighborhood */ if( fixptr->fixedType == POINTFLAG ){ /* if a cell is fixed at a point, */ /* try a rotation only */ /* calculate bin for move determination */ binX = SETBINX(axcenter) ; binY = SETBINY(aycenter) ; newCellListG = binptrG[binX][binY]->cells ; proposed_move = ROTATION ; /* we are finished break out of case */ break ; } else { /* cell center is fixed in a neighborhood */ /* pick new cell position using */ /* exponential distribution */ pick_neighborhood(&xb,&yb,axcenter,aycenter,fixptr) ; } } else { /* a normal cell move */ /* pick new cell position using */ /* exponential distribution */ pick_pos(&xb,&yb,axcenter,aycenter); } /* end pick cell position */ /* load move record with coordinates to move to */ /* first keep same orientation */ new_apos0G->xcenter = xb ; new_apos0G->ycenter = yb ; new_apos0G->orient = acellptr->orient ; /* calculate bin for move determination */ /* if bin is empty - single cell move */ binX = SETBINX(xb) ; binY = SETBINY(yb) ; newbptrG = binptrG[binX][binY] ; newCellListG = newbptrG->cells ; numcells_in_bin = newCellListG[0] ; /* if no cells in this bin attempt single cell move */ /* or cell a is the only cell in this bin - note 2 is */ /* first bin which holds cells */ if( numcells_in_bin == 0 || (numcells_in_bin == 1 && newCellListG[1] == a) ){ proposed_move = SINGLE_CELL_MOVE ; } else { proposed_move = PAIRWISE_CELL_SWAP ; } break ; case ROTATION_MOVE: /* calculate bin for move determination */ binX = SETBINX(axcenter) ; binY = SETBINY(aycenter) ; newCellListG = binptrG[binX][binY]->cells ; proposed_move = ROTATION ; break ; case ASPECT_MOVE: /* if( acellptr->softflag && acellptr->aspUB > 0.01 + acellptr->aspLB ){ proposed_move = ASPECT_RATIO_CHANGE ; } else { proposed_move = NULL ; } */ proposed_move = NULL ; break ; case PIN_MOVE: /* to make pin moves more efficient, use softPinArrayG */ /* which keeps track of all softcells which have pins */ /* which can move. softPinArrayG[0] holds size of array */ if( (INT) softPinArrayG[HOWMANY] > 0 ){ proposed_move = SOFT_PIN_MOVE ; /* pick one of the soft cells */ selection = PICK_INT( 1, (INT) softPinArrayG[HOWMANY] ); /* now get cellptr */ acellptr = softPinArrayG[selection] ; } else { /* if no soft pins are available give up */ proposed_move = NULL ; } break ; case GROUP_MOVE: /* not implemented yet */ proposed_move = NULL ; break ; } /* end switch */ } while( !(proposed_move) ) ; /* *********** NOW EVALUATE THE PROPOSED MOVE ********* */ MOVE_START:switch( proposed_move ){ case SINGLE_CELL_MOVE: /* first try moving cell */ if( acc_move = usite1( /* old_apos, new_apos */ ) ) { flipsG++ ; flip[SINGLE_CELL_MOVE]++ ; acc_cntS++ ; if( quickrouteG ){ move_size[SINGLE_CELL_MOVE] += d_costG ; } } att[SINGLE_CELL_MOVE]++ ; break ; case SINGLE_CELL_MOVE_AND_ROTATE: /* try a rotation of cell and move */ new_apos0G->orient = newOrient( acellptr , 4 ) ; if( new_apos0G->orient >= 0 ) { if( acc_move = usite1( /* old_apos, new_apos */ ) ) { flipsG++ ; flip[SINGLE_CELL_MOVE_AND_ROTATE]++ ; acc_cntS++ ; if( quickrouteG ){ move_size[SINGLE_CELL_MOVE_AND_ROTATE] += d_costG ; } } att[SINGLE_CELL_MOVE_AND_ROTATE]++ ; } break ; case PAIRWISE_CELL_SWAP: /* make sure we don't pick cell a if a exists in this bin */ do { bpos = PICK_INT( 1, newCellListG[0] ) ; b = newCellListG[bpos] ; } while ( a == b ) ; bcellptr = cellarrayG[b] ; /* now check classes */ if( acellptr->class != bcellptr->class ){ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - This is an invalid move but don't want to count as a move. Because break won't get us out of loop we need to use goto. Try another type of move for this cell. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ goto MOVE_PICK ; } new_bpos0G->cell = old_bpos0G->cell = b ; old_bpos0G->xcenter = bcellptr->xcenter ; old_bpos0G->ycenter = bcellptr->ycenter ; old_bpos0G->orient = new_bpos0G->orient = bcellptr->orient ; new_apos0G->xcenter = bcellptr->xcenter ; new_apos0G->ycenter = bcellptr->ycenter ; new_bpos0G->xcenter = acellptr->xcenter ; new_bpos0G->ycenter = acellptr->ycenter ; /* first try exchanging a and b positions */ if( acc_move = usite2( /*old_apos,new_apos,old_bpos,new_bpos*/ )) { acc_cntS++ ; flipsG++ ; flip[PAIRWISE_CELL_SWAP]++ ; if( quickrouteG ){ move_size[PAIRWISE_CELL_SWAP] += d_costG ; } } att[PAIRWISE_CELL_SWAP]++ ; break ; case PAIRWISE_CELL_SWAP_AND_ROTATION: /* try again with opposite orientation types. Remember old orientation in case of neworient failure. */ aorient = acellptr->orient ; borient = bcellptr->orient ; newaor = new_apos0G->orient = newOrient( acellptr , 4 ) ; newbor = new_bpos0G->orient = newOrient( bcellptr , 4 ) ; if( newaor >= 0 || newbor >= 0 ) { if( newaor < 0 ) { new_apos0G->orient = aorient ; } else if( newbor < 0 ) { new_bpos0G->orient = borient ; } /* try rotation and move of both cells */ /* make sure new_apos is correct not changed by */ /* previous call of usite2 */ new_apos0G->xcenter = bcellptr->xcenter ; new_apos0G->ycenter = bcellptr->ycenter ; new_bpos0G->xcenter = acellptr->xcenter ; new_bpos0G->ycenter = acellptr->ycenter ; if( acc_move = usite2( /* old_apos, new_apos, old_bpos, new_bpos */ )){ acc_cntS++ ; flipsG++ ; flip[PAIRWISE_CELL_SWAP_AND_ROTATION]++ ; if( quickrouteG ){ move_size[PAIRWISE_CELL_SWAP_AND_ROTATION] += d_costG ; } } att[PAIRWISE_CELL_SWAP_AND_ROTATION]++ ; } /* end pairwise_cell_swap_and rotation */ break ; case ROTATION: /* try rotation of cell only */ /* set coordinates back to original place */ new_apos0G->xcenter = acellptr->xcenter ; new_apos0G->ycenter = acellptr->ycenter ; /* calculate bin for move determination */ binX = SETBINX(axcenter) ; binY = SETBINY(aycenter) ; newCellListG = binptrG[binX][binY]->cells ; new_apos0G->orient = newOrient( acellptr , 8 ) ; if( new_apos0G->orient >= 0 ) { /* set coordinates back to original place */ if( acc_move = usite1( /* old_apos, new_apos */ ) ) { flipsG++ ; acc_cntS++ ; flip[ROTATION]++ ; if( quickrouteG ){ move_size[ROTATION] += d_costG ; } } att[ROTATION]++ ; } break ; case ASPECT_RATIO_CHANGE: /* * The goal here is to generate a new * aspect ratio for the cell. */ range = acellptr->aspUB - acellptr->aspLB; newAspect = range * ((DOUBLE)RAND / (DOUBLE) 0x7fffffff) + acellptr->aspLB ; /* insure cell center and orientation is correct */ new_apos0G->orient = acellptr->orient ; new_apos0G->xcenter = acellptr->xcenter ; new_apos0G->ycenter = acellptr->ycenter ; /* need to make sure we count right number of tiles */ /* see overlap.c - calc_wBins for details */ new_apos0G->numtiles = acellptr->numtiles ; if( acc_move = uaspect( a , newAspect ) ) { flipsG++ ; acc_cntS++ ; flip[ASPECT_RATIO_CHANGE]++ ; if( quickrouteG ){ move_size[ASPECT_RATIO_CHANGE] += d_costG ; } } att[ASPECT_RATIO_CHANGE]++ ; break ; case SOFT_PIN_MOVE: if( upinswap( acellptr->cellnum ) ){ flipsG++ ; flip[SOFT_PIN_MOVE]++ ; if( quickrouteG ){ move_size[SOFT_PIN_MOVE] += d_costG ; } acc_cntS++ ; } att[SOFT_PIN_MOVE]++ ; break ; case GROUP_CELL_MOVE: /* to be implemented */ break ; case CELL_INSTANCE_CHANGE: new_apos0G->orient = acellptr->orient ; new_apos0G->xcenter = acellptr->xcenter ; new_apos0G->ycenter = acellptr->ycenter ; if( acc_move = uinst( /* old_apos, new_apos */) ) { flipsG++ ; flip[CELL_INSTANCE_CHANGE]++ ; acc_cntS++ ; if( quickrouteG ){ move_size[CELL_INSTANCE_CHANGE] += d_costG ; } } att[CELL_INSTANCE_CHANGE]++ ; break ; } /* end switch */ /* *********** END OF PROPOSED MOVE EVALUATION ********* */ attempts++ ; /* see if user has requested an interuption for graphics */ if( doGraphicsG && iterationG >= -1 ){ /* at iteration = -1 we wait for user to continue if requested */ if( iterationG == -1 && wait_for_userG && firstTimeS ){ G( TWmessage( "TimberWolfMC waiting for your response" ) ) ; G( process_graphics() ) ; firstTimeS = FALSE ; /* otherwise see if user has interupted program */ /* G( ) is NOGRAPHICS conditional compile */ } else G( if( TWinterupt() ) ){ G( process_graphics() ) ; } } /* ----------------------------------------------------------- Update annealing schedule */ /* if debug on check cost after each move */ D( "uloop/incr.", checkcost() ); D( "uloop/every_move", static BOOL debugVarL = FALSE ; if( debugVarL ){ G( process_graphics() ) ; } else { G( draw_the_data() ) ; } ) ; if (iterationG <= 0 ) { /* statistic collection for overlap and pinFactor determination */ avg_funcG = (avg_funcG * avgsG + funccostG) / (avgsG + 1.0) ; avgsG += 1.0 ; totalwireS += (DOUBLE) funccostG ; totalpenalS += (DOUBLE) penaltyG ; delta_time = ABS( old_time - timingpenalG ) ; if( delta_time != 0 ){ /* calculate a running average of the delta timing penalty */ num_dtimeS += 1.0 ; avg_dtimeS = (avg_dtimeS * (num_dtimeS - 1.0) + (DOUBLE) delta_time) / num_dtimeS ; /* calculate a running average of the delta wiring penalty */ delta_func = ABS( old_func - funccostG ) ; num_dfuncS += 1.0 ; avg_dfuncS = (avg_dfuncS * (num_dfuncS - 1.0) + (DOUBLE) delta_func) / num_dfuncS ; } /* now update the old values of the timing and wirelength */ old_time = timingpenalG ; old_func = funccostG ; if (iterationG != 0.0 ){ /* stay at a high temperature */ continue; } /* lower temperature to starting point from infinite temp. */ /* do this to get starting temperature correct */ if (d_costG >= 0){ /*** d_cost is the -ve of the actual d_cost ***/ m1 ++; } else { dCp -= d_costG; m2 ++; } temp = (init_accG * attempts - m1) / m2; if (temp <= 0.0) { TG *= 0.9; } else { TG = -dCp / (m2 * log(temp)); } continue; /*** initialization phase. JL **/ } /* ----------------------------------------------------------------- Update temperature using negative feedback to control the acceptance ratio in accordance to curve fit schedule. Calc_acceptance_ratio returns desired acceptance ratio give the iteration. The damped error term (deviation) is then applied to correct the temperature T. Update_window_size controls the range limiter. We avoid updating T during initialization, we use exact schedule to compute starting T. The temp_timer allows us to update temperature inside the inner loop of the annealing algorithm. We use counter to avoid use of mod function for speed. We can either pick from incremental a_ratio or cummulative ratio. ------------------------------------------------------------------ */ if( ++temp_timer >= time_to_update || attempts >= attmaxG ) { a_ratioS = (DOUBLE) acc_cntS / (DOUBLE) temp_timer;/*incremental*/ ratioG = (DOUBLE) flipsG / (DOUBLE) attempts ; /*cummulative*/ temp_timer = 0 ; /* reset counter */ acc_cntS = 0; /* reset incremental timer */ iter_time = (DOUBLE) iterationG + (DOUBLE) attempts / (DOUBLE) attmaxG ; accept_deviation = (calc_acceptance_ratio( iter_time ) - a_ratioS ) ; #ifdef NEEDED YgraphHeading( "graph_T", "iter","pre_def","post_dev", "run_avg","calc_dev", "meas_dev","T", NULL ) ; Ygraph( "graph_T", "%d", iterationG, "%4.2le", accept_deviation ) ; Ygraph( "graph_T", "%d", iterationG, "%4.4le %4.4le %4.4le %4.4le %4.4le", accept_deviation, running_avg, calc_acceptance_ratio(iter_time), a_ratioS, TG ); YgraphFlush( "graph_T" ) ; #endif if( iterationG <= (INT) HIGHTEMP ) { /* no change to damping factor */ } else if( iterationG <= (INT) TURNOFFT ) { accept_deviation *= ACCEPTDAMPFACTOR ; } else { accept_deviation *= ACCEPTDAMPFACTOR2 ; } TG *= 1.0 + accept_deviation ; TG = MAX( TG, TMIN ) ; /* to avoid floating point errors */ update_window_size( iter_time ) ; } /* End of annealing schedule update ----------------------------------------------------------- */ /* ******************************************************* Now if moves were rejected and they were single cell or pairwise cell moves, try the same moves but with rotations. We think it makes sense to try another move with rotation if the move without rotation failed. Goto takes us not to beginning of loop but to top of move selection switch. We need to fall to bottom of loop so that the statistics are updated. ******************************************************** */ if( !(acc_move) ){ /* move wasn't accepted */ switch( proposed_move ){ case SINGLE_CELL_MOVE: proposed_move = SINGLE_CELL_MOVE_AND_ROTATE ; goto MOVE_START ; case SINGLE_CELL_MOVE_AND_ROTATE: /* - - - - - - - - - - - - - - - - - - - - - - - - - - If we fail rotation and move, propose to try either aspect ratio change or/and instance change depending on what moves are allowed. If both are allowed roll the dice. - - - - - - - - - - - - - - - - - - - - - - - - - - - */ if( acellptr->softflag && acellptr->aspUB > 0.01 + acellptr->aspLB ){ asp_move_possible = TRUE ; } else { asp_move_possible = FALSE ; } if( asp_move_possible && acellptr->instptr ){ /* roll the dice */ if( PICK_INT( 0, 1 ) ){ proposed_move = ASPECT_RATIO_CHANGE ; } else { proposed_move = CELL_INSTANCE_CHANGE ; } goto MOVE_START ; } else if( acellptr->instptr ){ proposed_move = CELL_INSTANCE_CHANGE ; goto MOVE_START ; } else if( asp_move_possible){ proposed_move = ASPECT_RATIO_CHANGE ; goto MOVE_START ; } else { /* done sequence */ break ; } case PAIRWISE_CELL_SWAP: proposed_move = PAIRWISE_CELL_SWAP_AND_ROTATION ; goto MOVE_START ; case PAIRWISE_CELL_SWAP_AND_ROTATION: /* done sequence */ break ; case ROTATION: /* done sequence */ break ; case ASPECT_RATIO_CHANGE: /* if we fail aspect ratio change propose pin change */ if( acellptr->numpins > 0 ){ /* end of sequence try only one so we don't due */ /* too much work at high T. */ /* proposed_move = SOFT_PIN_MOVE ; */ proposed_move = NULL ; goto MOVE_START ; } else { /* done sequence */ break ; } case SOFT_PIN_MOVE: /* done sequence */ break ; case GROUP_CELL_MOVE: /* done sequence */ break ; case CELL_INSTANCE_CHANGE: /* done sequence */ break ; } /* end switch */ } } /* ****** END OF ANNEALING INNER LOOP **************** */ /* verify incremental and current costs after each iteration */ D( "uloop", checkcost() ) ; if( !(++dumpCountS % dumpRatioS) ){ G( setGraphicWindow() ) ; G( draw_the_data() ) ; } /* ----------------------------------------------------------------- Use negative feedback to control relative ratio between penalties */ /* first get percentage of the task we have completed - temp */ percentDone = eval_ratio( iterationG ) ; if( percentDone >= FINISHED ){ /* turn off controller when percent done is 1.0 */ /* controlOn is initialize to TRUE and once turned off cannot */ /* get turned back on */ /* controlOnS = FALSE ; */ } if( controlOnS ){ /* **** core area controller **** */ coreFactorG = calc_core_factor( percentDone ) ; /* **** overlap penalty controller **** */ lapFactorG = calc_lap_factor( percentDone ) ; /* **** timing penalty controller **** */ timeFactorG = calc_time_factor( percentDone ) ; } /* end negative feedback controller code */ /* reset penalties */ penaltyG = (INT) (lapFactorG * sqrt( (DOUBLE) binpenalG ) ) ; timingcostG = (INT) (timeFactorG * (DOUBLE) timingpenalG ) ; total_costS = (DOUBLE) (funccostG + penaltyG + timingcostG ) ; ratioG = ( (DOUBLE) flipsG / (DOUBLE) attempts ) ; /* OUT3( "ratio : %4.2lf a_ratio : %4.2lf\n" , ratioG, a_ratioS) ;*/ FLUSHOUT() ; if( quickrouteG ){ output_move_table( flip, att, move_size ) ; } /* ----------------------------------------------------------------- If we are going to do a compaction save Temp. for low temperature anneal - compaction phase. We are saving the temperature which gives us a certain acc. ratio */ if( doCompactionG ){ if( ratioG > RATIOLOWERBOUND && ratioG < RATIOUPPERBOUND ){ TratioS = TG ; save_window( NULL ) ; /* save values in memory */ } } /* ----------------------------------------------------------------- now output statistics for this temperature. */ OUT1("\nI T funccost binpen x lapFact = penalty cost coreFactor\n"); OUT2("%3d ",iterationG ); OUT2("%4.2le ",TG ); OUT2("%4.2le ",(DOUBLE) funccostG ); OUT2("%4.2le ",(DOUBLE) binpenalG ); OUT2("%4.2le ",lapFactorG ); OUT2("%4.2le ",(DOUBLE) penaltyG ); OUT2("%4.2le ",total_costS ); OUT2("%4.2le\n",coreFactorG ); OUT1("timeFactor timepenal timecost var perDone\n"); OUT2("%4.2le ",(DOUBLE) timeFactorG ); OUT2("%4.2le ",(DOUBLE) timingpenalG ); OUT2("%4.2le ",(DOUBLE) timingcostG ); OUT2("%4.2le\n ",percentDone ); #ifdef LATER OUT1(" flip1 flipo flip0 flipp flipa flip2 flipo2 flipi flips ratio\n"); OUT3("%3d/%3d ",flip1,att1 ); OUT3("%3d/%3d ",flipo,atto ); OUT3("%3d/%3d ",flip0,att0 ); OUT3("%3d/%3d ",flipp,attp ); OUT3("%3d/%3d ",flipa,atta ); OUT3("%3d/%3d ",flip2,att2 ); OUT3("%3d/%3d ",flipo2,atto2 ); OUT3("%3d/%3d ",flipi,atti ); #endif OUT3(" %3d/%3d ",flipsG,attempts ); OUT2(" %4.2f\n\n",ratioG ); FLUSHOUT() ; /* GRAPH( graphFileName, xVarformat, xVar, yVarformat, yVars... ) */ YgraphHeading( "graph", "iter","funccost","binpenal", "percentDone","lapFactor","coreFactor", "ratio", "T", "totalcost", NULL ) ; Ygraph( "graph", "%d", iterationG, "%d %d %d %4.2le %4.2le %4.2le %4.2le %4.2le %4.2le", funccostG,binpenalG,percentDone,lapFactorG, coreFactorG, ratioG, TG, total_costS ) ; YgraphFlush( "graph" ) ; return ; } /* end uloop */ /* ***************************************************************** */ /* initializes random wiring and overlap statistics */ initStatCollection() { avgsG = 0.0 ; avg_funcG = 0.0 ; totalwireS = 0.0 ; totalpenalS = 0.0 ; avg_dtimeS = 0.0 ; num_dtimeS = 0.0 ; avg_dfuncS = 0.0 ; num_dfuncS = 0.0 ; ratioG = 1.0 ; } /* end initStatCollection */ /* ***************************************************************** */ getStatistics( totalWire, totalPenalty, avg_time, avg_func ) DOUBLE *totalWire, *totalPenalty, *avg_time, *avg_func ; { *totalWire = totalwireS ; *totalPenalty = totalpenalS ; *avg_time = avg_dtimeS ; *avg_func = avg_dfuncS ; } /* end getStatistics */ /* ***************************************************************** make_movebox - ALLOCATE MEMORY FOR MOVE RECORDS move boxes - old_aposG[0] holds info for old cell ie orient cell old_aposG[1..n] holds tile information for old cell. new_aposG[1..n] holds tile information for new cell. softcells only use old_aposG[1] and new_aposG[1] since they can have only one tile. */ make_movebox() { INT i ; INT maxtiles ; maxtiles = get_tile_count() ; /* allocate four arrays of moveboxs */ old_aposG = (MOVEBOXPTR *) Ysafe_malloc( maxtiles * sizeof(MOVEBOXPTR) ); for( i = 0; i< maxtiles ; i++ ){ old_aposG[i] = (MOVEBOXPTR) Ysafe_malloc( sizeof(MOVEBOX) ) ; old_aposG[i]->loaded_previously = FALSE ; } old_apos0G = old_aposG[0] ; new_aposG = (MOVEBOXPTR *) Ysafe_malloc( maxtiles * sizeof(MOVEBOXPTR) ); for( i = 0; i< maxtiles ; i++ ){ new_aposG[i] = (MOVEBOXPTR) Ysafe_malloc( sizeof(MOVEBOX) ) ; new_aposG[i]->loaded_previously = FALSE ; } new_apos0G = new_aposG[0] ; old_bposG = (MOVEBOXPTR *) Ysafe_malloc( maxtiles * sizeof(MOVEBOXPTR) ); for( i = 0; i< maxtiles ; i++ ){ old_bposG[i] = (MOVEBOXPTR) Ysafe_malloc( sizeof(MOVEBOX) ) ; old_bposG[i]->loaded_previously = FALSE ; } old_bpos0G = old_bposG[0] ; new_bposG = (MOVEBOXPTR *) Ysafe_malloc( maxtiles * sizeof(MOVEBOXPTR) ); for( i = 0; i< maxtiles ; i++ ){ new_bposG[i] = (MOVEBOXPTR) Ysafe_malloc( sizeof(MOVEBOX) ) ; new_bposG[i]->loaded_previously = FALSE ; } new_bpos0G = new_bposG[0] ; } /* end function make_movebox */ /* ***************************************************************** save_uloop - save uloop parameters for restart */ save_uloop( fp ) FILE *fp ; { fprintf(fp,"# uloop parameters:\n") ; fprintf(fp,"%d %d %d\n",iterationG,acc_cntS,move_cntS); fprintf(fp,"%f %f\n",a_ratioS,total_costS); } /* end save_uloop */ /* ***************************************************************** read_uloop - read uloop parameters for restart */ INT read_uloop( fp ) FILE *fp ; { INT error = 0 ; fscanf(fp,"%[ #:a-zA-Z]\n",YmsgG ); /* throw away comment */ fscanf(fp,"%ld %ld %ld\n",&iterationG,&acc_cntS,&move_cntS); fscanf(fp,"%lf %lf\n",&a_ratioS,&total_costS); /* try to detect errors in file */ if( acc_cntS < 0 ){ M(ERRMSG,"read_uloop","Restart file: acc_cntS negative\n") ; error++ ; } if( move_cntS < 0 ){ M(ERRMSG,"read_uloop","Restart file: move_cnt negative\n") ; error++ ; } if( a_ratioS < 0.0 ){ M(ERRMSG,"read_uloop","Restart file: a_ratio negative\n") ; error++ ; } if( a_ratioS > 1.0 ){ M(ERRMSG,"read_uloop","Restart file: a_ratio >1\n") ; error++ ; } if( iterationG < 1 ){ M(ERRMSG,"read_uloop","Restart file: iteration count <1\n") ; error++ ; /* one error */ } return(error) ; } /* end read_uloop */ /* ***************************************************************** initializeTemp - reinitializes temperature for a low temperature anneal. */ initializeTemp() { if( fabs(TratioS) < EPSILON ) { /* use default temperature */ TG = DEFAULTTEMP ; } else { TG = TratioS ; } ratioG = LOWTEMPRATIO ; fix_window() ; } partition_pick( turn_on ) INT turn_on ; { INT pick_partition_pos() ; if( turn_on ){ which_pickS = pick_partition_pos ; } else { which_pickS = pick_position ; } } /* end funtion partition_pick */ set_dump_ratio( count ) { dumpRatioS = count ; } /* end dump_ratio */ static output_move_table( flip, att, move_size ) INT *flip, *att ; DOUBLE *move_size ; { INT i ; FILE *fp ; char filename[LRECL] ; sprintf( filename, "%s.mset", cktNameG ) ; fp = TWOPEN( filename, "a", ABORT ) ; fprintf( fp, "I:%d ", iterationG ) ; for( i = 1; i <= NUMBER_MOVES; i++ ){ fprintf( fp, "%d %d %4.2le ", flip[i], att[i], move_size[i] ) ; } fprintf( fp, "\n" ) ; TWCLOSE( fp ) ; } /* end output_move_table */ graywolf-0.1.4+20170307gite1bf319/src/twmc/unbust.c000066400000000000000000000633731305746555600212250ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: unbust.c DESCRIPTION:routine which combines busted tiles for output CONTENTS: unbust() initPts( INT , char *, INT ) DATE: Jan 29, 1988 REVISIONS: Aug 16, 1989 - rewrote using new general algorithm. Sep 19, 1989 - now debug uses stderr. Sep 20, 1989 - added initialization to numptS+1 Sep 25, 1989 - correctly works for objects created with buster with minimal amount of work. Sun Dec 16 00:35:22 EST 1990 - now use library definition of buster. Sun Jan 20 21:34:36 PST 1991 - ported to AIX. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) unbust.c version 3.7 1/20/91" ; #endif #include #include #include #include #define E 0 #define T 1 #define L 2 #define R 3 #define B 4 #define HOWMANY 0 #define EXPECTEDNUMPINS 4 typedef struct { INT tile ; /* tile that point is attached */ INT x ; /* x position of point */ INT y ; /* y position of point */ INT Vnum ; /* position in VPts array */ INT Hnum ; /* position in HPts array */ INT order ; /* order that points should be output - negative means invalid */ BOOL marked ; /* point has been used */ } POINTBOX, *POINTPTR ; static INT numptS ; /* number of total points for figure */ static INT ptAllocS ; /* number of space allocated for points */ static POINTPTR *VptS = NULL ;/* vertical point array */ static POINTPTR *HptS ; /* horizontal point array */ static YBUSTBOXPTR resultS ; /* result array */ static BOOL addptS = FALSE ; /* whether to add points to figures or not*/ static INT find_next_state() ; static INT remove_redundant_points() ; static INT find_next_state(); static INT sortbyXY(); static INT sortbyYX(); static INT sortbyorder(); static INT remove_redundant_points(); static add_vpts(); static chek_vpt(); static add_hpts(); static chek_hpt(); static INT nextStateS[5][5] = { /* ERROR state - E */ E, E, E, E, E, /* UP state - T */ E, L, T, R, /* B */ E, /* LEFT state - L */ E, B, L, T, /* R */ E, /* RIGHT state - R */ E, T, R, B, /* L */ E, /* DOWN state - B */ E, R, B, L, /* T */ E } ; YBUSTBOXPTR unbust() { /* * Algorithm: * Add points to data structures. * Sort points according to x (Hpt array) and y (Vpt array) pos. * Remove redundant points. * If multiple tiles, * Check parallel line segments at change of tile boundary * Extend lines to hit other tile. Add points at these * intersections. When all points are added, sort again. * Tile needs only to be rectilinear not rectangular. * and use following Finite Automaton to find minimum containing * figure. * STATE TABLE. * last state try1 try2 try3 try4 * T L T R B - error * L B L T R - errror * R T R B L - error * B R B L T - error * * where * L : -1 in the Hpt array. * R : +1 in the Hpt array. * B : -1 in the Vpt array. * T : +1 in the Vpt array. * * By starting at the lower left point or Hpt[1] and * using the FA. we will traverse the minimum containing * figure of the cell or cells. * */ POINTPTR cur_pt ; /* current point record */ POINTPTR next_pt ; /* next point record */ INT sortbyXY() ; /* sort horizontal points */ INT sortbyYX() ; /* sort vertical points */ INT sortbyorder() ;/* final sort */ INT i ; /* counter */ INT count ; /* counter */ INT cur_state ; /* current state */ INT next_state ; /* next state */ INT limit ; /* used to detect loops */ INT order ; /* used to order the points */ INT given_num_pts ;/* number of points user gave us */ INT points_removed;/* number of redundant points removed */ /* static INT find_next_state() ; static INT remove_redundant_points() ; */ /* initialize 0 record */ cur_pt = VptS[0] ; cur_pt->order = 0 ; cur_pt->marked = TRUE ; cur_pt->Vnum = 0 ; cur_pt->Hnum = 0 ; cur_pt->x = INT_MIN ; cur_pt->y = INT_MIN ; resultS[HOWMANY].x = 0 ; /* initialize for error trapping */ /* sort points */ /* horizontal points */ Yquicksort( &(HptS[1]), numptS, sizeof(POINTPTR), sortbyYX ) ; /* vertical points */ Yquicksort( &(VptS[1]), numptS, sizeof(POINTPTR), sortbyXY ) ; /* need to delay changing number of points until both arrays are processed */ points_removed = 0 ; points_removed += remove_redundant_points( HptS ) ; points_removed += remove_redundant_points( VptS ) ; numptS -= points_removed ; D( "unbust", fprintf( stderr,"\n" ) ) ; given_num_pts = numptS ; if( addptS ){ /* only add points if necessary */ add_vpts( given_num_pts ) ; add_hpts( given_num_pts ) ; } if( numptS != given_num_pts ){ /* sort again */ Yquicksort( &(HptS[1]),numptS,sizeof(POINTPTR),sortbyYX ) ; /* vertical points */ Yquicksort( &(VptS[1]),numptS,sizeof(POINTPTR),sortbyXY ) ; points_removed = 0 ; points_removed += remove_redundant_points( HptS ) ; points_removed += remove_redundant_points( VptS ) ; numptS -= points_removed ; } /* initialize last record */ cur_pt = VptS[numptS+1] ; cur_pt->order = 0 ; cur_pt->marked = TRUE ; cur_pt->Vnum = numptS+1 ; cur_pt->Hnum = numptS+1 ; cur_pt->x = INT_MAX ; cur_pt->y = INT_MAX ; /* note both arrays must be done since redundant points may */ /* live up here */ cur_pt = HptS[numptS+1] ; cur_pt->order = 0 ; cur_pt->marked = TRUE ; cur_pt->Vnum = numptS+1 ; cur_pt->Hnum = numptS+1 ; cur_pt->x = INT_MAX ; cur_pt->y = INT_MAX ; /* name the points so we can cross reference */ for( i = 1; i <= numptS; i++ ){ cur_pt = HptS[i] ; cur_pt->Hnum = i ; } for( i = 1; i <= numptS; i++ ){ cur_pt = VptS[i] ; cur_pt->Vnum = i ; } dump_pts( VptS ) ; /* start automaton */ /* note we don't mark first point so we can return to it */ cur_pt = HptS[1] ; cur_pt->order = order = 1 ; cur_state = R ; limit = numptS + 1 ; D( "unbust", fprintf( stderr,"start_state:%d pt:(%d,%d)\n", cur_state, cur_pt->x, cur_pt->y ) ) ; for( i = 0; i <= limit; i++ ){ /* infinite loop protector */ /* determine next state */ if( next_state = find_next_state( cur_state,cur_pt,&next_pt )){ D( "unbust", fprintf( stderr,"next_state:%d next_pt:(%d,%d)\n", next_state, next_pt->x, next_pt->y ) ) ; if( next_pt->order == 1 ){ /* we know we have made a full circle */ /* first make sure last point is not colinear */ if( next_state == cur_state ){ order-- ; cur_pt->order = 0 ; } break ; } /* remove colinear points */ if( next_state != cur_state ){ next_pt->order = ++order ; } else { cur_pt->order = 0 ; next_pt->order = order ; } } else { M( ERRMSG, "unbust", "can't get next state fatal problem\n" ) ; break ; } /* set up for next state */ cur_pt = next_pt ; cur_state = next_state ; } /* end finite automaton */ if( i == limit ){ M( ERRMSG, "unbust", "we have detected an infinite loop in automaton\n" ) ; return ; } dump_pts( VptS ) ; /* now sort points by order for output */ Yquicksort( &(VptS[1]), numptS, sizeof(POINTPTR), sortbyorder ) ; dump_pts( VptS ) ; /* now output the points */ for( count=0,i=0; i <= numptS; i++ ){ if( VptS[i]->order ){ resultS[++count].x = VptS[i]->x ; resultS[count].y = VptS[i]->y ; } } resultS[HOWMANY].x = order ; return( resultS ) ; } /* end unbust */ /* find the next valid state */ static INT find_next_state( cur_state, cur_pt, next_pt ) INT cur_state ; POINTPTR cur_pt ; POINTPTR *next_pt ; { INT hpoint ; /* position of point in HptS */ INT vpoint ; /* position of point in HptS */ INT try ; /* used to test each possibility */ POINTPTR try_pt ; /* this is a candidate point */ /* get two partner of the current state */ hpoint = cur_pt->Hnum ; vpoint = cur_pt->Vnum ; ASSERTNRETURN( vpoint > 0 && vpoint <= numptS, "find_next_state", "vpoint out of bounds\n" ) ; ASSERTNRETURN( hpoint > 0 && hpoint <= numptS, "find_next_state", "hpoint out of bounds\n" ) ; /* now try possibilities in order */ for( try = 1; try <= 4; try++ ){ switch( nextStateS[cur_state][try] ){ case E: return( E ) ; case T: try_pt = VptS[vpoint+1] ; if(!(try_pt->marked) && cur_pt->x == try_pt->x ){ if( addptS ){ try_pt->marked = TRUE ; *next_pt = try_pt ; return( T ) ; } else { /* points must be same or adjacent tiles */ if( cur_pt->tile == try_pt->tile || cur_pt->tile + 1 == try_pt->tile || cur_pt->tile - 1 == try_pt->tile ){ try_pt->marked = TRUE ; *next_pt = try_pt ; return( T ) ; } } } break ; case L: try_pt = HptS[hpoint-1] ; if(!(try_pt->marked) && cur_pt->y == try_pt->y ){ if( addptS ){ try_pt->marked = TRUE ; *next_pt = try_pt ; return( L ) ; } else { /* points must be same or adjacent tiles */ if( cur_pt->tile == try_pt->tile || cur_pt->tile + 1 == try_pt->tile || cur_pt->tile - 1 == try_pt->tile ){ try_pt->marked = TRUE ; *next_pt = try_pt ; return( L ) ; } } } break ; case R: try_pt = HptS[hpoint+1] ; if(!(try_pt->marked) && cur_pt->y == try_pt->y ){ if( addptS ){ try_pt->marked = TRUE ; *next_pt = try_pt ; return( R ) ; } else { /* in this case points must be adjacent tiles */ if( cur_pt->tile == try_pt->tile || cur_pt->tile + 1 == try_pt->tile || cur_pt->tile - 1 == try_pt->tile ){ try_pt->marked = TRUE ; *next_pt = try_pt ; return( R ) ; } } } break ; case B: try_pt = VptS[vpoint-1] ; if(!(try_pt->marked) && cur_pt->x == try_pt->x ){ if( addptS ){ try_pt->marked = TRUE ; *next_pt = try_pt ; return( B ) ; } else { /* in this case points must be adjacent tiles */ if( cur_pt->tile == try_pt->tile || cur_pt->tile + 1 == try_pt->tile || cur_pt->tile - 1 == try_pt->tile ){ try_pt->marked = TRUE ; *next_pt = try_pt ; return( B ) ; } } } break ; } /* end switch */ } /* end going thru posibilities */ } /* end get_next_state */ addPt( tile, x, y ) INT tile, x, y ; { INT i ; /* counter */ POINTPTR ptr ; /* current point */ /* reallocate space if necessary */ if( ++numptS >= ptAllocS ){ ptAllocS += EXPECTEDNUMPINS ; VptS = (POINTPTR *) Ysafe_realloc( VptS, ptAllocS * sizeof(POINTPTR)) ; HptS = (POINTPTR *) Ysafe_realloc( HptS, ptAllocS * sizeof(POINTPTR)) ; resultS = (YBUSTBOXPTR) Ysafe_realloc( resultS, ptAllocS * sizeof(YBUSTBOX)) ; for( i = numptS; i < ptAllocS; i++ ){ HptS[i] = VptS[i] = (POINTPTR) Ysafe_malloc( sizeof(POINTBOX)) ; } } /* end space allocation */ /* now initialize data for point */ ptr = HptS[numptS] ; /* they point to same object */ ptr->tile = tile ; ptr->x = x ; ptr->y = y ; ptr->order = 0 ; ptr->Vnum = 0 ; ptr->Hnum = 0 ; ptr->marked = FALSE ; D( "addPt", fprintf( stderr,"adding point (%d,%d)...\n", x, y ) ) ; return ; } /* end addPt */ addPts( cell, l, r, b, t ) INT cell, l, r, b, t ; { addPt( cell, l, b ) ; addPt( cell, l, t ) ; addPt( cell, r, t ) ; addPt( cell, r, b ) ; D( "addPts", fprintf( stderr, "%d %d %d %d %d %d %d %d\n", l, b, l, t, r, t, r, b ) ) ; } /* end addPts */ initPts( addpoint_flag ) BOOL addpoint_flag ; { INT i ; /* counter */ numptS = 0 ; /* set addpoint static flag */ addptS = addpoint_flag ; if(!(VptS)){ ptAllocS = EXPECTEDNUMPINS ; VptS = (POINTPTR *) Ysafe_malloc( ptAllocS * sizeof(POINTPTR)) ; HptS = (POINTPTR *) Ysafe_malloc( ptAllocS * sizeof(POINTPTR)) ; resultS = (YBUSTBOXPTR) Ysafe_malloc( ptAllocS * sizeof(YBUSTBOX)) ; for( i = 0; i < ptAllocS; i++ ){ HptS[i] = VptS[i] = (POINTPTR) Ysafe_malloc( sizeof(POINTBOX)) ; } } else { /* make both arrays point to the same object */ for( i = 0; i < ptAllocS; i++ ){ HptS[i] = VptS[i] ; } } return ; } /* end initPts */ /* sort by x first then y */ static INT sortbyXY( pointA , pointB ) POINTPTR *pointA , *pointB ; { if( (*pointA)->x != (*pointB)->x ){ return( (*pointA)->x - (*pointB)->x ) ; } else { /* if x's are equal sort by y's */ return( (*pointA)->y - (*pointB)->y ) ; } } /* end sortbyXY */ /* sort by y first then x */ static INT sortbyYX( pointA , pointB ) POINTPTR *pointA , *pointB ; { if( (*pointA)->y != (*pointB)->y ){ return( (*pointA)->y - (*pointB)->y ) ; } else { /* if y's are equal sort by x's */ return( (*pointA)->x - (*pointB)->x ) ; } } /* end sortbyYX */ /* sort by order */ static INT sortbyorder( pointA , pointB ) POINTPTR *pointA , *pointB ; { return( (*pointA)->order - (*pointB)->order ) ; } /* end sortbyorder */ static INT remove_redundant_points( pt_array ) POINTPTR *pt_array ; { POINTPTR ptptr ; /* pointer to point record */ POINTPTR *tempArray ; /* temporary pointer for manipulating points */ INT oldX ; /* last x point */ INT oldY ; /* last y point */ INT redundant ; /* number of redundant points */ INT i ; /* counter */ INT top ; /* top of the point array */ INT bottom ; /* bottom of the point array */ BOOL no_ignored_pts ; /* invalid points exist in the array */ POINTPTR oldptr ; /* the last irredundant point */ ptptr = pt_array[0] ; oldX = ptptr->x ; oldY = ptptr->y ; redundant = 0 ; /* check to see if we have redundant points */ no_ignored_pts = TRUE ; for( i = 1; i <= numptS; i++ ){ ptptr = pt_array[i] ; /* ignore already redundant points */ if( ptptr->order == -1 ){ no_ignored_pts = FALSE ; continue ; } if( ptptr->x == oldX && ptptr->y == oldY ){ /* redundant point */ ptptr->order = -1 ; redundant++ ; /* need to set tile to smaller of two points */ /* so that all tiles will be adjacent */ oldptr->tile = MIN( oldptr->tile, ptptr->tile ) ; } oldX = ptptr->x ; oldY = ptptr->y ; oldptr = ptptr ; } if( redundant == 0 && no_ignored_pts ){ /* array is fine */ return( 0 ) ; } D( "remove_redundant_points", fprintf( stderr,"found %d redundant points\n", redundant ) ) ; /* we need to do work to remove point */ tempArray = (POINTPTR *) Ysafe_malloc( (numptS+1)*sizeof(POINTPTR) ) ; for( i=0; i <= numptS; i++ ) { tempArray[i] = pt_array[i] ; } /* now write valid points back */ bottom = 0 ; top = numptS ; for( i=0; i <= numptS; i++ ) { if( tempArray[i]->order >= 0 ){ pt_array[bottom++] = tempArray[i] ; } else { /* put invalid points at top of array so we can free them later on */ pt_array[top--] = tempArray[i] ; } } D( "remove_redundant_points", fprintf( stderr,"bottom:%d top:%d redundant:%d\n", bottom, top, redundant ) ) ; dump_pts( pt_array ) ; Ysafe_free( tempArray ) ; return( redundant ) ; } /* end remove_redundant_points */ static add_vpts( numpts ) INT numpts ; { POINTPTR tile1ptr ; /* temp pointer to a point */ POINTPTR tile2ptr ; /* temp pointer to a point */ POINTPTR tile3ptr ; /* temp pointer to a point */ POINTPTR tile4ptr ; /* temp pointer to a point */ INT i ; /* point counter */ INT j ; /* point counter */ INT oldX ; /* used to find vertical points */ INT tile1 ; /* tile1ptr's tile */ INT tile2 ; /* tile2ptr's tile */ INT tile3 ; /* tile3ptr's tile */ INT tile4 ; /* tile4ptr's tile */ BOOL newTiles ; /* when true load 4 points otherwise load two */ newTiles = TRUE ; D( "add_vpts",fprintf( stderr, "add_vpts:numpoints:%d\n", numpts ) ) ; /* process four points at a time */ for( i = 1; i+3 <= numpts; ){ if( newTiles ){ tile1ptr = VptS[i] ; tile2ptr = VptS[i+1] ; tile3ptr = VptS[i+2] ; tile4ptr = VptS[i+3] ; } else { /* tile1 and tile2 were determined below */ tile3ptr = VptS[i] ; tile4ptr = VptS[i+1] ; newTiles = TRUE ; } tile1 = tile1ptr->tile ; tile2 = tile2ptr->tile ; tile3 = tile3ptr->tile ; tile4 = tile4ptr->tile ; if( tile1 == tile2 ){ if( tile1 == tile3 && tile1 == tile4 ){ i += 4 ; /* all the same cell */ } else if( tile3 == tile4 ){ /* case two parallel lines that are diffent tiles */ chek_vpt( tile1ptr, tile2ptr, tile3ptr, tile4ptr ) ; i += 4 ; } else { /* one and two are same 3 and four are different */ /* 3 and 4 are colinear points */ /* find last of the colinear points */ oldX = VptS[i+2]->x ; for( j = i+3;j <= numpts;j++ ){ if( VptS[j]->x != oldX ){ j-- ; break ; } } ASSERT( j > 0 && j <=numpts, "add_vpts","j out of bounds\n" ) ; /* j is the last colinear vertical point */ /* i+2 -- j is a line to compare */ tile4ptr = VptS[j] ; chek_vpt( tile1ptr, tile2ptr, tile3ptr, tile4ptr ) ; i = j + 1 ; ASSERT( i > 0, "add_vpts","i out of bounds\n" ) ; } } else { /* find last of the colinear points */ oldX = VptS[i]->x ; for( j = i+1;j <= numpts;j++ ){ if( VptS[j]->x != oldX ){ j-- ; break ; } } ASSERT( j > 0 && j <=numpts,"add_vpts","j out of bounds\n" ); /* j is the last colinear vertical point */ tile2ptr = VptS[j] ; i = j + 1 ; } } /* end for loop */ if( i <= numpts ){ D( "add_vpts", fprintf( stderr, "ERROR[add_vpts] in algorithm\n" ) ) ; } } /* end add_vpts */ static chek_vpt( tile1, tile2, tile3, tile4 ) POINTPTR tile1, tile2, tile3, tile4 ; { /* four cases */ /* CASE 1 */ /* * 2 * X 4 * | | * X 3 * 1 */ if( tile1->y <= tile3->y && tile2->y >= tile4->y ){ /* add non - redundant upper X */ if( tile2->y != tile4->y ){ addPt( tile2->tile, tile1->x, tile4->y ) ; } if( tile1->y != tile3->y ){ addPt( tile1->tile, tile1->x, tile3->y ) ; } } /* CASE 2 */ /* * 4 * 2 X * | | * 1 X * 3 */ if( tile1->y >= tile3->y && tile2->y <= tile4->y ){ /* add non - redundant upper X */ if( tile2->y != tile4->y ){ addPt( tile4->tile, tile4->x, tile2->y ) ; } if( tile1->y != tile3->y ){ addPt( tile3->tile, tile3->x, tile1->y ) ; } } /* CASE 3 */ /* * 4 * 2 X * | | * X 3 * 1 */ if( tile1->y <= tile3->y && tile2->y <= tile4->y ){ /* add non - redundant upper X */ if( tile2->y != tile4->y ){ addPt( tile4->tile, tile4->x, tile2->y ) ; } if( tile1->y != tile3->y ){ addPt( tile1->tile, tile1->x, tile3->y ) ; } } /* CASE 4 */ /* * 2 * X 4 * | | * 1 X * 3 */ if( tile1->y >= tile3->y && tile2->y >= tile4->y ){ /* add non - redundant upper X */ if( tile2->y != tile4->y ){ addPt( tile2->tile, tile2->x, tile4->y ) ; } if( tile1->y != tile3->y ){ addPt( tile3->tile, tile3->x, tile1->y ) ; } } } /* end chek_vpt */ static add_hpts( numpts ) INT numpts ; { POINTPTR tile1ptr ; /* temp pointer to a point */ POINTPTR tile2ptr ; /* temp pointer to a point */ POINTPTR tile3ptr ; /* temp pointer to a point */ POINTPTR tile4ptr ; /* temp pointer to a point */ INT i ; /* point counter */ INT j ; /* point counter */ INT oldY ; /* used to find horizontal points */ INT tile1 ; /* tile1ptr's tile */ INT tile2 ; /* tile2ptr's tile */ INT tile3 ; /* tile3ptr's tile */ INT tile4 ; /* tile4ptr's tile */ BOOL newTiles ; /* when true load 4 points otherwise load two */ newTiles = TRUE ; D( "add_hpts", fprintf( stderr, "add_vpts:numpoints:%d\n", numpts ) ) ; /* process four points at a time */ for( i = 1; i+3 <= numpts; ){ if( newTiles ){ tile1ptr = HptS[i] ; tile2ptr = HptS[i+1] ; tile3ptr = HptS[i+2] ; tile4ptr = HptS[i+3] ; } else { /* tile1 and tile2 were determined below */ tile3ptr = HptS[i] ; tile4ptr = HptS[i+1] ; newTiles = TRUE ; } tile1 = tile1ptr->tile ; tile2 = tile2ptr->tile ; tile3 = tile3ptr->tile ; tile4 = tile4ptr->tile ; if( tile1 == tile2 ){ if( tile1 == tile3 && tile1 == tile4 ){ i += 4 ; /* all the same cell */ continue ; } else if( tile3 == tile4 ){ /* case two parallel lines that are diffent tiles */ chek_hpt( tile1ptr, tile2ptr, tile3ptr, tile4ptr ) ; i += 4 ; } else { /* one and two are same 3 and four are different */ /* 3 and 4 are colinear points */ /* find last of the colinear points */ oldY = HptS[i+2]->y ; for( j = i+3;j <= numpts;j++ ){ if( HptS[j]->y != oldY ){ j-- ; break ; } } ASSERT( j > 0 && j <= numpts, "add_hpts","j out of bounds\n" ) ; /* j is the last colinear vertical point */ /* i+2 -- j is a line to compare */ tile4ptr = HptS[j] ; chek_hpt( tile1ptr, tile2ptr, tile3ptr, tile4ptr ) ; i = j + 1 ; ASSERT( i > 0, "add_hpts","i out of bounds\n" ) ; } } else { /* find last of the colinear points */ oldY = HptS[i]->y ; for( j = i+1;j <= numpts;j++ ){ if( HptS[j]->y != oldY ){ j-- ; break ; } } ASSERT( j > 0 && j <=numpts,"add_hpts","j out of bounds\n" ); /* j is the last colinear vertical point */ tile2ptr = HptS[j] ; i = j + 1 ; } } /* end for loop */ if( i <= numpts ){ D( "add_hpts", fprintf( stderr, "ERROR[add_hpts] in algorithm\n" ) ) ; } } /* end add_hpts */ static chek_hpt( tile1, tile2, tile3, tile4 ) POINTPTR tile1, tile2, tile3, tile4 ; { /* four cases */ /* CASE 1 */ /* * * 3--4 * * 1--X--X--2 * */ if( tile1->x <= tile3->x && tile2->x >= tile4->x ){ /* add non - redundant lower X */ if( tile1->y != tile3->y ){ addPt( tile1->tile, tile3->x, tile1->y ) ; } if( tile2->y != tile4->y ){ addPt( tile2->tile, tile4->x, tile2->y ) ; } } /* CASE 2 */ /* * * 3--X--X--4 * * 1--2 * */ if( tile1->x >= tile3->x && tile2->x <= tile4->x ){ /* add non - redundant lower X */ if( tile1->y != tile3->y ){ addPt( tile3->tile, tile1->x, tile3->y ) ; } if( tile2->y != tile4->y ){ addPt( tile4->tile, tile2->x, tile4->y ) ; } } /* CASE 3 */ /* * * 3--X--4 * * 1--X--2 * */ if( tile1->x <= tile3->x && tile2->x <= tile4->x ){ /* add non - redundant lower X */ if( tile1->y != tile3->y ){ addPt( tile1->tile, tile3->x, tile1->y ) ; } if( tile2->y != tile4->y ){ addPt( tile4->tile, tile2->x, tile4->y ) ; } } /* CASE 4 */ /* * * 3--X--4 * * 1--X--2 * */ if( tile1->x >= tile3->x && tile2->x >= tile4->x ){ /* add non - redundant lower X */ if( tile1->y != tile3->y ){ addPt( tile3->tile, tile1->x, tile3->y ) ; } if( tile2->y != tile4->y ){ addPt( tile2->tile, tile4->x, tile2->y ) ; } } } /* end chek_hpt */ dump_pts( pt ) POINTPTR *pt ; { INT i ; POINTPTR ptr ; D( "dump_pts", fprintf( stderr, "Point dump:\n" ) ) ; for( i=0; i <= numptS; i++ ){ DS( ptr = pt[i] ; ) ; D( "dump_pts", fprintf( stderr, "(%d,%d) order=%d marked=%d Vnum=%d Hnum=%d tile:%d\n", ptr->x, ptr->y, ptr->order, ptr->marked, ptr->Vnum, ptr->Hnum, ptr->tile ) ) ; } } /* end dump_pts */ graywolf-0.1.4+20170307gite1bf319/src/twmc/unet.c000066400000000000000000000523371305746555600206560ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: unet.c DESCRIPTION:Incremental bounding box routines. CONTENTS: INT unet( antrmptr ) PINBOXPTR antrmptr ; statice check_validbound( dimptr , termptr , nextptr ) DBOXPTR dimptr ; TEBOXPTR termptr , nextptr ; static wire_boundary1( netptr ) NETBOXPTR netptr ; static wire_boundary2( c , netptr ) NETBOXPTR dimptr ; INT c ; init_unet() ; DATE: Mar 27, 1989 REVISIONS: Oct 21, 1989 - changed memoptrS to a pointer rather than a fixed array. Added init_unet to initialize this array. Apr 23, 1990 - added assertion to make sure half perimeter does not go negative. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) unet.c (Yale) version 3.6 11/23/91" ; #endif #include #include #define BREAK_PT 5 static INT prev_netS , curr_netS , test_newnetS ; static INT validLS , validRS , validBS , validTS ; static PINBOXPTR *memoptrS ; static INT kS ; static check_validbound(); static wire_boundary2(); static wire_boundary1(); init_unet() { INT maxpin, get_max_pin() ; maxpin = get_max_pin() ; memoptrS = (PINBOXPTR *) Ysafe_malloc( (++maxpin) * sizeof(PINBOXPTR) ) ; } /* end init_unet */ /* returns the incremental cost for a single cell */ INT unet( antrmptr ) PINBOXPTR antrmptr ; { register NETBOXPTR netptr ; register PINBOXPTR pinptr ; register INT x, y ; PINBOXPTR termptr , nextptr ; INT cost ; /* INT test ; */ prev_netS = -1 ; cost = 0 ; validRS = validLS = validBS = validTS = 0 ; for( termptr = antrmptr ; termptr ; termptr = termptr->nextpin ) { curr_netS = termptr->net ; test_newnetS = ( prev_netS == curr_netS ) ? 0 : 1 ; if( test_newnetS ) { memoptrS[ kS = 0 ] = termptr ; } prev_netS = curr_netS ; netptr = netarrayG[ curr_netS ] ; memoptrS[ ++kS ] = nextptr = termptr->nextpin ; if( netptr->nflag == 0 || netptr->skip == 1 ) { continue ; } if( netptr->numpins <= BREAK_PT ) { netptr->nflag = 0 ; /* ***** CASE of small number of pins - normal case ***** */ if( pinptr = netptr->pins ) { if( pinptr->flag == 1 ) { netptr->newxmin = netptr->newxmax = pinptr->newx ; netptr->newymin = netptr->newymax = pinptr->newy ; pinptr->flag = 0 ; } else { netptr->newxmin = netptr->newxmax = pinptr->xpos ; netptr->newymin = netptr->newymax = pinptr->ypos ; } } for( pinptr = pinptr->next ;pinptr; pinptr = pinptr->next ) { if( pinptr->flag == 1 ) { x = pinptr->newx ; y = pinptr->newy ; pinptr->flag = 0 ; } else { x = pinptr->xpos ; y = pinptr->ypos ; } if( x < netptr->newxmin ) { netptr->newxmin = x ; } else if( x > netptr->newxmax ) { netptr->newxmax = x ; } if( y < netptr->newymin ) { netptr->newymin = y ; } else if( y > netptr->newymax ) { netptr->newymax = y ; } } /* *********** end case of small number of pins ******** */ } else { check_validbound( netptr , termptr , nextptr ) ; /* if we have another pin on same net continue since we */ /* have already taken care of it */ if( nextptr && curr_netS == nextptr->net ) { continue ; } netptr->nflag = 0 ; wire_boundary2( validLS + 2*validBS + 4*validRS + 8*validTS, netptr ); validRS = validLS = validBS = validTS = 0 ; } /* add2net_set remembers which nets are modified by this move */ add2net_set( curr_netS ) ; netptr->newhalfPx = netptr->newxmax - netptr->newxmin ; netptr->newhalfPy = netptr->newymax - netptr->newymin ; ASSERT( netptr->newhalfPx >= 0,"unet","Half perimeter negative\n"); ASSERT( netptr->newhalfPy >= 0,"unet","Half perimeter negative\n"); /* new wire cost */ cost += ( netptr->newhalfPx - netptr->halfPx + (INT)(vertical_wire_weightG * (DOUBLE)netptr->newhalfPy) - (INT)(vertical_wire_weightG * (DOUBLE)netptr->halfPy) ); } return( cost ) ; } /* end unet */ INT unet2( antrmptr, bntrmptr ) PINBOXPTR antrmptr , bntrmptr ; { NETBOXPTR netptr ; PINBOXPTR termptr , nextptr ; INT anet , bnet ; INT aflag ; INT deltaP ; /* change in half perimeter bounding box */ INT cost ; /* INT test ; */ if( !antrmptr ) { return( unet( bntrmptr ) ) ; } if( !bntrmptr ) { return( unet( antrmptr ) ) ; } validRS = validLS = validBS = validTS = 0 ; aflag = ( antrmptr->net <= bntrmptr->net ) ? 1 : 0 ; if( aflag ) { termptr = antrmptr ; antrmptr = antrmptr->nextpin ; } else { termptr = bntrmptr ; bntrmptr = bntrmptr->nextpin ; } prev_netS = -1 ; cost = 0 ; for( ; termptr ; termptr = nextptr ) { curr_netS = termptr->net ; test_newnetS = ( prev_netS == curr_netS ) ? 0 : 1 ; if( test_newnetS ) { memoptrS[ kS = 0 ] = termptr ; } prev_netS = curr_netS ; netptr = netarrayG[ curr_netS ] ; if( antrmptr && bntrmptr ) { if( (anet = antrmptr->net) < (bnet = bntrmptr->net) ) { nextptr = antrmptr ; antrmptr = antrmptr->nextpin ; aflag = 1 ; } else if( anet > bnet ) { nextptr = bntrmptr ; bntrmptr = bntrmptr->nextpin ; aflag = 0 ; } else { /* anet is equal to bnet */ if( aflag ) { /* the current pointer is on antrmptr list*/ nextptr = antrmptr ; antrmptr = antrmptr->nextpin ; } else { /* the current pointer is on bntrmptr list*/ nextptr = bntrmptr ; bntrmptr = bntrmptr->nextpin ; } } } else if( !antrmptr && bntrmptr ) { nextptr = bntrmptr ; bntrmptr = bntrmptr->nextpin ; } else if( antrmptr && !bntrmptr ) { nextptr = antrmptr ; antrmptr = antrmptr->nextpin ; } else { nextptr = NIL(PINBOXPTR) ; } memoptrS[ ++kS ] = nextptr ; if( netptr->nflag == FALSE || netptr->skip == TRUE ) { continue ; } if( netptr->numpins <= BREAK_PT ) { netptr->nflag = FALSE ; wire_boundary1( netptr ) ; } else { /* The pin No. of the net is greater than break_pt */ check_validbound( netptr , termptr , nextptr ) ; if( nextptr && curr_netS == nextptr->net ) { continue ; } netptr->nflag = FALSE ; wire_boundary2( validLS + 2*validBS + 4*validRS + 8*validTS, netptr ) ; validRS = validLS = validBS = validTS = 0 ; } /* add2net_set remembers which nets are modified by this move */ add2net_set( curr_netS ) ; netptr->newhalfPx = netptr->newxmax - netptr->newxmin ; netptr->newhalfPy = netptr->newymax - netptr->newymin ; ASSERT( netptr->newhalfPx >= 0,"unet","Half perimeter negative\n"); ASSERT( netptr->newhalfPy >= 0,"unet","Half perimeter negative\n"); /* new wire cost */ cost += ( netptr->newhalfPx - netptr->halfPx + (INT)(vertical_wire_weightG * (DOUBLE)netptr->newhalfPy) - (INT)(vertical_wire_weightG * (DOUBLE)netptr->halfPy) ); } return( cost ) ; } /* end unet2 */ static check_validbound( netptr , termptr , nextptr ) NETBOXPTR netptr ; PINBOXPTR termptr , nextptr ; { INT nux , nuy , x , y ; nux = termptr->newx ; nuy = termptr->newy ; x = termptr->xpos ; y = termptr->ypos ; if( test_newnetS ) { netptr->newxmax = netptr->xmax ; netptr->newxmin = netptr->xmin ; netptr->newymax = netptr->ymax ; netptr->newymin = netptr->ymin ; netptr->newRnum = netptr->Rnum ; netptr->newLnum = netptr->Lnum ; netptr->newBnum = netptr->Bnum ; netptr->newTnum = netptr->Tnum ; } if( nux > netptr->newxmax ) { netptr->newxmax = nux ; netptr->newRnum = 1 ; validRS = 1 ; } else if( x != nux && nux == netptr->newxmax ) { netptr->newRnum++ ; validRS = 1 ; } else if( x == netptr->newxmax && nux < netptr->newxmax ) { netptr->newRnum-- ; } if( nux < netptr->newxmin ) { netptr->newxmin = nux ; netptr->newLnum = 1 ; validLS = 1 ; } else if( x != nux && nux == netptr->newxmin ) { netptr->newLnum++ ; validLS = 1 ; } else if( x == netptr->newxmin && nux > netptr->newxmin ) { netptr->newLnum-- ; } if( nuy > netptr->newymax ) { netptr->newymax = nuy ; netptr->newTnum = 1 ; validTS = 1 ; } else if( y != nuy && nuy == netptr->newymax ) { netptr->newTnum++ ; validTS = 1 ; } else if( y == netptr->newymax && nuy < netptr->newymax ) { netptr->newTnum-- ; } if( nuy < netptr->newymin ) { netptr->newymin = nuy ; netptr->newBnum = 1 ; validBS = 1 ; } else if( y != nuy && nuy == netptr->newymin ) { netptr->newBnum++ ; validBS = 1 ; } else if( y == netptr->newymin && nuy > netptr->newymin ) { netptr->newBnum-- ; } if( !nextptr || curr_netS != nextptr->net ) { if( !validRS && netptr->newxmax == netptr->xmax && netptr->newRnum > 0 ) { validRS = 1 ; } if( !validLS && netptr->newxmin == netptr->xmin && netptr->newLnum > 0 ) { validLS = 1 ; } if( !validTS && netptr->newymax == netptr->ymax && netptr->newTnum > 0 ) { validTS = 1 ; } if( !validBS && netptr->newymin == netptr->ymin && netptr->newBnum > 0 ) { validBS = 1 ; } } } /* end check_validbound */ static wire_boundary2( c , netptr ) NETBOXPTR netptr ; INT c ; { PINBOXPTR pinptr ; INT x , y , i ; if( c == 15 ) { for( i = 0 ; i <= kS-1 ; i++ ) { memoptrS[i]->flag = 0 ; } return ; } if( pinptr = netptr->pins ){ if( pinptr->flag == 1 ) { pinptr->flag = 0 ; switch( c ) { case 0 : /* L , R , B , T false */ netptr->newxmin = netptr->newxmax = pinptr->newx ; netptr->newymin = netptr->newymax = pinptr->newy ; break ; case 1 : /* R , B , T false */ netptr->newxmax = pinptr->newx ; netptr->newymin = netptr->newymax = pinptr->newy ; break ; case 2 : /* L , R , T false */ netptr->newxmin = netptr->newxmax = pinptr->newx ; netptr->newymax = pinptr->newy ; break ; case 3 : /* R , T false */ netptr->newxmax = pinptr->newx ; netptr->newymax = pinptr->newy ; break ; case 4 : /* L , B , T false */ netptr->newxmin = pinptr->newx ; netptr->newymin = netptr->newymax = pinptr->newy ; break ; case 5 : /* B , T false */ netptr->newymin = netptr->newymax = pinptr->newy ; break ; case 6 : /* L , T false */ netptr->newxmin = pinptr->newx ; netptr->newymax = pinptr->newy ; break ; case 7 : /* T false */ netptr->newymax = pinptr->newy ; break ; case 8 : /* L , R , B false */ netptr->newxmin = netptr->newxmax = pinptr->newx ; netptr->newymin = pinptr->newy ; break ; case 9 : /* R , B false */ netptr->newxmax = pinptr->newx ; netptr->newymin = pinptr->newy ; break ; case 10 : /* L , R false */ netptr->newxmin = netptr->newxmax = pinptr->newx ; break ; case 11 : /* R false */ netptr->newxmax = pinptr->newx ; break ; case 12 : /* L , B false */ netptr->newxmin = pinptr->newx ; netptr->newymin = pinptr->newy ; break ; case 13 : /* B false */ netptr->newymin = pinptr->newy ; break ; case 14 : /* L false */ netptr->newxmin = pinptr->newx ; break ; } } else { switch( c ) { case 0 : /* L , R , B , T false */ netptr->newxmin = netptr->newxmax = pinptr->xpos ; netptr->newymin = netptr->newymax = pinptr->ypos ; break ; case 1 : /* R , B , T false */ netptr->newxmax = pinptr->xpos ; netptr->newymin = netptr->newymax = pinptr->ypos ; break ; case 2 : /* L , R , T false */ netptr->newxmin = netptr->newxmax = pinptr->xpos ; netptr->newymax = pinptr->ypos ; break ; case 3 : /* R , T false */ netptr->newxmax = pinptr->xpos ; netptr->newymax = pinptr->ypos ; break ; case 4 : /* L , B , T false */ netptr->newxmin = pinptr->xpos ; netptr->newymin = netptr->newymax = pinptr->ypos ; break ; case 5 : /* B , T false */ netptr->newymin = netptr->newymax = pinptr->ypos ; break ; case 6 : /* L , T false */ netptr->newxmin = pinptr->xpos ; netptr->newymax = pinptr->ypos ; break ; case 7 : /* T false */ netptr->newymax = pinptr->ypos ; break ; case 8 : /* L , R , B false */ netptr->newxmin = netptr->newxmax = pinptr->xpos ; netptr->newymin = pinptr->ypos ; break ; case 9 : /* R , B false */ netptr->newxmax = pinptr->xpos ; netptr->newymin = pinptr->ypos ; break ; case 10 : /* L , R false */ netptr->newxmin = netptr->newxmax = pinptr->xpos ; break ; case 11 : /* R false */ netptr->newxmax = pinptr->xpos ; break ; case 12 : /* L , B false */ netptr->newxmin = pinptr->xpos ; netptr->newymin = pinptr->ypos ; break ; case 13 : /* B false */ netptr->newymin = pinptr->ypos ; break ; case 14 : /* L false */ netptr->newxmin = pinptr->xpos ; break ; } } } if( !validLS ) { netptr->newLnum = 1 ; } if( !validRS ) { netptr->newRnum = 1 ; } if( !validBS ) { netptr->newBnum = 1 ; } if( !validTS ) { netptr->newTnum = 1 ; } for( pinptr = pinptr->next ; pinptr ; pinptr = pinptr->next ) { if( pinptr->flag == 1 ) { x = pinptr->newx ; y = pinptr->newy ; pinptr->flag = 0 ; } else { x = pinptr->xpos ; y = pinptr->ypos ; } switch( c ) { case 0 : /* L , R , B , T false */ if( x < netptr->newxmin ) { netptr->newxmin = x ; netptr->newLnum = 1 ; } else if( x > netptr->newxmax ) { netptr->newxmax = x ; netptr->newRnum = 1 ; } else if( x == netptr->newxmin ) { netptr->newLnum++ ; if( x == netptr->newxmax ) { netptr->newRnum++ ; } } else if( x == netptr->newxmax ) { netptr->newRnum++ ; } if( y < netptr->newymin ) { netptr->newymin = y ; netptr->newBnum = 1 ; } else if( y > netptr->newymax ) { netptr->newymax = y ; netptr->newTnum = 1 ; } else if( y == netptr->newymin ) { netptr->newBnum++ ; if( y == netptr->newymax ) { netptr->newTnum++ ; } } else if( y == netptr->newymax ) { netptr->newTnum++ ; } break ; case 1 : /* R , B , T false */ if( x > netptr->newxmax ) { netptr->newxmax = x ; netptr->newRnum = 1 ; } else if( x == netptr->newxmax ) { netptr->newRnum++ ; } if( y < netptr->newymin ) { netptr->newymin = y ; netptr->newBnum = 1 ; } else if( y > netptr->newymax ) { netptr->newymax = y ; netptr->newTnum = 1 ; } else if( y == netptr->newymin ) { netptr->newBnum++ ; if( y == netptr->newymax ) { netptr->newTnum++ ; } } else if( y == netptr->newymax ) { netptr->newTnum++ ; } break ; case 2 : /* L , R , T false */ if( x < netptr->newxmin ) { netptr->newxmin = x ; netptr->newLnum = 1 ; } else if( x > netptr->newxmax ) { netptr->newxmax = x ; netptr->newRnum = 1 ; } else if( x == netptr->newxmin ) { netptr->newLnum++ ; if( x == netptr->newxmax ) { netptr->newRnum++ ; } } else if( x == netptr->newxmax ) { netptr->newRnum++ ; } if( y > netptr->newymax ) { netptr->newymax = y ; netptr->newTnum = 1 ; } else if( y == netptr->newymax ) { netptr->newTnum++ ; } break ; case 3 : /* R , T false */ if( x > netptr->newxmax ) { netptr->newxmax = x ; netptr->newRnum = 1 ; } else if( x == netptr->newxmax ) { netptr->newRnum++ ; } if( y > netptr->newymax ) { netptr->newymax = y ; netptr->newTnum = 1 ; } else if( y == netptr->newymax ) { netptr->newTnum++ ; } break ; case 4 : /* L , B , T false */ if( x < netptr->newxmin ) { netptr->newxmin = x ; netptr->newLnum = 1 ; } else if( x == netptr->newxmin ) { netptr->newLnum++ ; } if( y < netptr->newymin ) { netptr->newymin = y ; netptr->newBnum = 1 ; } else if( y > netptr->newymax ) { netptr->newymax = y ; netptr->newTnum = 1 ; } else if( y == netptr->newymin ) { netptr->newBnum++ ; if( y == netptr->newymax ) { netptr->newTnum++ ; } } else if( y == netptr->newymax ) { netptr->newTnum++ ; } break ; case 5 : /* B , T false */ if( y < netptr->newymin ) { netptr->newymin = y ; netptr->newBnum = 1 ; } else if( y > netptr->newymax ) { netptr->newymax = y ; netptr->newTnum = 1 ; } else if( y == netptr->newymin ) { netptr->newBnum++ ; if( y == netptr->newymax ) { netptr->newTnum++ ; } } else if( y == netptr->newymax ) { netptr->newTnum++ ; } break ; case 6 : /* L , T false */ if( x < netptr->newxmin ) { netptr->newxmin = x ; netptr->newLnum = 1 ; } else if( x == netptr->newxmin ) { netptr->newLnum++ ; } if( y > netptr->newymax ) { netptr->newymax = y ; netptr->newTnum = 1 ; } else if( y == netptr->newymax ) { netptr->newTnum++ ; } break ; case 7 : /* T false */ if( y > netptr->newymax ) { netptr->newymax = y ; netptr->newTnum = 1 ; } else if( y == netptr->newymax ) { netptr->newTnum++ ; } break ; case 8 : /* L , R , B false */ if( x < netptr->newxmin ) { netptr->newxmin = x ; netptr->newLnum = 1 ; } else if( x > netptr->newxmax ) { netptr->newxmax = x ; netptr->newRnum = 1 ; } else if( x == netptr->newxmin ) { netptr->newLnum++ ; if( x == netptr->newxmax ) { netptr->newRnum++ ; } } else if( x == netptr->newxmax ) { netptr->newRnum++ ; } if( y < netptr->newymin ) { netptr->newymin = y ; netptr->newBnum = 1 ; } else if( y == netptr->newymin ) { netptr->newBnum++ ; } break ; case 9 : /* R , B false */ if( x > netptr->newxmax ) { netptr->newxmax = x ; netptr->newRnum = 1 ; } else if( x == netptr->newxmax ) { netptr->newRnum++ ; } if( y < netptr->newymin ) { netptr->newymin = y ; netptr->newBnum = 1 ; } else if( y == netptr->newymin ) { netptr->newBnum++ ; } break ; case 10 : /* L , R false */ if( x < netptr->newxmin ) { netptr->newxmin = x ; netptr->newLnum = 1 ; } else if( x > netptr->newxmax ) { netptr->newxmax = x ; netptr->newRnum = 1 ; } else if( x == netptr->newxmin ) { netptr->newLnum++ ; if( x == netptr->newxmax ) { netptr->newRnum++ ; } } else if( x == netptr->newxmax ) { netptr->newRnum++ ; } break ; case 11 : /* R false */ if( x > netptr->newxmax ) { netptr->newxmax = x ; netptr->newRnum = 1 ; } else if( x == netptr->newxmax ) { netptr->newRnum++ ; } break ; case 12 : /* L , B false */ if( x < netptr->newxmin ) { netptr->newxmin = x ; netptr->newLnum = 1 ; } else if( x == netptr->newxmin ) { netptr->newLnum++ ; } if( y < netptr->newymin ) { netptr->newymin = y ; netptr->newBnum = 1 ; } else if( y == netptr->newymin ) { netptr->newBnum++ ; } break ; case 13 : /* B false */ if( y < netptr->newymin ) { netptr->newymin = y ; netptr->newBnum = 1 ; } else if( y == netptr->newymin ) { netptr->newBnum++ ; } break ; case 14 : /* L false */ if( x < netptr->newxmin ) { netptr->newxmin = x ; netptr->newLnum = 1 ; } else if( x == netptr->newxmin ) { netptr->newLnum++ ; } break ; } } } /* end wire_boundary2 */ static wire_boundary1( netptr ) NETBOXPTR netptr ; { PINBOXPTR pinptr ; INT x , y ; if( pinptr = netptr->pins ) { if( pinptr->flag == 1 ) { netptr->newxmin = netptr->newxmax = pinptr->newx ; netptr->newymin = netptr->newymax = pinptr->newy ; pinptr->flag = 0 ; } else { netptr->newxmin = netptr->newxmax = pinptr->xpos ; netptr->newymin = netptr->newymax = pinptr->ypos ; } } for( pinptr = pinptr->next ; pinptr ; pinptr = pinptr->next ) { if( pinptr->flag == 1 ) { x = pinptr->newx ; y = pinptr->newy ; pinptr->flag = 0 ; } else { x = pinptr->xpos ; y = pinptr->ypos ; } if( x < netptr->newxmin ) { netptr->newxmin = x ; } else if( x > netptr->newxmax ) { netptr->newxmax = x ; } if( y < netptr->newymin ) { netptr->newymin = y ; } else if( y > netptr->newymax ) { netptr->newymax = y ; } } } /* wire_boundary1 */ graywolf-0.1.4+20170307gite1bf319/src/twmc/upin.c000066400000000000000000000072701305746555600206520ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: upin.c DESCRIPTION:update pins on a cell CONTENTS: upin_test( termsptr, pos ) PINBOXPTR termptr ; MOVEBOXPTR pos ; upin_accept( termptr ) PINBOXPTR termptr ; DATE: Jan 30, 1988 REVISIONS: Jun 30, 1988 - added rel_pos for test. Oct 19, 1988 - added newhalfP update. Mar 16, 1989 - removed usoftpin.c and ufixpin.c and replaced with upin.c. Now one set of routines handle both softpins and hardpins. Aug 13, 1990 - moved relpos to yalecad/relpos.h Wed Jan 30 14:15:02 EST 1991 - removed relpos. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) upin.c version 3.4 1/30/91" ; #endif #include #include #include #define BREAK_PT2 6 upin_test( termptr, pos ) PINBOXPTR termptr ; MOVEBOXPTR pos ; { NETBOXPTR dimptr ; INT targetx, targety, orient ; /* get target position from Rotational record */ targetx = pos->xcenter ; targety = pos->ycenter ; orient = pos->orient ; for( ; termptr ; termptr = termptr->nextpin ) { netarrayG[ termptr->net ]->nflag = TRUE ; termptr->flag = TRUE ; /* rel position is a macro which calculates absolute pin */ /* location defined in relpos.h */ REL_POS( orient, termptr->newx, termptr->newy, /* result */ termptr->txpos, termptr->typos, /* cell relative */ targetx, targety ) ; /* cell center */ } } /* end upin_test */ upin_accept( termptr ) PINBOXPTR termptr ; { NETBOXPTR dimptr ; for( ; termptr ; termptr = termptr->nextpin ) { dimptr = netarrayG[ termptr->net ] ; dimptr->xmin = dimptr->newxmin ; dimptr->xmax = dimptr->newxmax ; dimptr->ymin = dimptr->newymin ; dimptr->ymax = dimptr->newymax ; dimptr->halfPx = dimptr->newhalfPx ; dimptr->halfPy = dimptr->newhalfPy ; termptr->xpos = termptr->newx ; termptr->ypos = termptr->newy ; if( dimptr->numpins >= BREAK_PT2 ) { dimptr->Lnum = dimptr->newLnum ; dimptr->Rnum = dimptr->newRnum ; dimptr->Bnum = dimptr->newBnum ; dimptr->Tnum = dimptr->newTnum ; } } return ; } /* end upin_accept */ graywolf-0.1.4+20170307gite1bf319/src/twmc/upinswap.c000066400000000000000000000107231305746555600215420ustar00rootroot00000000000000/* * Copyright (C) 1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: upinswap.c DESCRIPTION:place pins on the cell. CONTENTS: BOOL upinswap( a ) INT a ; DATE: Mar 30, 1990 - new vertion of pinswap code. REVISIONS: ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) upinswap.c version 3.3 9/5/90" ; #endif #include #include #include #include #define CURVERTICES FALSE BOOL upinswap( a ) INT a ; { CELLBOXPTR acellptr ; PINBOXPTR pin, atermptr ; SOFTBOXPTR spin ; INT cost, inst ; INT newtimepenalty, newtimepenal ; acellptr = cellarrayG[ a ] ; atermptr = acellptr->pinptr ; /* ------------ update the position of all pins ------------------- */ /* place pins using the current vertices for the cell */ placepin( a, CURVERTICES ) ; cost = funccostG ; /* reset set to mark nets that have changed position */ clear_net_set() ; cost += unet( atermptr ) ; newtimepenal = timingpenalG ; newtimepenal += calc_incr_time( a ) ; ASSERT(newtimepenal==dcalc_full_penalty(),"upinswap","Timing woes\n"); /* scale new timing penalty */ newtimepenalty = (INT) ( timeFactorG * (DOUBLE) newtimepenal ) ; if( acceptt( funccostG + timingcostG - cost - newtimepenalty )){ /* update current terminal positions from original positions */ inst = acellptr->cur_inst ; for( pin = atermptr ; pin ; pin = pin->nextpin ) { pin->txpos = pin->txpos_new ; pin->typos = pin->typos_new ; if( pin->type != HARDPINTYPE ){ pin->txpos_orig[inst] = pin->txpos ; pin->typos_orig[inst] = pin->typos ; } } upin_accept( atermptr ) ; update_time( a ) ; funccostG = cost ; timingcostG = newtimepenalty ; timingpenalG = newtimepenal ; /* debug function to check sanity of the pin positions */ D( "upinswap", check_pin(a) ) ; return (ACCEPT) ; } else { return (REJECT) ; } } /* end upinswap */ check_pin( a ) INT a ; { INT x, y, l, r, t, b; INT orient ; CELLBOXPTR acellptr ; PINBOXPTR pin ; acellptr = cellarrayG[a] ; regenorient( a, a ) ; orient = acellptr->orient ; l = acellptr->bounBox[orient]->l + acellptr->xcenter ; b = acellptr->bounBox[orient]->b + acellptr->ycenter ; r = acellptr->bounBox[orient]->r + acellptr->xcenter ; t = acellptr->bounBox[orient]->t + acellptr->ycenter ; for( pin = acellptr->pinptr ; pin ; pin = pin->nextpin ) { REL_POS( orient, x, y, pin->txpos, pin->typos, acellptr->xcenter, acellptr->ycenter ); if( x != pin->xpos ){ fprintf( stderr,"xpin != xpos \n" ) ; pin->xpos = x ; } if( y != pin->ypos ){ fprintf( stderr,"ypin != ypos \n" ) ; pin->ypos = y ; } if( x < l || x > r ){ fprintf( stderr,"pin outside bounding box\n" ) ; } if( y < b || b > t ){ fprintf( stderr,"pin outside bounding box\n" ) ; } } } /* end check_pin */ graywolf-0.1.4+20170307gite1bf319/src/twmc/usite1.c000066400000000000000000000124351305746555600211100ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: usite1.c DESCRIPTION:single cell move and/or orientation flip CONTENTS: BOOL usite1( ) DATE: Feb 3, 1988 REVISIONS: Feb 5, 1988 - changed old_apos, new_apos to global variables, old method remains commented out. Aug 25, 1988 - calls to ufixpin and usoftpin changed. Oct 21, 1988 - changed to sqrt of overlap penalty. Nov 25, 1988 - added timing driven code ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) usite1.c version 3.4 9/10/90" ; #endif #include #include BOOL usite1( /* old_apos, new_apos */ ) /* MOVEBOXPTR *old_apos, *new_apos ; */ { CELLBOXPTR acellptr ; PINBOXPTR anewtermptr ; MOVEBOXPTR pos ; /* temp pointer for easier access */ INT cost , newpenalty, newbinpenal, newtimepenalty, newtimepenal ; INT a, i ; INT oldBinX, oldBinY, array_limit, *oldCellList ; INT wire_chg, time ; DOUBLE delta_wire ; /* ----------------------------------------------------------------- global information is stored in element zero of position arrays set a's MOVEBOX record - new position records have been initialized in uloop(). */ a = new_apos0G->cell ; acellptr = cellarrayG[a] ; anewtermptr = acellptr->pinptr ; clear_net_set() ; /* reset set to mark nets that have changed position */ newbinpenal = binpenalG ; newbinpenal += overlap( /* old_aposG, new_aposG */ ) ; /* scale new penalty for feedback circuit */ newpenalty = (INT) ( lapFactorG * sqrt( (DOUBLE) newbinpenal ) ) ; upin_test( anewtermptr, new_apos0G ) ; cost = funccostG ; cost += unet( anewtermptr ) ; newtimepenal = timingpenalG ; newtimepenal += calc_incr_time( a ) ; ASSERT( newtimepenal == dcalc_full_penalty(),"usite1","Timing woes\n") ; /* scale new timing penalty */ newtimepenalty = (INT) ( timeFactorG * (DOUBLE) newtimepenal ) ; wire_chg = cost - funccostG ; if( acceptt( penaltyG - newpenalty - wire_chg + timingcostG - newtimepenalty )){ upin_accept( anewtermptr ) ; update_overlap( /* old_aposG */ ) ; update_time( a ) ; /* update new position and orientation of a cell */ acellptr->xcenter = new_apos0G->xcenter ; acellptr->ycenter = new_apos0G->ycenter ; acellptr->orient = new_apos0G->orient ; /* *** BEGIN UPDATE OF BIN CELL LIST *** */ oldBinX = SETBINX(old_apos0G->xcenter) ; oldBinY = SETBINY(old_apos0G->ycenter) ; oldCellList = binptrG[oldBinX][oldBinY]->cells ; /* do nothing if cell a remains in same bin */ if( oldCellList != newCellListG ){ /* add cell a to newcellList - check space */ array_limit = ++newCellListG[0] ; if( array_limit >= newbptrG->space ) { newbptrG->space += EXPCELLPERBIN ; /* need to worry about 2 info array positions */ /* the 2 is assumed to avoid a subtraction */ newCellListG = (INT *) Ysafe_realloc( newCellListG, (newbptrG->space) *sizeof(INT) ) ; } newCellListG[array_limit] = a ; /* remove a for other list */ /* find a 's position in array */ array_limit = oldCellList[0] ; for( i=1;i<=array_limit;i++ ){ if( oldCellList[i] == a ){ break ; } } /* assert i now has correct value of a */ ASSERT( oldCellList[i] == a, "usite1", "Problem in oldbin cell lists\n" ) ; if( i != array_limit ){ /* a's position is not last position swap with last */ oldCellList[ i ] = oldCellList[ array_limit ] ; } oldCellList[0]-- ; } /* *** END UPDATE OF BIN CELL LIST *** */ /* debug check */ ASSERT( checkbinList(), "usite1","We have a problem here \n") ; funccostG = cost ; penaltyG = newpenalty ; binpenalG = newbinpenal ; timingcostG = newtimepenalty ; timingpenalG = newtimepenal ; return (ACCEPT) ; } else { return (REJECT) ; } } /* end usite1 */ graywolf-0.1.4+20170307gite1bf319/src/twmc/usite2.c000066400000000000000000000212141305746555600211040ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: usite2.c DESCRIPTION:two cell flip and/or orientation change CONTENTS: BOOL usite2( ) DATE: Jan 30, 1988 REVISIONS: Feb 5, 1988 - changed old_apos, new_apos, old_bpos, new_bpos to global variables. Old method remains commented out. Aug 25, 1988 - calls to ufixpin and usoftpin changed. Oct 21, 1988 - changed to sqrt for overlap penalty. Nov 25, 1988 - added timing driven code. May 3, 1989 - added unet2 for two cell swaps. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) usite2.c version 3.4 9/10/90" ; #endif #include #include static INT acellS, bcellS, mod_cellS ; static CELLBOXPTR acellptrS , bcellptrS ; BOOL usite2( /* old_apos, new_apos, old_bpos, new_bpos */ ) /* MOVEBOXPTR *old_apos, *new_apos, *old_bpos, *new_bpos ; */ { PINBOXPTR anewtermptr , bnewtermptr ; MOVEBOXPTR pos ; /* temp pointer for easier access */ BINBOXPTR modptr ; INT cost , newpenalty, newbinpenal, newtimepenalty, newtimepenal ; INT oldBinX, oldBinY, limit, *oldCellList ; INT modBinX, modBinY, *modCellList ; INT i ; INT wire_chg ; DOUBLE delta_wire ; /* ----------------------------------------------------------------- global information is stored in element zero of position arrays new position records have been initialized in uloop(). */ acellS = new_apos0G->cell ; acellptrS = cellarrayG[acellS] ; anewtermptr = acellptrS->pinptr ; bcellS = new_bpos0G->cell ; bcellptrS = cellarrayG[bcellS] ; bnewtermptr = bcellptrS->pinptr ; clear_net_set() ; /* reset set to mark nets that have changed position */ /* remove overlap so that pairwise exchange has better chance at low T*/ mod_cellS = 0 ; /* mod_cell_positions() ; */ /* save state of penalty */ newbinpenal = binpenalG ; /* adjust overlap penalty */ newbinpenal += overlap2( /* old_apos, new_apos, old_bpos, new_bpos */ ) ; /* scale newpenalty for feedback circuit */ newpenalty = (INT) ( lapFactorG * sqrt( (DOUBLE) newbinpenal ) ) ; upin_test( anewtermptr, new_apos0G ) ; upin_test( bnewtermptr, new_bpos0G ) ; cost = funccostG ; cost += unet2( anewtermptr, bnewtermptr ) ; wire_chg = cost - funccostG ; newtimepenal = timingpenalG ; newtimepenal += calc_incr_time2( acellS, bcellS ) ; ASSERT( newtimepenal == dcalc_full_penalty(),"usite2","Timing woes\n" ) ; /* scale new timing penalty */ newtimepenalty = (INT) ( timeFactorG * (DOUBLE) newtimepenal ) ; if( acceptt( penaltyG - newpenalty - wire_chg + timingcostG - newtimepenalty )){ upin_accept( anewtermptr ) ; upin_accept( bnewtermptr ) ; update_overlap2( /* old_aposG, old_bposG */ ) ; update_time2( acellS, bcellS ) ; /* update new position and orientation of a cell */ acellptrS->xcenter = new_apos0G->xcenter ; acellptrS->ycenter = new_apos0G->ycenter ; acellptrS->orient = new_apos0G->orient ; bcellptrS->xcenter = new_bpos0G->xcenter ; bcellptrS->ycenter = new_bpos0G->ycenter ; bcellptrS->orient = new_bpos0G->orient ; /* ************ BEGIN UPDATE OF BIN CELL LIST ************** */ if( !(mod_cellS) ){ /* a and b are swapped - assert old_apos0 has b new position */ /* and newcellList has new a position calculated in uloop.c */ oldBinX = SETBINX(old_apos0G->xcenter) ; oldBinY = SETBINY(old_apos0G->ycenter) ; oldCellList = binptrG[oldBinX][oldBinY]->cells ; /* do nothing if cell a remains in same bin */ if( oldCellList != newCellListG ){ /* swap a for b in oldcellList */ /* find a 's position in array */ limit = oldCellList[0] ; for( i=1;i<=limit;i++ ){ if( oldCellList[i] == acellS ){ oldCellList[i] = bcellS ; break ; } } /* assert i now has correct value of b */ ASSERT( oldCellList[i] == bcellS,"usite2", "Problem in oldbin cell lists\n" ) ; /* swap b for a in newcellList */ /* find a 's position in array */ limit = newCellListG[0] ; for( i=1;i<=limit;i++ ){ if( newCellListG[i] == bcellS ){ newCellListG[i] = acellS ; break ; } } /* assert i now has correct value of a */ ASSERT( newCellListG[i] == acellS,"usite2", "Problem in newbin cell lists\n" ) ; } } else if( mod_cellS == acellS ){ /* a's bin is modified by the moving cells apart */ oldBinX = SETBINX(old_apos0G->xcenter) ; oldBinY = SETBINY(old_apos0G->ycenter) ; oldCellList = binptrG[oldBinX][oldBinY]->cells ; modBinX = SETBINX(new_apos0G->xcenter) ; modBinY = SETBINY(new_apos0G->ycenter) ; modptr = binptrG[modBinX][modBinY] ; modCellList = modptr->cells ; /* add b to oldCellList - find a 's position in array */ limit = oldCellList[0] ; for( i=1;i<=limit;i++ ){ if( oldCellList[i] == acellS ){ oldCellList[i] = bcellS ; break ; } } /* assert i now has correct value of b */ ASSERT( oldCellList[i] == bcellS, "usite2", "Problem in oldbin cell lists\n"); /* delete b in newCellList */ limit = newCellListG[0] ; for( i=1;i<=limit;i++ ){ if( newCellListG[i] == bcellS ){ break ; } } ASSERT( newCellListG[i] == bcellS, "usite2", "Problem in newbin cell lists\n" ) ; if( i != limit ){ newCellListG[i] = newCellListG[ limit ] ; } newCellListG[0]-- ; /* now add a to modified bin */ limit = ++modCellList[0] ; if( limit >= modptr->space ){ modptr->space += EXPCELLPERBIN ; modCellList = (INT *) Ysafe_realloc( modCellList, modptr->space * sizeof(INT) ) ; } modCellList[limit] = acellS ; } else if( mod_cellS == bcellS ){ /* b's bin is modified by the moving cells apart */ oldBinX = SETBINX(old_apos0G->xcenter) ; oldBinY = SETBINY(old_apos0G->ycenter) ; oldCellList = binptrG[oldBinX][oldBinY]->cells ; modBinX = SETBINX(new_bpos0G->xcenter) ; modBinY = SETBINY(new_bpos0G->ycenter) ; modptr = binptrG[modBinX][modBinY] ; modCellList = modptr->cells ; /* add a to newCellList - find b 's position in array */ /* this delete's b's old position */ limit = newCellListG[0] ; for( i=1;i<=limit;i++ ){ if( newCellListG[i] == bcellS ){ newCellListG[i] = acellS ; break ; } } /* assert i now has correct value of a */ ASSERT( newCellListG[i] == acellS, "usite2", "Problem in newbin cell lists\n" ) ; /* delete a in oldCellList */ limit = oldCellList[0] ; for( i=1;i<=limit;i++ ){ if( oldCellList[i] == acellS ){ break ; } } ASSERT( oldCellList[i] == acellS, "usite2", "Problem in oldbin cell lists\n" ) ; if( i != limit ){ oldCellList[i] = oldCellList[ limit ] ; } oldCellList[0]-- ; /* now add b to modified bin */ limit = ++modCellList[0] ; if( limit >= modptr->space ){ modptr->space += EXPCELLPERBIN ; modCellList = (INT *) Ysafe_realloc( modCellList, modptr->space * sizeof(INT) ) ; } modCellList[limit] = bcellS ; } /* ********** END UPDATE OF BIN CELL LIST ************** */ /* check that everything is ok */ ASSERT( checkbinList(), "usite2", "We have a problem at checkbinList()\n") ; funccostG = cost ; penaltyG = newpenalty ; binpenalG = newbinpenal ; timingcostG = newtimepenalty ; timingpenalG = newtimepenal ; return (ACCEPT) ; } else { return (REJECT) ; } } graywolf-0.1.4+20170307gite1bf319/src/twmc/usoftmove.c000066400000000000000000000045271305746555600217300ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: usoftmove.c DESCRIPTION:pin move routine. CONTENTS: BOOL usoftmove( acellptr,UCpin,seq,firstNewSite,lastNewSite ) INT UCpin , seq , firstNewSite , lastNewSite ; CELLBOXPTR acellptr ; DATE: Jun 27, 1988 REVISIONS: Oct 21, 1988 - removed Hweight and Vweight fields. Mar 16, 1989 - rewrote data structure and move upin to usoftmove.c. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) usoftmove.c version 3.3 9/5/90" ; #endif #include #include #include /* ----------------------------------------------------------------- important global definitions - defined in custom.h used for feedback. INT overfillG, overpenalG ; DOUBLE pinFactorG ; */ graywolf-0.1.4+20170307gite1bf319/src/twmc/utemp.c000066400000000000000000000072401305746555600210260ustar00rootroot00000000000000/* * Copyright (C) 1988-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: utemp.c DESCRIPTION:outer loop of the simulated annealing algorithm. CONTENTS: utemp( ) DATE: Feb 5, 1988 REVISIONS: Dec 3, 1988 - added output info for timing. Dec 4, 1988 - moved output info to prnt_cost routine and updated arguments to savewolf. Feb 20,1989 - recoded annealing loop to make it easier to read. Mar 01,1989 - changed iter_countS to iteration a global. removed all static code. Mar 02,1989 - removed fuloop from code. Jun 21,1989 - added verbose switch to iteration number. Oct 14,1990 - added overlap iterations. Fri Jan 25 18:09:20 PST 1991 - removed unnecessary globals. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) utemp.c version 3.6 4/6/92" ; #endif #include #include #include utemp( attempts, multi_cell_moves ) INT attempts ; BOOL multi_cell_moves ; { INT i ; DOUBLE calc_lap_factor( P1(DOUBLE percentDone) ) ; /****************** main annealing loop ***************** */ while( iterationG < (INT) LASTTEMP ){ iterationG++ ; /* next iteration */ /* write iteration to the screen if not verbose */ if(!(verboseG )){ fprintf( stdout, "%3d ", iterationG ) ; if(!(iterationG % 15)){ fprintf( stdout, "\n" ) ; } fflush( stdout ) ; } uloop( attmaxG ) ; savewolf( FALSE ) ; /* don't force save */ } /* **** overlap penalty controller **** */ if( iterationG <= (INT) LASTTEMP ){ iterationG++ ; /* next iteration */ lapFactorG = calc_lap_factor( (DOUBLE) 3.0 ) ; funccostG = findcost() ; for( i = 1; i <= 3 ; i++ ){ uloop( attmaxG ) ; savewolf( FALSE ) ; /* don't force save */ iterationG++ ; /* next iteration */ } } /*************** end main annealing loop ***************** */ /* * * WE ARE FINISHED * */ prnt_cost("\nPLACEMENT RESULTS AFTER ANNEALING ARE:\n" ) ; OUT2("MAX NUMBER OF ATTEMPTED FLIPS PER T:%8d\n", attmaxG ) ; /* verify incremental and current costs */ D( "twmc/utemp", checkcost() ) ; return ; } /* end utemp */ graywolf-0.1.4+20170307gite1bf319/src/twmc/watesides.c000066400000000000000000000105701305746555600216640ustar00rootroot00000000000000/* * Copyright (C) 1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: watesides.c DESCRIPTION:weight the tile sides for wire estimation. CONTENTS: watesides DATE: Mon Feb 4 02:25:16 EST 1991 - added header and new wire estimator. REVISIONS: ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) watesides.c version 3.5 2/4/91" ; #endif #include #include watesides( ptr, pSideArray ) CELLBOXPTR ptr ; PSIDEBOX *pSideArray ; { TILEBOXPTR tileptr ; INT side , left , right , bottom , top ; for( tileptr = ptr->tiles;tileptr; tileptr = tileptr->next ) { left = ptr->xcenter + tileptr->left ; tileptr->lweight = -1.0 ; for( side = 1 ; side <= ptr->numsides ; side++ ) { if( pSideArray[side].vertical == 1 ) { if( pSideArray[side].position == left ) { if( new_wire_estG ){ tileptr->lweight = pSideArray[side].pincount + 1 ; if( tileptr->lweight == 0.0 ){ tileptr->lweight = 1.0 ; } } else { tileptr->lweight = pSideArray[side].pincount / (DOUBLE) pSideArray[side].length ; } ptr->vertices->numpins[side] = (FLOAT) pSideArray[side].pincount; } } } right = ptr->xcenter + tileptr->right ; tileptr->rweight = -1.0 ; for( side = 1 ; side <= ptr->numsides ; side++ ) { if( pSideArray[side].vertical == 1 ) { if( pSideArray[side].position == right ) { if( new_wire_estG ){ tileptr->rweight = pSideArray[side].pincount + 1 ; if( tileptr->rweight == 0.0 ){ tileptr->rweight = 1.0 ; } } else { tileptr->rweight = pSideArray[side].pincount / (DOUBLE) pSideArray[side].length ; } ptr->vertices->numpins[side] = (FLOAT) pSideArray[side].pincount; } } } bottom = ptr->ycenter + tileptr->bottom ; tileptr->bweight = -1.0 ; for( side = 1 ; side <= ptr->numsides ; side++ ) { if( pSideArray[side].vertical == 0 ) { if( pSideArray[side].position == bottom ) { if( new_wire_estG ){ tileptr->bweight = pSideArray[side].pincount + 1 ; if( tileptr->bweight == 0.0 ){ tileptr->bweight = 1.0 ; } } else { tileptr->bweight = pSideArray[side].pincount / (DOUBLE) pSideArray[side].length ; } ptr->vertices->numpins[side] = (FLOAT) pSideArray[side].pincount; } } } top = ptr->ycenter + tileptr->top ; tileptr->tweight = -1.0 ; for( side = 1 ; side <= ptr->numsides ; side++ ) { if( pSideArray[side].vertical == 0 ) { if( pSideArray[side].position == top ) { if( new_wire_estG ){ tileptr->tweight = pSideArray[side].pincount + 1 ; if( tileptr->tweight == 0.0 ){ tileptr->tweight = 1.0 ; } } else { tileptr->tweight = pSideArray[side].pincount / (DOUBLE) pSideArray[side].length ; } ptr->vertices->numpins[side] = (FLOAT) pSideArray[side].pincount; } } } } return ; } graywolf-0.1.4+20170307gite1bf319/src/twmc/window.c000066400000000000000000000267571305746555600212210ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: window.c DESCRIPTION:new window limiter routines due to Jimmy Lamm CONTENTS: DOUBLE eval_ratio(percentWindow) DOUBLE *percentWindow ; init_control() pick_position(INT *, INT *, int, int) update_control(a) fix_window() update_window_size( iteration ) DOUBLE iteration ; DATE: Feb 29, 1988 REVISIONS: Apr 23, 1988 - added fix_window for low temp anneal Oct 21, 1988 - changed steps per cell and add graph func. Oct 26, 1988 - add pick_neighborhood and fixed bug in pick_position. Nov 20, 1988 - fixed chip aspect ratio. Jan 15, 1989 - added update_window_size, and new eval ratio for curve-fit controller. Jan 29, 1989 - changed to YmsgG. Mar 02, 1989 - move temp defintions to temp.h Apr 09, 1989 - fixed bug in pick_position and pick_neighborhood so that cells can't jump outside region. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) window.c version 3.6 11/26/90" ; #endif #include #include #include #define AC0 0.90 /*** 0.75 ***/ #define AC1 0.44 /*** 0.44 ***/ #define AC2 0.06 /*** 0.08 ***/ #define PT1 0.15 /*** 0.15 ***/ #define PT2 0.52 /*** 0.52 ***/ #define PT3 1.00 /*** 1.00 ***/ #define LAC1 (log(AC1)) #define LAC2 (log(AC2)) #define STEPSPERCEL 0.01 /* was 0.01 */ #define TABLIMIT 4096 /*** simple table lookup for log. ***/ #define TABSHIFT 19 #define TABMASK 0xfff #define TABOFFSET 0x40000 #define RANDFACT (1.0 / INT_MAX) #define PICK_INT(l,u) (((l)<(u)) ? ((RAND % ((u)-(l)+1))+(l)) : (l)) static DOUBLE xadjustmentS,xalS,min_xalphaS,max_xalphaS;/** x control **/ static DOUBLE yadjustmentS,yalS,min_yalphaS,max_yalphaS;/** y control **/ static DOUBLE total_stepS; static DOUBLE log_tabS[TABLIMIT]; static DOUBLE tauXS, tauYS ; /* exp. decay time constants for window */ DOUBLE eval_ratio( iteration ) INT iteration ; { if( iteration >= TURNOFFT ){ return( (DOUBLE) 1.0 ) ; } else if( iteration < 0 ){ return( (DOUBLE) 0.0 ) ; } else { return( (DOUBLE) iteration / TURNOFFT ) ; } } /* ***************************************************************** init_control - initialize range limiter. */ init_control(first) BOOL first ; { INT i; DOUBLE area ; #define FRACTION 0.10 /*** initialize move generation parameters ***/ /* minxspan = mean_width + 3 sigma variation */ area = mean_cellAreaG + 3 * dev_cellAreaG ; /*** average min. window size ***/ min_xalphaS = 0.5 * sqrt( area / chipaspectG ) ; min_yalphaS = 0.5 * sqrt( chipaspectG * area ) ; min_xalphaS = MIN( min_xalphaS, FRACTION * (DOUBLE) bdxlengthG ) ; min_yalphaS = MIN( min_yalphaS, FRACTION * (DOUBLE) bdylengthG ) ; OUT2( "min_xalpha:%4.2lf\n", min_xalphaS ) ; OUT2( "min_yalpha:%4.2lf\n", min_yalphaS ) ; if (init_accG >= 0.44) { max_xalphaS = bdxlengthG; /*** average max. window size ***/ max_yalphaS = bdylengthG; /*** average max. window size ***/ } else { max_xalphaS = min_xalphaS; /*** no adjustments ***/ max_yalphaS = min_yalphaS; } total_stepS = STEPSPERCEL * numcellsG; xadjustmentS = (max_xalphaS - min_xalphaS) / total_stepS; yadjustmentS = (max_yalphaS - min_yalphaS) / total_stepS; xalS = max_xalphaS; yalS = max_yalphaS; if (first) { xalS = max_xalphaS; yalS = max_yalphaS; /* determine tauXS */ tauXS = - log( (min_xalphaS/max_xalphaS)) / (MEDTEMP - HIGHTEMP) ; tauYS = - log( (min_yalphaS/max_yalphaS)) / (MEDTEMP - HIGHTEMP) ; } /*** prepare lookup table ***/ for (i=0; i> TABSHIFT) & TABMASK]; if (m & 0x10000){ n = -n; } n += ox; /* check for inside core */ if (n >= blocklG && n <= blockrG){ /* hate to use a goto here but it saves another test */ goto DONEX ; } } /* by default -we have failed. Use boundary */ if (n < blocklG) { if (ox > blockrG){ ox = blockrG; } else if (ox < blocklG){ ox = blocklG; } n = PICK_INT(blocklG,ox); } else if (n > blockrG) { if (ox < blocklG){ ox = blocklG; } else if (ox > blockrG){ ox = blockrG; } n = PICK_INT(ox,blockrG); } DONEX: *x = n; /* get exponentially distributed random number around old y */ for (i=0; i<2; i++) { m = RAND; n = -yalS * log_tabS[(m >> TABSHIFT) & TABMASK]; if (m & 0x10000){ n = -n; } n += oy; /* check for inside core */ if (n >= blockbG && n <= blocktG){ *y = n; return; } } /* if fail use boundary */ if (n < blockbG) { if (oy > blocktG){ oy = blocktG; } else if (oy < blockbG){ oy = blockbG; } n = PICK_INT(blockbG,oy); } else if (n > blocktG) { if (oy < blockbG){ oy = blockbG; } else if (oy > blocktG){ oy = blocktG; } n = PICK_INT(oy,blocktG); } *y = n; } /* ***************************************************************** pick_neighborhood - pick place to move within neighborhood while still using range limiter. */ pick_neighborhood(x,y,ox,oy,fixptr) INT *x,*y,ox,oy; FIXEDBOXPTR fixptr ; { register INT i,m,n; INT xjump, yjump ; #define DIV_2 >> 1 /* check if x range limiter is smaller than neighborhood */ if( xalS > fixptr->xspan ){ ox = fixptr->xcenter ; /* jump from center of neighborhood */ xjump = fixptr->xspan DIV_2 ; /* average jump half the xspan */ } else { /* we must use range limiter and jump from old coordinates */ xjump = xalS ; } /* get exponentially distributed random number around old x */ for (i=0; i<2; i++) { m = RAND; n = -xjump * log_tabS[(m >> TABSHIFT) & TABMASK]; if (m & 0x10000){ n = -n; } n += ox; /* check for inside neighborhood */ if (n >= fixptr->x1 && n <= fixptr->x2 ){ /* hate to use a goto here but it saves another test */ goto DONEX ; } } /* by default - we have failed. Use neighborhood boundary */ if (n < fixptr->x1 ) { if (ox > fixptr->x2 ){ ox = fixptr->x2 ; } else if (ox < fixptr->x1 ){ ox = fixptr->x1 ; } n = PICK_INT(fixptr->x1 ,ox); } else if (n > fixptr->x2 ) { if (ox < fixptr->x1 ){ ox = fixptr->x1 ; } else if (ox > fixptr->x2 ){ ox = fixptr->x2 ; } n = PICK_INT(ox,fixptr->x2 ); } DONEX: *x = n; /* check if y range limiter is smaller than neighborhood */ if( yalS > fixptr->yspan ){ oy = fixptr->ycenter ; /* jump from center of neighborhood */ yjump = fixptr->yspan DIV_2 ; /* average jump half the yspan */ } else { /* we must use range limiter and jump from old coordinates */ yjump = yalS ; } /* get exponentially distributed random number around old y */ for (i=0; i<2; i++) { m = RAND; n = -yjump * log_tabS[(m >> TABSHIFT) & TABMASK]; if (m & 0x10000){ n = -n; } n += oy; /* check for inside core */ if (n >= fixptr->y1 && n <= fixptr->y2){ *y = n; return; } } /* if fail use neighborhood boundary */ if (n < fixptr->y1) { if (oy > fixptr->y2){ oy = fixptr->y2; } else if (oy < fixptr->y1){ oy = fixptr->y1; } n = PICK_INT(fixptr->y1,oy); } else if (n > fixptr->y2) { if (oy < fixptr->y1){ oy = fixptr->y1; } else if (oy > fixptr->y2){ oy = fixptr->y2; } n = PICK_INT(oy,fixptr->y2); } *y = n; } /* end pick_neighborhood */ update_window_size( iteration ) DOUBLE iteration ; { if( iteration <= HIGHTEMP ){ xalS = max_xalphaS ; yalS = max_yalphaS ; } else if( iteration <= MEDTEMP ){ /* exponential decay xal and yal */ /* -------------------------------------------------------- xal = max_xalpha * exp( - tauXS * ( iteration - HIGHTEMP )) yal = max_yalpha * exp( - tauYS * ( iteration - HIGHTEMP )) -------------------------------------------------------- */ xalS = yalS = iteration - HIGHTEMP ; xalS *= - tauXS ; xalS = max_xalphaS * exp( xalS ) ; yalS *= - tauYS ; yalS = max_yalphaS * exp( yalS ) ; } else { /* low temp */ xalS = min_xalphaS ; yalS = min_yalphaS ; } /* OUT5(" xal = %4.2le yal = %4.2le stepsG = %4.2le T=%4.2le\n", xalS, yalS, stepsG, TG ); */ } fix_window() { /*** set window to minimum for low temp anneal ***/ xalS = min_xalphaS; yalS = min_yalphaS; } /* ***************************************************************** save_window - save window parameters for restart */ /* static declaration for restoring state for low temp anneal */ static DOUBLE ws_xalS; static DOUBLE ws_yalS; static DOUBLE ws_ratioS ; save_window( fp ) FILE *fp ; { if( fp ){ /* if a file pointer is given write to file */ fprintf(fp,"# window parameters:\n") ; fprintf(fp,"%f %f %f\n",xalS,yalS,ratioG ); } else { /* otherwise save in memory */ ws_xalS = xalS ; ws_yalS = yalS ; ws_ratioS = ratioG ; } } /* ***************************************************************** read_window - read window parameters for restart */ INT read_window( fp ) FILE *fp ; { INT errors = 0 ; if( fp ){ /* if file pointer given restore from file */ fscanf(fp,"%[ #:a-zA-Z]\n",YmsgG ); /* throw away comment */ fscanf(fp,"%lf %lf %lf\n",&xalS,&yalS,&ratioG); /* try to detect errors */ if( xalS < 0.0 ){ M(ERRMSG,"read_window","Restart file: xal negative\n") ; errors++ ; } if( yalS < 0.0 ){ M(ERRMSG,"read_window","Restart file: yal negative\n") ; errors++ ; } if( ratioG < 0.0 ){ M(ERRMSG,"read_window","Restart file: ratio negative\n") ; errors++ ; } if( ratioG > 1.0 ){ M(ERRMSG,"read_window","Restart file: ratio > 1\n") ; errors++ ; } } else { /* restore from memory */ xalS = ws_xalS ; yalS = ws_yalS ; ratioG = ws_ratioS ; } return(errors) ; } /* end read_window */ graywolf-0.1.4+20170307gite1bf319/src/twmc/wirecosts.c000066400000000000000000000100331305746555600217100ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: wirecosts.c DESCRIPTION:Examines wire cost more closely. LimitNets is the wirelength of nets which are in the cost function, that is their skip field in NETBOXPTR is FALSE. WithPads is the wirelength including all connections and withOutPads is the wirelength including the skip nets but neglecting pad connections. CONTENTS: DATE: Apr 27, 1989 - added heading and added limitnets calc. REVISIONS: ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) wirecosts.c version 3.3 9/5/90" ; #endif #include #include wirecosts() { NETBOXPTR dimptr ; PINBOXPTR pinptr ; INT limitNets, withPads , withOutPads ; INT x , y , xmin , xmax , ymin , ymax , net ; INT cell, celltype, bbox ; withPads = 0 ; withOutPads = 0 ; limitNets = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[net] ; xmin = 0 ; xmax = 0 ; ymin = 0 ; ymax = 0 ; for( pinptr = dimptr->pins ;pinptr;pinptr = pinptr->next ) { cell = pinptr->cell ; celltype = cellarrayG[cell]->celltype ; if( celltype == PADCELLTYPE || celltype == PADGROUPTYPE ){ continue ; } xmin = xmax = pinptr->xpos ; ymin = ymax = pinptr->ypos ; pinptr = pinptr->next ; break ; } for( ; pinptr ; pinptr = pinptr->next ) { cell = pinptr->cell ; celltype = cellarrayG[cell]->celltype ; if( celltype == PADCELLTYPE || celltype == PADGROUPTYPE ){ continue ; } x = pinptr->xpos ; y = pinptr->ypos ; if( x < xmin ) { xmin = x ; } else if( x > xmax ) { xmax = x ; } if( y < ymin ) { ymin = y ; } else if( y > ymax ) { ymax = y ; } } withOutPads += (xmax - xmin) + (ymax - ymin) ; dimptr = netarrayG[net] ; pinptr = dimptr->pins ; xmin = 0 ; xmax = 0 ; ymin = 0 ; ymax = 0 ; if( pinptr ) { xmin = xmax = pinptr->xpos ; ymin = ymax = pinptr->ypos ; pinptr = pinptr->next ; } for( ; pinptr ; pinptr = pinptr->next ) { x = pinptr->xpos ; y = pinptr->ypos ; if( x < xmin ) { xmin = x ; } else if( x > xmax ) { xmax = x ; } if( y < ymin ) { ymin = y ; } else if( y > ymax ) { ymax = y ; } } withPads += bbox = (xmax - xmin) + (ymax - ymin) ; if(!(dimptr->skip)){ limitNets += bbox ; } } OUT1("Wirelength:\n") ; OUT2("\tAll nets :%d\n", withPads ) ; OUT2("\tLimited nets :%d\n", limitNets ) ; OUT2("\tAll nets without pads:%d\n", withOutPads ) ; return ; } graywolf-0.1.4+20170307gite1bf319/src/twmc/wireest.c000066400000000000000000000236301305746555600213570ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: wireest.c DESCRIPTION:wire estimator routines. Uses tent function. CONTENTS: wireestx. Uses tent function. DATE: Feb 19, 1988 Aug 24, 1988 - thanks to Joy Chhugini and Anirudh Mathuria for hints on simplifying logic of wire estimator code. Four calls to this procedure are reduced to one call. REVISIONS: Mar 29, 1989 - changed tileptr argument to pos. Mon Feb 4 02:26:14 EST 1991 - added new wire estimator that uses SVD algorithm. Thu Mar 7 01:49:31 EST 1991 - now save wireestimation parameters. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) wireest.c version 3.6 3/7/91" ; #endif #include #include #ifdef MACRO #define CHECK_ROUTING( routing ) \ if( routing < 0 ){ \ M( WARNMSG, "check_routing", "Routing negative - taking ABS\n"); \ routing = - routing ; \ } #else #define CHECK_ROUTING( routing ) check_routing( &(routing) ) #endif #define ROUTING( x, y, numpins ) \ C0S + (C1S + C2S * x ) * x + (C3S + C4S * y ) * y + C5S * numpins /* static definitions */ static DOUBLE C0S ; /* constant */ static DOUBLE C1S ; /* C1S * x */ static DOUBLE C2S ; /* C2S * x * x */ static DOUBLE C3S ; /* C3S * y */ static DOUBLE C4S ; /* C4S * y * y */ static DOUBLE C5S ; /* C5S * numpins */ static DOUBLE blocklS ; /* these are used to speed calculation */ static DOUBLE blockbS ; static DOUBLE bdxlengthS ; static DOUBLE bdylengthS ; static check_routing(); /*******************************************************************/ wireestxy( pos, xc, yc ) MOVEBOXPTR pos ; INT xc, yc ; { INT xs , xe , y ; INT x , ys , ye ; INT left , right , bottom , top ; DOUBLE factor ; right = pos->r += xc ; left = pos->l += xc ; bottom = pos->b += yc ; top = pos->t += yc ; if( left <= blockmxG ) { xs = left - blocklG ; } else { xs = blockrG - left ; } if( right <= blockmxG ) { xe = right - blocklG ; } else { xe = blockrG - right ; } if( xs < 0 ){ xs = 0 ; } if( xe < 0 ) { xe = 0 ; } /************************************/ if (bottom <= top) { if (top <= blockmyG) { ys = bottom - blockbG ; if( ys < 0 ){ ys = 0 ; } ye = top - blockbG ; if( ye < 0 ){ ye = 0 ; } y = ye ; } else { ye = blocktG - top ; if( ye < 0 ){ ye = 0 ; } if (bottom>= blockmyG) { ys = blocktG - bottom ; if( ys < 0 ){ ys = 0 ; } y = ys ; } else { ys = bottom - blockbG ; if( ys < 0 ){ ys = 0 ; } y = halfYspanG ; } } } else { if (bottom <= blockmyG) { ys = bottom - blockbG ; if( ys < 0 ){ ys = 0 ; } ye = top - blockbG ; if( ye < 0 ){ ye = 0 ; } y = blocktG - bottom ; if( y < 0 ){ y = 0 ; } } else { ys = blocktG - bottom ; if( ys < 0 ){ ys = 0 ; } if (top >= blockmyG) { ye = blocktG - top ; if( ye < 0 ){ ye = 0 ; } y = top - blockbG ; if( y < 0 ){ y = 0 ; } } else { ye = top - blockbG ; if( ye < 0 ){ ye = 0 ; } if( bottom - blockmyG <= blockmyG - top){ y = ys ; } else { y = ye ; } } } } /*************************************/ /* y <= ( ( deltaY * y + blockt ) */ y *= deltaY ; y += blocktG ; /* xs <= (xs * deltaX + blockrG) */ xs *= deltaX ; xs += blockrG ; /* xe <= (xe * deltaX + blockrG) */ xe *= deltaX ; xe += blockrG ; /* ----------------------------------------------------------------- Unfortunately we can't multiply the x's by y using integer multiplication because of possible wraparounds on large designs. Instead we must multiply y in following statement. xs *= y ; xe *= y ; ----------------------------------------------------------------- */ pos->l = pos->l - (INT) ( (DOUBLE) xs * (DOUBLE) y * wireFactorXG * pos->lw ); pos->r = pos->r + (INT) ( (DOUBLE) xe * (DOUBLE) y * wireFactorXG * pos->rw ); if( right >= blockmxG && left <= blockmxG ) { x = halfXspanG ; } else if( ABS(left - blockmxG) <= ABS(right - blockmxG) ) { x = blockrG - left ; if( x < 0 ) { x = 0 ; } } else { x = right - blocklG ; if( x < 0 ) { x = 0 ; } } /* x <= ( ( deltaX * x + blockrG ) */ x *= deltaX ; x += blockrG ; /* ys <= (ys * deltaY + blocktG) */ ys *= deltaY ; ys += blocktG ; /* ye <= (ye * deltaY + blocktG) */ ye *= deltaY ; ye += blocktG ; /* ----------------------------------------------------------------- See above comment. ys *= x ; ye *= x ; ----------------------------------------------------------------- */ pos->b = pos->b - (INT) ( (DOUBLE) ys * (DOUBLE) x * wireFactorYG * pos->bw ); pos->t = pos->t + (INT) ( (DOUBLE) ye * (DOUBLE) x * wireFactorYG * pos->tw ); return ; } /* end wireestxy */ /*********************************************************************/ wireestxy2( pos, xc, yc ) MOVEBOXPTR pos ; INT xc, yc ; { DOUBLE l, r, b, t ; /* four sides of the tile */ DOUBLE xave, yave ; /* average of a tile side */ INT routing ; /* amount of routing estimate for side */ pos->r += xc ; pos->l += xc ; pos->b += yc ; pos->t += yc ; /* check to see if we have a standard cell cluster */ if( pos->lw < 0 || bdxlengthS <= 1.0 ){ /* no more work to do */ return ; } l = ( (DOUBLE) pos->l - blocklS ) / bdxlengthS ; if( l < 0.0 ) l = 0.0 ; if( l > 1.0 ) l = 1.0 ; r = ( (DOUBLE) pos->r - blocklS ) / bdxlengthS ; if( r < 0.0 ) r = 0.0 ; if( r > 1.0 ) r = 1.0 ; b = ( (DOUBLE) pos->b - blockbS ) / bdylengthS ; if( b < 0.0 ) b = 0.0 ; if( b > 1.0 ) b = 1.0 ; t = ( (DOUBLE) pos->t - blockbS ) / bdylengthS ; if( t < 0.0 ) t = 0.0 ; if( t > 1.0 ) t = 1.0 ; xave = (l + r) / 2.0 ; yave = (b + t) / 2.0 ; /* now add the routing to the tile */ routing = (INT) ROUTING( l, yave, pos->lw ) ; CHECK_ROUTING( routing ) ; pos->l -= routing ; routing = (INT) ROUTING( r, yave, pos->rw ) ; CHECK_ROUTING( routing ) ; pos->r += routing ; routing = (INT) ROUTING( xave, b, pos->bw ) ; CHECK_ROUTING( routing ) ; pos->b -= routing ; routing = (INT) ROUTING( xave, t, pos->tw ) ; CHECK_ROUTING( routing ) ; pos->t += routing ; } /* end wireestxy2 */ BOOL read_wire_est( fp ) FILE *fp ; { INT max_pitch ; fprintf( fpoG, "\nSVD fit parameters found. Using:\n" ) ; HPI( fp, &C0S ) ; HPO( fpoG, C0S ) ; HPI( fp, &C1S ) ; HPO( fpoG, C1S ) ; HPI( fp, &C2S ) ; HPO( fpoG, C2S ) ; HPI( fp, &C3S ) ; HPO( fpoG, C3S ) ; HPI( fp, &C4S ) ; HPO( fpoG, C4S ) ; HPI( fp, &C5S ) ; HPO( fpoG, C5S ) ; /* now add the constant */ max_pitch = MAX( track_spacingXG, track_spacingYG ) ; C0S += (DOUBLE) max_pitch ; fprintf( fpoG, "\nConstant modified to:\n" ) ; HPO( fpoG, C0S ) ; return( TRUE ) ; } /* end read_wire_est */ resize_wire_params() { blocklS = (DOUBLE) blocklG ; blockbS = (DOUBLE) blockbG ; bdxlengthS = (DOUBLE) bdxlengthG ; bdylengthS = (DOUBLE) bdylengthG ; } /* end resize_wire_params */ static check_routing( routing ) INT *routing ; { if( *routing < 0 ){ /* M( WARNMSG, "check_routing", "Routing negative - taking ABS\n"); *routing = - *routing ; */ *routing = 0.0 ; } }/* end check_routing */ /* ***************************************************************** save_wireest - save wireest parameters for restart */ save_wireest( fp ) FILE *fp ; { fprintf(fp,"# wireest parameters:\n") ; HPO( fp, C0S ) ; HPO( fp, C1S ) ; HPO( fp, C2S ) ; HPO( fp, C3S ) ; HPO( fp, C4S ) ; HPO( fp, C5S ) ; } /* end save_wireest */ /* ***************************************************************** read_wireest - read wireest parameters for restart */ INT read_wireest( fp ) FILE *fp ; { INT error = 0 ; fscanf(fp,"%[ #:a-zA-Z]\n",YmsgG ); /* throw away comment */ HPI( fp, &C0S ) ; HPI( fp, &C1S ) ; HPI( fp, &C2S ) ; HPI( fp, &C3S ) ; HPI( fp, &C4S ) ; HPI( fp, &C5S ) ; return(error) ; } /* end read_wireest */ graywolf-0.1.4+20170307gite1bf319/src/twmc/wireratio.c000066400000000000000000000251671305746555600217110ustar00rootroot00000000000000/* * Copyright (C) 1991-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: wireratio.c DESCRIPTION:This file contains routines for analyzing random to optimal wire ratio. CONTENTS: wireratio DATE: Tue Jan 15 20:54:36 PST 1991 REVISIONS: Fri Jan 25 18:15:36 PST 1991 - added numpins to equations untested at this time. Mon Feb 4 02:27:16 EST 1991 - working SVD fit algorithm that also checks for small cases. Thu Feb 7 00:22:56 EST 1991 - last solution for small cases didn't resize memory properly. Wed May 1 19:18:55 EDT 1991 - added switchbox field so we can ignore these areas during wire estimation. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) wireratio.c version 3.9 3/10/92" ; #endif #include #include #include #include #include #include #include gsl_matrix_disp( mptr, rows, cols ) gsl_matrix *mptr ; int rows, cols; { INT i, j ; for( i=0; i < rows; i++ ){ for( j=0; j < cols; j++ ){ fprintf( stderr, "% 4.4le ", gsl_matrix_get(mptr, i, j)) ; } fprintf( stderr, "\n" ) ; } fprintf( stderr, "\n" ) ; } /* end gsl_matrix_disp */ gsl_vector_disp( vptr, rows ) gsl_vector *vptr ; int rows; { INT i; for( i=0; i < rows; i++ ){ fprintf( stderr, "% 4.4le ", gsl_vector_get(vptr, i)) ; } fprintf( stderr, "\n" ) ; } /* end gsl_vector_disp */ static set_pins( A, center, loc, tile_side, sidepins, count ) gsl_matrix *A ; /* the matrix holding x y positions */ INT center ; INT loc ; INT tile_side ; INT *sidepins ; INT count ; { INT side ; /* the matching side for a given tile */ if( sidepins ){ side = find_tile_side( center, loc, tile_side ) ; if( side ){ gsl_matrix_set(A, count, 5, (DOUBLE) sidepins[side]); } else { M( ERRMSG, "adapt_wire_estimator", "Trouble finding pinside - defaulting to 0.\n" ) ; gsl_matrix_set(A, count, 5, 0.0); } } else { /* no pins for cell */ gsl_matrix_set(A, count, 5, 0.0); } } /* end set_pins */ adapt_wire_estimator() { INT i ; /* coefficient counter */ INT cell ; /* cell counter */ INT count ; /* count number of tiles */ INT xc, yc ; /* cell center */ INT *sidepins ; /* array holding #pins for side */ INT l, r, b, t ; /* the global position of the rtiles */ INT solved ; /* status of gsl_linalg_SV_solve */ INT *find_pin_sides() ; /* find number of pins on all sides */ char filename[LRECL] ; /* output the results of the SVD fit */ FILE *fp ; /* write out the results */ gsl_matrix *A ; /* the matrix holding x y positions */ gsl_vector *B ; /* the resulting global routing space*/ gsl_vector *Xret ; /* the solution to At*A*x = At*B */ DOUBLE x, y ; /* cell placement */ DOUBLE lf, rf, bf, tf ; /* the global position of the rtiles */ DOUBLE xlength, ylength;/* length of side */ DOUBLE xrouting, yrouting;/* routing space */ CELLBOXPTR cptr ; /* current pointer to cell */ RTILEBOXPTR rptr ; /* traverse tiles */ gsl_matrix *U ; gsl_matrix *V ; gsl_vector *S ; gsl_vector *work ; if(!(routingTilesG)){ return ; } /* first count the number of routing tiles */ count = 0 ; for( cell = 1 ; cell <= numcellsG; cell++ ){ for( rptr=routingTilesG[cell];rptr;rptr=rptr->next ){ if( rptr->switchbox ){ /* switchbox densities are not accurate discard */ continue ; } count++ ; } } if( count < 6 ){ /* now we can size the matrices */ A = gsl_matrix_alloc(6, 6); B = gsl_vector_alloc(6); } else { /* now we can size the matrices */ A = gsl_matrix_alloc(count, 6); B = gsl_vector_alloc(count); } /* initialize the pin counting routines */ init_wire_est() ; /* we eventually want to solve AtA x = At B */ /* now fill in the data in the matrices. */ xlength = (DOUBLE) (blockrG - blocklG) ; ylength = (DOUBLE) (blocktG - blockbG) ; count = 0 ; for( cell = 1 ; cell <= numcellsG; cell++ ){ cptr = cellarrayG[ cell ] ; xc = cptr->xcenter ; yc = cptr->ycenter ; sidepins = find_pin_sides( cell ) ; for( rptr=routingTilesG[cell];rptr;rptr=rptr->next ){ if( rptr->switchbox ){ /* switchbox densities are not accurate discard */ continue ; } gsl_matrix_set(A, count, 0, 1.0); /* for finding const */ l = xc + rptr->x1 ; r = xc + rptr->x2 ; b = yc + rptr->y1 ; t = yc + rptr->y2 ; xrouting = (DOUBLE)(r - l) ; yrouting = (DOUBLE)(t - b) ; lf = ( (DOUBLE)(l - blocklG ) ) / xlength ; if( lf < 0.0 ) lf = 0.0 ; rf = ( (DOUBLE)(r - blocklG ) ) / xlength ; bf = ( (DOUBLE)(b - blockbG ) ) / ylength ; if( bf < 0.0 ) bf = 0.0 ; tf = ( (DOUBLE)(t - blockbG ) ) / ylength ; switch( rptr->side ){ case TILEL: /* calculate x and y */ x = rf ; y = (bf + tf) / 2.0 ; set_pins( A, (b+t)/2, r, TILEL, sidepins, count ) ; gsl_matrix_set(A, count, 1, x); gsl_matrix_set(A, count, 2, x * x); gsl_matrix_set(A, count, 3, y); gsl_matrix_set(A, count, 4, y * y); gsl_vector_set(B, count, xrouting); break ; case TILET: /* calculate x and y */ x = (lf + rf) / 2.0 ; y = bf ; set_pins( A, (l+r)/2, b, TILET, sidepins, count ) ; gsl_matrix_set(A, count, 1, x); gsl_matrix_set(A, count, 2, x * x); gsl_matrix_set(A, count, 3, y); gsl_matrix_set(A, count, 4, y * y); gsl_vector_set(B, count, yrouting); break ; case TILER: /* calculate x and y */ x = lf ; y = (bf + tf) / 2.0 ; set_pins( A, (b+t)/2, l, TILER, sidepins, count ) ; gsl_matrix_set(A, count, 1, x); gsl_matrix_set(A, count, 2, x * x); gsl_matrix_set(A, count, 3, y); gsl_matrix_set(A, count, 4, y * y); gsl_vector_set(B, count, xrouting); break ; case TILEB: /* calculate x and y */ x = (lf + rf) / 2.0 ; y = tf ; set_pins( A, (l+r)/2, t, TILEB, sidepins, count ) ; gsl_matrix_set(A, count, 1, x); gsl_matrix_set(A, count, 2, x * x); gsl_matrix_set(A, count, 3, y); gsl_matrix_set(A, count, 4, y * y); gsl_vector_set(B, count, yrouting); break ; } /* end switch */ count++ ; } if( sidepins ){ Yvector_free( sidepins, 1, sizeof(INT) ) ; } } /* end loop on cells */ /* now make sure we have at least 6 rows */ if( count < 1 ){ M( ERRMSG, "adapt_wire_estimator", "Too few cells for TimberWolfMC. Must abort\n" ) ; YexitPgm(PGMFAIL) ; } else if( count < 6 ){ /* pad with zeros */ for( ; count < 6; count++ ){ for( i = 0; i < 6; i++ ){ gsl_matrix_set(A, count, i, gsl_matrix_get(A, 0, i)); } gsl_vector_set(B, count, gsl_vector_get(B, 0)); } } D( "TWMC/awe/init", fprintf( stderr,"\nA:\n" ) ; gsl_matrix_disp( A, count < 6 ? 6 : count, 6 ) ; fprintf( stderr,"\nB:\n" ) ; gsl_vector_disp( B, count < 6 ? 6 : count ) ; ) ; /* now solve using SVD */ U = gsl_matrix_alloc((count < 6) ? 6 : count, 6); V = gsl_matrix_alloc(6, 6); S = gsl_vector_alloc(6); work = gsl_vector_alloc(6); gsl_matrix_memcpy(U, A); gsl_linalg_SV_decomp(U, V, S, work); solved = gsl_linalg_SV_solve(U, V, S, B, Xret); if( solved ){ sprintf( filename, "%s.mest", cktNameG ) ; fp = TWOPEN( filename, "w", ABORT ) ; fprintf( fpoG, "\nThe results of the SVD fit are:\n" ) ; for( i = 0; i < 6; i++ ){ HPO( fp, gsl_vector_get(Xret, i)); HPO( fpoG, gsl_vector_get(Xret, i)); } TWCLOSE( fp ) ; } gsl_matrix_free(U); gsl_matrix_free(V); gsl_vector_free(S); gsl_vector_free(work); D( "TWMC/awe/answer", gsl_vector *AX ; /* multiply the answer */ gsl_vector *R ; gsl_matrix *Q ; INT c ; DOUBLE d ; DOUBLE dx ; AX = gsl_vector_alloc(count < 6 ? count : 6); R = gsl_vector_alloc(count < 6 ? count : 6); /* Compute AX = A * Xret */ for ( c = 0; c < (count < 6) ? 6 : count; c++ ) { d = 0.0; dx = gsl_vector_get(Xret, c); for ( i = 0; i < 6; i++ ) { d += gsl_matrix_get(A, c, i) * dx; gsl_set_vector(AX, c, d); } /* Compute R = AX - B */ gsl_vector_memcpy(R, AX); gsl_vector_sub( R, B ); Q = gsl_matrix_alloc( count, 7 ); for( c = 0; c < count; c++ ){ gsl_matrix_set(Q, c, 0, gsl_matrix_get(A, c, 1)) ; /* x */ gsl_matrix_set(Q, c, 1, gsl_matrix_get(A, c, 3)) ; /* y */ gsl_matrix_set(Q, c, 2, gsl_matrix_get(A, c, 5)) ; /* pins */ gsl_matrix_set(Q, c, 3, gsl_vector_get(B, c)) ; /* B */ gsl_matrix_set(Q, c, 4, gsl_matrix_get(AX, c, 0)) ; /* AX */ gsl_matrix_set(Q, c, 5, gsl_matrix_get(R, c, 0)) ; /* B - AX */ gsl_matrix_set(Q, c, 6, gsl_matrix_get(Q, c, 5) / gsl_matrix_get(Q, c, 3)) ; /* error */ } fprintf( stderr, "\n x, y, B, pins, AB, B - AX, error:\n"); gsl_matrix_disp( Q, count, 7 ) ; gsl_matrix_free(Q); gsl_vector_free(R); gsl_vector_free(AX); ) ; /* now done free the matrices */ gsl_matrix_free( A ); gsl_vector_free( B ); gsl_vector_free( Xret ); } /* end adapt_wire_estimator */ graywolf-0.1.4+20170307gite1bf319/src/twmc/ys.awk000066400000000000000000000012351305746555600206650ustar00rootroot00000000000000BEGIN { state = 1; pstate = 0 } $1 == "%%" { pstate = 1; next } $1 == "{" { state = 0 } $1 == "}" { state = 1; next } $1 == "#include" && pstate == 1 { exit } state == 1 && pstate == 1 { if( $2 == ":" ){ printf( "\n%s\t: ", $1 ) ; i = 3 ; while( i <= NF ){ printf( "%s ", $i ) ; i++ ; } printf( "\n" ) ; } else if( $1 == "|" ){ if( $NF == "error" || $(NF-1) == "error" ){ next ; } printf( "\t| " ) ; i = 2 ; while( i <= NF ){ printf( "%s ", $i ) ; i++ ; } printf( "\n" ) ; } else if( $NF > 0 ){ i = 1 ; printf( "\t\t" ) ; while( i <= NF ){ printf( "%s ", $i ) ; i++ ; } printf( "\n" ) ; } } END { } graywolf-0.1.4+20170307gite1bf319/src/twsc/000077500000000000000000000000001305746555600175335ustar00rootroot00000000000000graywolf-0.1.4+20170307gite1bf319/src/twsc/CMakeLists.txt000066400000000000000000000021071305746555600222730ustar00rootroot00000000000000 add_executable(TimberWolfSC acceptt.c coarseglb.c debug2.c findcostf.c globroute.c newtemp.c overlap.c readcell.c rowevener.c sortpin.c ucxxo1.c upair.c buildimp.c configpads.c debug.c findrcost.c graphics.c outcm.c parser.c readnets.c savewolf.c steiner.c ucxxo2.c urcost.c cell_width.c configure.c dimbox.c findunlap.c main.c outpins1.c paths.c readpar.c seagate.c uc0.c ucxxp.c utemp.c cglbroute.c countf.c feedest.c gateswap.c mergeseg.c outpins.c placepads.c reconfig.c sort.c ucxx1.c uloop.c xpickint.c changrid.c crossbus.c findcost.c globe.c netgraph.c output.c readblck.c rmoverlap.c sortpad.c ucxx2.c unlap.c ${CMAKE_SOURCE_DIR}/src/date/date.c) target_link_libraries(TimberWolfSC ${CMAKE_BINARY_DIR}/src/Ylib/libycadgraywolf.so) target_link_libraries(TimberWolfSC X11) target_link_libraries(TimberWolfSC m) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include .) install(TARGETS TimberWolfSC DESTINATION lib/graywolf/bin) graywolf-0.1.4+20170307gite1bf319/src/twsc/acceptt.c000066400000000000000000000117001305746555600213210ustar00rootroot00000000000000/* * Copyright (C) 1988-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: acceptt.c DESCRIPTION:accept routine used in simulated annealing CONTENTS: acceptt( INT ) DATE: Jan 30, 1988 REVISIONS: ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) acceptt.c version 4.7 4/2/92" ; #endif #include #include #include "main.h" #include "standard.h" #define MASK 0x3ff static DOUBLE table1S[1024] , table2S[1024] , table3S[1024] ; init_table() { INT i2 ; table1S[0] = 1.0 ; table2S[0] = 1.0 ; table3S[0] = 1.0 ; for( i2 = 1 ; i2 <= 1023 ; i2++ ) { table1S[ i2 ] = exp( -(DOUBLE) i2 / 8.0 ) ; table2S[ i2 ] = exp( -(DOUBLE) i2 / 8192.0 ) ; table3S[ i2 ] = exp( -(DOUBLE) i2 / 8388608.0 ) ; } } #ifdef DEBUG_CODE static FILE *fpS = NULL ; BOOL acceptt( d_wire, d_time, d_penal ) INT d_wire, d_time, d_penal ; { BOOL truth ; INT time ; extern INT aG ; time = d_time ; truth = acceptt2( d_wire, d_time, d_penal ) ; if(!fpS){ fpS = fopen( "newcost.dat", "w" ) ; } fprintf( fpS, "delta_cost:%10d w:%10d t:%10d p:%10d accept:%d cell:%d\n", d_costG, d_wire, time, d_penal, truth, aG ) ; fflush( fpS ) ; return( truth ) ; } #endif /* DEBUG_CODE */ /* ----------------------------------------------------------------- Acceptance function for the annealing algorithm. We expect all deltas to be of the form (old_cost - new_cost). If new_cost is less than the old_cost, the quantity will be positive and always acceptted. The variable d_costG lets the statistic accumulation code know of the change. ----------------------------------------------------------------- */ BOOL acceptt( d_wire, d_time, d_penal ) INT d_wire, d_time, d_penal ; { DOUBLE fred ; register unsigned fract ; /* d_time = (INT) ( 10.0 * timeFactorG * (DOUBLE) d_time ) ; */ d_time = (INT) ( timeFactorG * (DOUBLE) d_time ) ; d_costG = d_wire + d_time + d_penal ; if( d_costG >= 0 ){ return( TRUE ) ; } else { fred = ((DOUBLE) d_costG ) / TG ; } /* Now we are left with the uphill moves */ if( fred < -80.0 ) { return( FALSE ) ; } else if( fred > -0.0001 ) { if( 1.0 + fred > ( (DOUBLE) RAND / (DOUBLE)0x7fffffff ) ) { return( TRUE ) ; } else { return( FALSE ) ; } } else { fract = (INT)( -fred * 8388608.0 ) ; if( (table1S[ (fract >> 20) & MASK ] * table2S[ (fract >> 10) & MASK] * table3S[ fract & MASK ]) > ( (DOUBLE) RAND / (DOUBLE)0x7fffffff ) ) { return( TRUE ) ; } else { return( FALSE ) ; } } } /* end acceptt() */ /* ----------------------------------------------------------------- Greedy acceptance function for the annealing algorithm. We expect all deltas to be of the form (old_cost - new_cost). If new_cost is less than the old_cost, the quantity will be positive and always acceptted. ----------------------------------------------------------------- */ BOOL accept_greedy( d_wire, d_time, d_penal ) INT d_wire, d_time, d_penal ; { if( d_time == 0 ){ /* in the case the delta time is zero, use wirelength */ d_costG = d_wire + d_penal ; if( d_costG >= 0 ){ return( TRUE ) ; } else { return( FALSE ) ; } } else { /* If we have a timing constraint, use it */ d_costG = d_time + d_penal ; if( d_costG >= 0 ){ return( TRUE ) ; } else { return( FALSE ) ; } } } /* end accept_greedy() */ graywolf-0.1.4+20170307gite1bf319/src/twsc/buildimp.c000066400000000000000000000217441305746555600215140ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: buildimp.c DESCRIPTION:build implicit feedthrus. CONTENTS: buildimp( ) link_imptr( ) decide_boundary( ) fixwolf( ) addfeed( row , pos , feednum ) INT row , pos , feednum ; DATE: Mar 27, 1989 REVISIONS: Aug 30, 1989 - removed lastimp error. Tue Jan 15 20:31:33 PST 1991 - removed constant number of implicit feeds in a cell and instead made it dynamic. Wed Jan 16 14:26:44 PST 1991 - removed re_buildimp ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) buildimp.c (Yale) version 4.9 11/7/91" ; #endif #endif #include "standard.h" #include "groute.h" #include "feeds.h" static INT max_impfeed_in_cellS ; /* max no. of feeds in a cell */ INT comparetxpos() ; extern BOOL ignore_feedsG ; /* Treat feedthroughs as width 0 */ buildimp( ) { IPBOXPTR *impinptr , imptr ; CBOXPTR cellptr ; INT i , j , *Aray , row , count , total ; INT row_rite , longest_row , longest_blk_length ; INT *feasible_feednum ; /* first calculate the maximum implicit feeds in a cell */ max_impfeed_in_cellS = 0 ; for( i = 1; i <= numcellsG; i++ ){ cellptr = carrayG[ i ] ; count = 0 ; for( imptr = cellptr->imptr ; imptr ; imptr = imptr->next ) { count++ ; } if( count > max_impfeed_in_cellS ){ max_impfeed_in_cellS = count ; } } FeedInRowG = (INT *)Ysafe_calloc( numRowsG+1, sizeof(INT)) ; impinptr = (IPBOXPTR *) Ysafe_malloc( (max_impfeed_in_cellS+1)* sizeof(IPBOXPTR) ) ; impFeedsG = (IPBOXPTR *)Ysafe_malloc( ( numRowsG+1 ) * sizeof( IPBOXPTR )); feasible_feednum = (INT *)Ysafe_malloc( ( numRowsG+1 ) * sizeof( INT )); for( row = 1 ; row <= numRowsG ; row++ ) { total = 0 ; impFeedsG[row] = (IPBOXPTR)Ysafe_calloc( 1, sizeof(IPBOX)) ; Aray = pairArrayG[row] ; for( i = 1 ; i <= Aray[0] ; i++ ) { cellptr = carrayG[ Aray[i] ] ; count = 0 ; for( imptr = cellptr->imptr ; imptr ; imptr = imptr->next ) { impinptr[ ++count ] = imptr ; } if( count <= 1 ) { continue ; } Yquicksort( (char *)(impinptr+1) , count , sizeof(PINBOXPTR), comparetxpos ) ; if( cellptr->corient <= 1 ) { cellptr->imptr = impinptr[1] ; for( j = 1 ; j <= count - 1 ; j++ ) { impinptr[j]->next = impinptr[j+1] ; impinptr[j+1]->prev = impinptr[j] ; } impinptr[count]->next = NULL ; } else { cellptr->imptr = impinptr[count] ; for( j = count ; j >= 2 ; j-- ) { impinptr[j]->next = impinptr[j-1] ; impinptr[j-1]->prev = impinptr[j] ; } impinptr[1]->next = NULL ; } total += count ; } FeedInRowG[row] = total ; if( impFeedsG[row]->next != NULL ) { impFeedsG[row]->next->prev = NULL ; } } Ysafe_free( impinptr ) ; blk_most_riteG = 0 ; longest_row = 1 ; for( row = 1 ; row <= numRowsG ; row++ ) { cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; row_rite = cellptr->cxcenter + cellptr->tileptr->right ; if( row_rite > blk_most_riteG ) { blk_most_riteG = row_rite ; longest_row = row ; } } longest_blk_length = blk_most_riteG - blkleftG ; printf("\n block left edge is at %d\n", blkleftG ) ; printf(" the longest block length is %d\n" , longest_blk_length ) ; if( longest_blk_length < barrayG[ longest_row ]->desire ) { for( row = 1 ; row <= numRowsG ; row++ ) { cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; row_rite = cellptr->cxcenter + cellptr->tileptr->right ; feasible_feednum[row] = ( barrayG[row]->desire - row_rite ) / fdWidthG ; } } else { for( row = 1 ; row <= numRowsG ; row++ ) { cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; row_rite = cellptr->cxcenter + cellptr->tileptr->right ; if( fdWidthG > 0 ) { feasible_feednum[row] = ( blk_most_riteG - row_rite ) / fdWidthG ; } else { feasible_feednum[row] = ( blk_most_riteG - row_rite ) ; } } } /* for( row = 1 ; row <= numRowsG ; row++ ) { FeedInRowG[row] += feasible_feednum[row] ; } */ Ysafe_free( feasible_feednum ) ; } link_imptr( ) { INT i , row , *Aray ; CBOXPTR cellptr ; IPBOXPTR imptr , lastimp ; for( row = 1 ; row <= numRowsG ; row++ ) { Aray = pairArrayG[row] ; lastimp = impFeedsG[row] ; for( i = 1 ; i <= Aray[0] ; i++ ) { cellptr = carrayG[ Aray[i] ] ; if( cellptr->imptr == NULL ) { continue ; } imptr = cellptr->imptr ; lastimp->next = imptr ; imptr->prev = lastimp ; for( lastimp = imptr ; lastimp->next ; lastimp = lastimp->next); } } } decide_boundary( ) { INT row , fcx , fcl , lcx , lcr , lcl ; INT fcell , lcell , cell ; INT xstart , xstop ; numChansG = numRowsG + 1 ; xstart = INT_MAX ; xstop = INT_MIN ; for( row = 1 ; row <= numRowsG ; row++ ) { fcell = pairArrayG[row][1] ; lcell = pairArrayG[row][ pairArrayG[row][0] ] ; fcx = carrayG[fcell]->cxcenter ; fcl = carrayG[fcell]->tileptr->left ; lcx = carrayG[lcell]->cxcenter ; lcr = carrayG[lcell]->tileptr->right ; if( lcx + lcr > xstop ) { xstop = lcx + lcr ; } if( fcx + fcl < xstart ) { xstart = fcx + fcl ; } } for( cell = numcellsG + 1 ; cell <= lastpadG ; cell++ ) { lcx = carrayG[cell]->cxcenter ; lcl = carrayG[cell]->tileptr->left ; lcr = carrayG[cell]->tileptr->right ; if( lcx + lcr > xstop ) { xstop = lcx + lcr ; } if( lcx + lcl < xstart ) { xstart = lcx + lcl ; } } gxstartG = xstart ; gxstopG = xstop ; } fixwolf( ) { INT j , last_j ; maxtermG = implicit_feed_countG + fdthrusG + TotRegPinsG ; last_j = maxtermG + 2 * numRowsG + 2 ; carrayG = (CBOXPTR *)Ysafe_realloc( carrayG, (1 + numcellsG + numtermsG + 2 * numRowsG + fdthrusG) * sizeof(CBOXPTR) ); tearrayG = ( PINBOXPTR * ) Ysafe_realloc( tearrayG , ( last_j + 1 ) * sizeof(PINBOXPTR) ); for( j = TotRegPinsG + 1 ; j <= last_j ; j++ ) { tearrayG[j] = PINNULL ; } return ; } addfeed( row , pos , feednum ) INT row , pos , feednum ; { CBOXPTR cellptr ; TIBOXPTR tileptr ; IPBOXPTR imptr ; int locFdWidth = fdWidthG; /* This seems to work to remove explicit feedthroughs. . . */ if (ignore_feedsG) locFdWidth = 0; cellptr = ( CBOXPTR )Ysafe_malloc( sizeof( CBOX ) ) ; carrayG[ numcellsG + numtermsG + feednum ] = cellptr ; cellptr->cname = (char *) Ysafe_malloc( 16 * sizeof( char ) ) ; #ifdef FEED_INSTANCES sprintf( cellptr->cname , "twfeed%d", feednum ) ; #else sprintf( cellptr->cname , "twfeed" ) ; #endif cellptr->cclass = 0 ; if( barrayG[row]->borient == 2 ) { cellptr->corient = 1 ; } else { cellptr->corient = 0 ; } /* if( gate_array_special ) { ptr->orflag = 1 ; } else { ptr->orflag = 0 ; } */ cellptr->orflag = 0 ; cellptr->cxcenter = pos ; cellptr->cycenter = barrayG[row]->bycenter ; cellptr->cheight = barrayG[row]->bheight ; cellptr->clength = locFdWidth ; cellptr->cblock = row ; cellptr->numterms = 1 ; cellptr->pins = NULL ; cellptr->padptr = NULL ; cellptr->paths = NULL ; tileptr = cellptr->tileptr = ( TIBOXPTR )Ysafe_malloc( sizeof( TIBOX ) ); tileptr->left = -locFdWidth / 2 ; tileptr->right = locFdWidth + tileptr->left ; tileptr->bottom = -( barrayG[row]->bheight / 2 ) ; tileptr->top = barrayG[row]->bheight + tileptr->bottom ; cellptr->imptr = imptr = ( IPBOXPTR )Ysafe_calloc( 1,sizeof(IPBOX)); imptr->txpos = 0 ; imptr->xpos = pos ; imptr->cell = numcellsG + numtermsG + feednum ; imptr->terminal = TotRegPinsG + implicit_feed_countG + feednum ; imptr->pinname = (char *)Ysafe_malloc( 2 ) ; imptr->eqpinname = (char *)Ysafe_malloc( 2 ) ; sprintf( imptr->pinname, "%s", "1" ) ; sprintf( imptr->eqpinname, "%s", "2" ) ; return ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/cell_width.c000066400000000000000000000421641305746555600220240ustar00rootroot00000000000000/* * Copyright (C) 1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: calc_cells_width.c DESCRIPTION:calculates the width that encompasses most of the cells in the stdcell.cel file CONTENTS: calc_cell_width() DATE: July 26, 1991 ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) cell_width.c (Yale) version 1.1 9/27/91" ; #endif #endif #define PADKEYWORD "pad" #define RELATIVE_TO_CURPOS 1 /* #define MITLL */ #include #include "standard.h" #include "main.h" #include "config.h" #include "readpar.h" #include "parser.h" #include #include #include #include #define GREATER 1 #define LESS -1 #define EQUAL 0 #define MAX_CELL_LEN 10 extern INT extra_cellsG ; static INT compare_cell_length(); static read_pads(); /*--------------------------------------------------------------------------*/ /*------------ User defined print routine to print out the tree ------------*/ /*--------------------------------------------------------------------------*/ INT print_cell_name(c1) CBOXPTR c1; { return; } INT print_cell_length(c1) CBOXPTR c1; { return; } INT print_cell_pins(c1) CBOXPTR c1; { return ; } /*--------------------------------------------------------------------------*/ calc_cells_width() { FILE *fp; /*--- file pointer to stdcell.comp ---*/ INT cell, std_length, cell_length = 0 ; INT Ratio, sect, xpost,xminus, ypost, yminus, corient; INT alength, lower, upper, counter, longest_cell, cell_count, pp; DOUBLE avg_cell_length, deviation, percent, ratio, part_pin; YTREEPTR CellTree; CBOXPTR acellptr, dummy_box, Low_Key, Hi_Key, TestTree; PINBOXPTR termptr, netptr; EQ_NBOXPTR eptr; DBOXPTR dptr; char *aptr, *bptr, *cptr, *nptr; char *add_ptr = "-XTRA", *add_fptr = "-1"; INT xx , yy, zzz, r_term, last_term, pin_diff ; char layer; system("clear"); fprintf(stderr, "\n\n "); /*------ Memory allocation ------*/ dummy_box = (CBOXPTR) Ysafe_malloc( sizeof(CBOX) ); Low_Key = (CBOXPTR) Ysafe_malloc( sizeof(CBOX) ); Hi_Key = (CBOXPTR) Ysafe_malloc( sizeof(CBOX) ); TestTree = (CBOXPTR) Ysafe_malloc( sizeof(CBOX) ); /*------ Initialize and build the tree ------*/ CellTree = Yrbtree_init(compare_cell_length); for(cell = 1; cell <= numcellsG - extra_cellsG ; cell++){ acellptr = carrayG[cell]; /*----Get the pointer----*/ cell_length += carrayG[cell]->clength; /*---Total cell length---*/ Yrbtree_insert(CellTree, acellptr); /*----insert the cell-----*/ ASSERTNFAULT(Yrbtree_verify(CellTree),"calc_cells_name","bad tree"); } /* fprintf(stderr,"\n\n The RB-Tree of All The Cells Follows: \n\n "); Yrbtree_dump(CellTree,print_cell_name); printout the whole tree--*/ /*--------- Calculate the avarage cell length and deviation ---------*/ avg_cell_length = cell_length / (numcellsG - extra_cellsG) ; for(cell = 1; cell <= numcellsG - extra_cellsG ; cell++){ deviation += (carrayG[cell]->clength - avg_cell_length) * (carrayG[cell]->clength - avg_cell_length) ; } deviation = sqrt (deviation / (numcellsG - extra_cellsG) ) ; /*--------------------------------------------------------------------*/ fprintf(stderr, "\n------------------------------------\n"); fprintf(stderr, "The total number of cells = %d \n", --cell ); fprintf(stderr, "The avarage cell length = %f \n", avg_cell_length ); fprintf(stderr, "The cell deviation = %f", deviation ); fprintf(stderr,"\n------------------------------------"); /*-------------- Set the limits from "0" to "avg_cell_length" -------------*/ /* ----------- Get the count of all the cells within that range ------------ */ Low_Key->clength = 0; Hi_Key->clength = avg_cell_length; upper = Hi_Key->clength ; fprintf(stderr, "\n"); counter = 0; for(TestTree = (CBOXPTR) Yrbtree_interval(CellTree,Low_Key,Hi_Key,TRUE); TestTree ; TestTree = (CBOXPTR) Yrbtree_interval(CellTree,Low_Key,Hi_Key,FALSE)) { counter ++; } percent = (counter / (float) (numcellsG - extra_cellsG)) ; /*--------------------------------------------------------------------------*/ /*----------- For cells within the limit, clength = avg_cell_length --------*/ /*--------------------------------------------------------------------------*/ if (percent >= 0.6){ fprintf(stderr,"\n\nThe Total Number of Cells b/w the Lower Limit = %d",lower); fprintf(stderr,"\nand the Upper Limit = %d is ----->> %d \n", upper, counter); fprintf(stderr,"\nThe Percentage of Cells within the Limits = %f \n", 100*percent); fprintf(stderr,"\nPlease wait, conversion is being done ... \n"); Hi_Key->clength = avg_cell_length ; } else { while(percent < 0.6){ Hi_Key->clength += (INT) deviation / 20 ; upper = Hi_Key->clength ; counter = 0; for(TestTree = (CBOXPTR)Yrbtree_interval(CellTree,Low_Key,Hi_Key,TRUE); TestTree ; TestTree = (CBOXPTR)Yrbtree_interval(CellTree,Low_Key,Hi_Key,FALSE)) { counter ++; } percent = (counter / (float) (numcellsG - extra_cellsG)) ; }/*--- end while ---*/ for(TestTree = (CBOXPTR)Yrbtree_interval(CellTree,Low_Key,Hi_Key,TRUE); TestTree ; TestTree = (CBOXPTR)Yrbtree_interval(CellTree,Low_Key,Hi_Key,FALSE)) { TestTree->clength = Hi_Key->clength; } fprintf(stderr,"\n\nThe Total Number of Cell b/w the Lower Limit = %d",lower); fprintf(stderr,"\nand the Upper Limit = %d is ----->> %d \n", upper, counter); fprintf(stderr,"\nThe Percentage of Cells within the Limits = %f \n", 100*percent); fprintf(stderr,"\nPlease wait, conversion is being done ... \n"); }/*---- end else ----*/ std_length = Hi_Key->clength ; /*---------------------------------------------------------------*/ /*------------ Now copy the adjusted cells to a file ------------*/ /*---------------------------------------------------------------*/ fp = TWOPEN ("stdcell.comp", "w", ABORT); cell_count = 0; for(TestTree = (CBOXPTR)Yrbtree_interval(CellTree,Low_Key,Hi_Key,TRUE); TestTree ; TestTree = (CBOXPTR)Yrbtree_interval(CellTree,Low_Key,Hi_Key,FALSE)) { /*------ setting up the parameters to be passed on to the (fp) --------*/ TestTree->clength = Hi_Key->clength ; TestTree->tileptr->left = - Hi_Key->clength / 2 ; TestTree->tileptr->right = Hi_Key->clength / 2 ; cell_count ++; print_cell_length(TestTree); /*--- printout the cell's length ---*/ fprintf(fp,"cell %d %s \n", cell_count, TestTree->cname); fprintf(fp,"left %d right %d", TestTree->tileptr->left,TestTree->tileptr->right); fprintf(fp," bottom %d top %d \n", TestTree->tileptr->bottom,TestTree->tileptr->top); xx = 100 ; for(termptr = TestTree->pins; termptr; termptr = termptr->nextpin) { /*--- putting the y-pins on both sides ---*/ /*if ((termptr->typos[0] != 0) && (termptr->typos[1] == 0)) { termptr->typos[1] = - termptr->typos[0] ; } else if ((termptr->typos[0] == 0) && (termptr->typos[1] != 0)) { termptr->typos[0] = - termptr->typos[1] ; } else */ if ((termptr->typos[0] == 0) && (termptr->typos[1] == 0)){ termptr->typos[0] = TestTree->tileptr->top ; termptr->typos[1] = TestTree->tileptr->bottom ; } corient = TestTree->corient ; xpost = termptr->txpos[corient / 2] ; ypost = termptr->typos[corient % 2] ; /* xminus = termptr->txpos[1] ; yminus = termptr->typos[1] ; */ aptr = termptr->pinname ; aptr++ ; layer = *(aptr) ; aptr++ ; dptr = netarrayG[termptr->net] ; bptr = dptr->name ; eptr = termptr->eqptr ; if (eptr){ /*-- if the equivalent pin exists, print it out too --*/ cptr = eptr->pinname ; yminus = eptr->typos ; cptr++ ; layer = *(cptr) ; cptr++ ; fprintf(fp,"pin name %s signal %s layer %c %d %d \n", aptr , bptr, layer,xpost, -yminus); fprintf(fp," equiv name %s layer %c %d %d \n", cptr, layer, xpost, yminus); } else { fprintf(fp,"pin name %s signal %s layer %c %d %d \n", aptr , bptr, layer,xpost,ypost); } fprintf(fp,"pin name %d signal TW_PASS_THRU layer %c %d %d \n",xx,layer, xpost + 3 , ypost); fprintf(fp," equiv name %d layer %c %d %d \n",++xx,layer, xpost + 3 , - ypost); xx++ ; }/*--end for-loop--*/ fprintf(fp, "\n\n"); } longest_cell = MAX_CELL_LEN; /*----------- Get the maximum cell length now -------------*/ for(cell = 1; cell <= numcellsG - extra_cellsG ; cell++){ if (carrayG[cell]->clength > longest_cell){ longest_cell = carrayG[cell]->clength ; } } /*---------------------------------------------------------*/ /*--------------------------------------------------------------------------- ----------- Now adjust the length of the oversized cells ------------------ ---------------------------------------------------------------------------*/ if (percent != 1.0 ){ Low_Key->clength = ++Hi_Key->clength ; Hi_Key->clength = longest_cell; cell_count = 100; counter = 0; for(TestTree = (CBOXPTR)Yrbtree_interval(CellTree,Low_Key,Hi_Key,TRUE); TestTree ; TestTree = (CBOXPTR)Yrbtree_interval(CellTree,Low_Key,Hi_Key,FALSE)) { counter++; cell_count++ ; lower = TestTree->numterms ; upper = TestTree->clength ; cell = (numcellsG - extra_cellsG) + 1 ; /*--------------- find out how many times we have to break it ------------*/ /* TestTree->clength = lower + 1 ; left out for testing ---- */ if ( upper > std_length){ ratio = (float) TestTree->clength / std_length ; Ratio = (INT) ratio ; if((ratio - Ratio) > 0){ Ratio++ ; } pin_diff = TestTree->clength - std_length ; termptr = TestTree->pins ; nptr = TestTree->cname ; /*--- concatenate the name ---*/ part_pin = lower / (float) Ratio ; /*--calculate the pins per partition--*/ pp = (INT) part_pin ; if ((part_pin - pp) > 0){ pp++ ; } r_term = (pp * Ratio) - lower ; for(sect = 0; sect < Ratio ; sect++){ nptr = strcat(nptr,add_ptr); dummy_box = carrayG[cell++] ; /*-- get a dummy structure --*/ /*---- distributing the pins, the last section will have only one pin ---*/ if (sect < Ratio - 1) { dummy_box->numterms = pp ; /*-- get # of pins on the sub_cells-*/ } else { -- pp ; if ((part_pin - pp) > 0) { last_term = ++pp - r_term ; dummy_box->numterms = last_term ; } else dummy_box->numterms = pp ; }/*-end else-*/ /*-----------------------------------------------------------------------*/ dummy_box->clength = std_length; /*-- force the length to std_cell ---*/ dummy_box->cname = nptr ; /*-- concatenate the name ---*/ dummy_box->tileptr->left = - std_length / 2; /*-- adjust left --*/ dummy_box->tileptr->right = std_length / 2; /*--adjust right --*/ /*---------------- output the partition on stdcell.comp ----------------*/ if ( dummy_box->numterms == 0) { continue ; } fprintf(fp,"cell %d %s \n", cell_count, dummy_box->cname); fprintf(fp,"left %d right %d", dummy_box->tileptr->left,dummy_box->tileptr->right); fprintf(fp," bottom %d top %d \n", dummy_box->tileptr->bottom,dummy_box->tileptr->top); xx = 100 ; /*-------------- trying to print the pins in the dummy_box ---------------*/ for(counter = 0; counter < dummy_box->numterms; counter++){ if ((termptr->typos[0] == 0) && (termptr->typos[1] == 0)){ termptr->typos[0] = TestTree->tileptr->top ; termptr->typos[1] = TestTree->tileptr->bottom ; } corient = TestTree->corient ; xpost = termptr->txpos[corient / 2] ; /*-- fixing for out of space pins --*/ for ( zzz = 0; zzz < Ratio ; zzz++) { if (abs(xpost) >= ((zzz + 1) * (std_length / 2 ) ) ){ if (abs(xpost) == ((zzz + 1) * (std_length / 2 ) ) ){ if (xpost > 0){ xpost = xpost - (( zzz + 1 ) * ( std_length / 2 )) ; } else { xpost = xpost + (( zzz + 1 ) * ( std_length / 2 )) ; } } else { if (xpost > 0){ xpost = xpost - (( zzz + 2 ) * ( std_length / 2 )) ; } else { xpost = xpost + (( zzz + 2 ) * ( std_length / 2 )) ; } } } } ypost = termptr->typos[corient % 2] ; aptr = termptr->pinname ; aptr++ ; layer = *(aptr) ; aptr++ ; dptr = netarrayG[termptr->net] ; bptr = dptr->name ; eptr = termptr->eqptr ; /*-- get the equivalent pin --*/ if (eptr){ /*-- if the equivalent pin exists, print it out --*/ cptr = eptr->pinname ; yminus = eptr->typos ; if (abs(yminus) >= std_length){ if (yminus > 0){ yminus = yminus - std_length ; } else { yminus = yminus + std_length ; } } cptr++ ; layer = *(cptr) ; /*-- get the equivalent pin number --*/ cptr++ ; fprintf(fp,"pin name %s signal %s layer %c %d %d\n", aptr , bptr, layer, xpost, - yminus); fprintf(fp," equiv name %s layer %c %d %d\n", cptr, layer, xpost, yminus); } else { fprintf(fp,"pin name %s signal %s layer %c %d %d\n", aptr , bptr, layer, xpost, yminus); } termptr = termptr->nextpin ; fprintf(fp,"pin name %d signal TW_PASS_THRU layer %c %d %d \n",xx,layer, xpost + 3 , ypost); fprintf(fp," equiv name %d layer %c %d %d \n",++xx,layer, xpost + 3 , - ypost); xx++ ; }/*---end the inner for-statement---*/ xx++ ; fprintf(fp,"pin name %d signal TW_PASS_THRU layer %c %d %d \n",xx,layer, xpost + 1 , ypost); fprintf(fp," equiv name %d layer %c %d %d \n",++xx,layer, xpost + 1 , - ypost); fprintf(fp,"\n\n"); }/*----end for-statement---*/ } } /*----- for the outer for-loop -----*/ }/*---end if percent ---*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Transferring the Pads info as it is to the stdcell.comp ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ read_pads( fp ); TWCLOSE( fp ); return; } /***************************************************************************/ static INT compare_cell_length(c1,c2) CBOXPTR c1; CBOXPTR c2; { if (c1->clength > c2->clength){ return(GREATER); } else if (c1->clength < c2->clength){ return(LESS); } return(EQUAL); } /****************************************************************************/ static read_pads( fp ) FILE *fp ; { char buffer[LRECL], *bufferptr ; char **tokens ; /* for parsing menu file */ char copyBuf[LRECL] ; INT numtokens ; int delta ; int error ; int lineG ; FILE *fp_cell ; fp_cell = TWOPEN ("stdcell.cel","r" , ABORT) ; while( bufferptr = fgets(buffer,LRECL,fp_cell )){ /* make copy because scanner adds EOS characters */ strcpy( copyBuf, bufferptr ) ; tokens = Ystrparser( bufferptr, " \t\n", &numtokens ); if( numtokens == 0 ){ /*-- skip over the blank lines --*/ continue ; } /*-------------------------------------------------------------------*/ /*----- Once the Pad is detected, throw in the rest of the file -----*/ /*-------------------------------------------------------------------*/ if( strcmp( tokens[0], PADKEYWORD ) == STRINGEQ){ fprintf( fp, "%s", copyBuf ) ; while( bufferptr = fgets(buffer,LRECL,fp_cell )){ strcpy( copyBuf, bufferptr ) ; fprintf( fp, "%s", copyBuf ) ; } break ; } } /* end the big while loop */ /* now we need to unread the last line */ delta = - strlen(copyBuf) ; error = fseek( fp, delta, RELATIVE_TO_CURPOS ) ; if( error == -1 ){ M( ERRMSG, "readcells", "can't jump backwards in file\n" ) ; } } /* end read_pads */ graywolf-0.1.4+20170307gite1bf319/src/twsc/cglbroute.c000066400000000000000000000565331305746555600217010ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * Copyright (C) 2015 Tim Edwards * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: cglbroute.c DESCRIPTION:coarse global routing routines. CONTENTS: cglb_initial() proj_tree_to_grid( ) set_cbucket( ) cglbroute() free_cglb_initial() reinitial_Hdensity() update_switchvalue() rebuild_cbucket() check_cbucket() print_bucket( row ) INT row ; DATE: Mar 27, 1989 REVISIONS: Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) cglbroute.c (Yale) version 4.5 12/15/90" ; #endif #endif #include "standard.h" #include "main.h" #include "groute.h" #define OVERHEAD_INIT 100 #define OVERHEAD_DELTA 20 typedef struct coarsedensity { SHORT density ; SHORT x_coord ; struct coarsedensity *next ; struct coarsedensity *prev ; } HCAPBOX , *HCAPPTR ; static HCAPPTR **HcapacityS ; static HCAPPTR **entryptS ; static int entrysizeS ; static SEGBOXPTR *swLsegptrS ; static INT LswitchsegS , svalueS , evalueS ; static INT *crowdmaxS , glb_crowdmaxS , *node_rightS ; static DOUBLE ctrackContS , factor_hereS , factor_oneS , factor_twoS ; cglb_initial() { INT i , j , net , x , tilted_seg ; PINBOXPTR ptr1 , ptr2 ; SEGBOXPTR segptr ; tilted_seg = 0 ; ctrackContS = 2.25 ; factor_hereS = 1.0 ; factor_oneS = 0.5 ; factor_twoS = 0.2 ; svalueS = hznode_sepG * 4 / 10 ; evalueS = hznode_sepG * 6 / 10 ; node_rightS = (INT *)Ysafe_malloc( ( chan_node_noG + 1 ) * sizeof(INT) ); node_rightS[1] = blkleftG + ( hznode_sepG + 1 ) / 2 ; for( i = 2 ; i <= chan_node_noG ; i++ ) { node_rightS[i] = node_rightS[i-1] + hznode_sepG ; } HcapacityS = (HCAPPTR **)Ysafe_malloc( numChansG * sizeof(HCAPPTR *) ); for( i = 1 ; i <= numRowsG ; i++ ) { HcapacityS[i] = (HCAPPTR *) Ysafe_calloc( chan_node_noG + 1 , sizeof( HCAPPTR ) ) ; for( j = 1 ; j <= chan_node_noG ; j++ ) { HcapacityS[i][j] = ( HCAPPTR )Ysafe_calloc(1,sizeof(HCAPBOX)); HcapacityS[i][j]->x_coord = j ; } } for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ) { ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; x = ABS( ptr1->xpos - ptr2->xpos ) ; if( ptr1->row != ptr2->row ) { if( add_Lcorner_feedG && x >= average_feed_sepG ) { segptr->flag = FALSE ; } else { segptr->flag = TRUE ; } if( x >= average_feed_sepG ) { segptr->switchvalue = swL_up ; } else { segptr->switchvalue = nswLINE ; } tilted_seg++ ; } else if( ABS( ptr1->pinloc - ptr2->pinloc ) > 1 ) { segptr->flag = FALSE ; if( x >= average_feed_sepG ) { segptr->switchvalue = swL_up ; } else { segptr->switchvalue = nswLINE ; } } else { segptr->flag = TRUE ; segptr->switchvalue = nswLINE ; } } } fprintf(fpoG," the number of net = %d\n", numnetsG ) ; fprintf(fpoG," the number of tilted segment = %d\n", tilted_seg ) ; } proj_tree_to_grid( ) { SEGBOXPTR segptr ; PINBOXPTR ptr1 , ptr2 , netptr ; INT lowV , highV , lowH , highH ; INT i , h , k , net ; for( net = 1 ; net <= numnetsG ; net++ ) { for( netptr = steinerHeadG[net]->next;netptr;netptr = netptr->next ) { if( netptr->flag && 1 <= netptr->row && netptr->row <= numRowsG){ k = set_node( netptr->xpos ) ; feedpptrG[netptr->row][k]->needed++ ; } } } for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ) { ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; lowV = ptr1->row ; highV = ptr2->row ; lowH = set_node( ptr1->xpos ) ; highH = set_node( ptr2->xpos ) ; if( segptr->switchvalue == nswLINE ) { if( lowV != highV ) { if( ptr1->pinloc >= NEITHER || ptr1->row == 0 ) { lowV++ ; } if( ptr2->pinloc <= NEITHER || ptr2->row == numChansG ) { highV-- ; } for( i = lowV ; i <= highV ; i++ ) { feedpptrG[i][lowH]->needed++ ; } } else if( 1 <= lowV && lowV <= numRowsG ) { if( lowH == highH ) { HcapacityS[lowV][lowH]->density++ ; } else if( ptr2->xpos >= ptr1->xpos + average_feed_sepG ) { for( i = lowH + 1 ; i < highH ; i++ ) { HcapacityS[lowV][i]->density++ ; } if( node_rightS[lowH] - ptr1->xpos >= svalueS ) { HcapacityS[lowV][lowH]->density++ ; } if( node_rightS[highH] - ptr2->xpos <= evalueS ) { HcapacityS[lowV][highH]->density++ ; } } else if( ptr1->xpos >= ptr2->xpos + average_feed_sepG ){ for( i = highH + 1 ; i < lowH ; i++ ) { HcapacityS[lowV][i]->density++ ; } if( node_rightS[highH] - ptr2->xpos >= svalueS ) { HcapacityS[lowV][highH]->density++ ; } if( node_rightS[lowH] - ptr1->xpos <= evalueS ) { HcapacityS[lowV][lowH]->density++ ; } } if( segptr->flag == FALSE ) { /* segptr->pin1ptr->pinloc == BOTCELL && segptr->pin2ptr->pinloc == TOPCELL */ feedpptrG[lowV][lowH]->needed++ ; } } continue ; } else if( segptr->switchvalue == swL_up ) { h = lowH ; k = highV ; if( ptr1->pinloc >= NEITHER || ptr1->row == 0 ) { lowV++ ; } if( ptr2->pinloc <= NEITHER && segptr->flag || ptr2->row == numChansG ) { highV-- ; } if( k <= numRowsG ) { if( lowH == highH ) { HcapacityS[k][lowH]->density++ ; } else if( lowH < highH ) { for( i = lowH + 1 ; i < highH ; i++ ) { HcapacityS[k][i]->density++ ; } if( node_rightS[lowH] - ptr1->xpos >= svalueS ) { HcapacityS[k][lowH]->density++ ; } if( node_rightS[highH] - ptr2->xpos <= evalueS ) { HcapacityS[k][highH]->density++ ; } } else { for( i = highH + 1 ; i < lowH ; i++ ) { HcapacityS[k][i]->density++ ; } if( node_rightS[highH] - ptr2->xpos >= svalueS ) { HcapacityS[k][highH]->density++ ; } if( node_rightS[lowH] - ptr1->xpos <= evalueS ) { HcapacityS[k][lowH]->density++ ; } } } } else { /* switchvalue == swL_down */ h = highH ; k = lowV ; if( ptr1->row == 0 || ptr1->pinloc >= NEITHER && segptr->flag ) { lowV++ ; } if( ptr2->row == numChansG || ptr2->pinloc <= NEITHER ) { highV-- ; } if( 1 <= k ) { if( lowH == highH ) { HcapacityS[k][lowH]->density++ ; } else if( lowH < highH ) { for( i = lowH + 1 ; i < highH ; i++ ) { HcapacityS[k][i]->density++ ; } if( node_rightS[lowH] - ptr1->xpos >= svalueS ) { HcapacityS[k][lowH]->density++ ; } if( node_rightS[highH] - ptr2->xpos <= evalueS ) { HcapacityS[k][highH]->density++ ; } } else { for( i = highH + 1 ; i < lowH ; i++ ) { HcapacityS[k][i]->density++ ; } if( node_rightS[highH] - ptr2->xpos >= svalueS ) { HcapacityS[k][highH]->density++ ; } if( node_rightS[lowH] - ptr1->xpos <= evalueS ) { HcapacityS[k][lowH]->density++ ; } } } } for( i = lowV ; i <= highV ; i++ ) { feedpptrG[i][h]->needed++ ; } } } } set_cbucket( ) { HCAPPTR hcaptr , headptr ; SEGBOXPTR segptr ; INT j , last_j , row , max , net ; glb_crowdmaxS = 0 ; crowdmaxS = (INT *)Ysafe_calloc( numRowsG + 1, sizeof(INT) ) ; for( row = 1 ; row <= numRowsG ; row++ ) { max = 0 ; for( j = 1 ; j <= chan_node_noG ; j++ ) { if( HcapacityS[row][j]->density > max ) { max = HcapacityS[row][j]->density ; } } crowdmaxS[row] = max ; if( max > glb_crowdmaxS ) { glb_crowdmaxS = max ; } } entryptS = (HCAPPTR **)Ysafe_malloc( ( numRowsG+1 ) * sizeof(HCAPPTR *) ) ; entrysizeS = glb_crowdmaxS + OVERHEAD_INIT; for( row = 1 ; row <= numRowsG ; row++ ) { entryptS[row] = (HCAPPTR *)Ysafe_malloc( ( entrysizeS + 1 ) * sizeof( HCAPPTR )) ; for( j = 0 ; j <= entrysizeS ; j++ ) { entryptS[row][j] = (HCAPPTR)Ysafe_calloc( 1,sizeof(HCAPBOX)) ; } } for( row = 1 ; row <= numRowsG ; row++ ) { for( j = 1 ; j <= chan_node_noG ; j++ ) { hcaptr = HcapacityS[row][j] ; headptr = entryptS[row][ hcaptr->density ] ; if( headptr->next != NULL ) { hcaptr->next = headptr->next ; hcaptr->next->prev = hcaptr ; hcaptr->prev = headptr ; headptr->next = hcaptr ; } else { headptr->next = hcaptr ; hcaptr->prev = headptr ; hcaptr->next = NULL ; } } } LswitchsegS = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ) { if( segptr->switchvalue != nswLINE ) { LswitchsegS++ ; } } } fprintf(fpoG," the number of switchable L segment = %d\n", LswitchsegS ); swLsegptrS = ( SEGBOXPTR *)Ysafe_malloc( ( LswitchsegS + 2 * numnetsG ) * sizeof( SEGBOXPTR ) ) ; j = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ) { if( segptr->switchvalue != nswLINE ) { swLsegptrS[ ++j ] = segptr ; } } } } cglbroute() { SEGBOXPTR segptr ; PINBOXPTR ptr1 , ptr2 ; HCAPPTR hcaptr , denptr , headptr ; INT trys , maxtrys ; INT i , h , k , nh , nk , luck ; INT intersect_max , cover_allmax ; INT lowH , highH , startH , endH , lowV , highV ; INT vt_beg , vt_end , nvt_beg , nvt_end ; INT new_SwValue , density ; INT range_one_diff , range_two_diff , diff_here ; INT back_one_diff , back_two_diff , next_one_diff , next_two_diff ; DOUBLE penalty , ctrack_penalty , attperLseg ; DOUBLE penalty_here , penalty_one , penalty_two ; trys = 0 ; attperLseg = 15.0 ; maxtrys = attperLseg * LswitchsegS ; while( ++trys < maxtrys ) { luck = (INT)( (DOUBLE)LswitchsegS * ( (DOUBLE)RAND / (DOUBLE) 0x7fffffff ) ) + 1 ; segptr = swLsegptrS[ luck ] ; ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; lowH = set_node( ptr1->xpos ) ; highH = set_node( ptr2->xpos ) ; lowV = ptr1->row ; highV = ptr2->row ; if( lowH == highH ) { startH = endH = lowH ; } else if( lowH < highH ) { if( node_rightS[lowH] - ptr1->xpos >= svalueS ) { startH = lowH ; } else { startH = lowH + 1 ; } if( node_rightS[highH] - ptr2->xpos <= evalueS ) { endH = highH ; } else { endH = highH - 1 ; } } else { if( node_rightS[highH] - ptr2->xpos >= svalueS ) { startH = highH ; } else { startH = highH + 1 ; } if( node_rightS[lowH] - ptr1->xpos <= evalueS ) { endH = lowH ; } else { endH = lowH - 1 ; } } if( segptr->switchvalue == swL_up ) { h = lowH ; k = highV ; nh = highH ; nk = lowV ; new_SwValue = swL_down ; if( ptr1->pinloc >= NEITHER ) { vt_beg = lowV + 1 ; if( segptr->flag || ptr1->row == 0 ) { nvt_beg = lowV + 1 ; } else { nvt_beg = lowV ; } } else if( ptr1->row == 0 ) { vt_beg = lowV + 1 ; nvt_beg = lowV + 1 ; } else { vt_beg = lowV ; nvt_beg = lowV ; } if( ptr2->pinloc <= NEITHER ) { if( segptr->flag || ptr2->row == numChansG ) { vt_end = highV - 1 ; } else { vt_end = highV ; } nvt_end = highV - 1 ; } else if( ptr2->row == numChansG ) { vt_end = highV - 1 ; nvt_end = highV - 1 ; } else { vt_end = highV ; nvt_end = highV ; } } else { h = highH ; k = lowV ; nh = lowH ; nk = highV ; new_SwValue = swL_up ; if( ptr1->pinloc >= NEITHER ) { if( segptr->flag || ptr1->row == 0 ) { vt_beg = lowV + 1 ; } else { vt_beg = lowV ; } nvt_beg = lowV + 1 ; } else if( ptr1->row == 0 ) { vt_beg = lowV + 1 ; nvt_beg = lowV + 1 ; } else { vt_beg = lowV ; nvt_beg = lowV ; } if( ptr2->pinloc <= NEITHER ) { vt_end = highV - 1 ; if( segptr->flag || ptr2->row == numChansG ) { nvt_end = highV - 1 ; } else { nvt_end = highV ; } } else if( ptr2->row == numChansG ) { vt_end = highV - 1 ; nvt_end = highV - 1 ; } else { vt_end = highV ; nvt_end = highV ; } } if( 1 <= k && k <= numRowsG ) { cover_allmax = TRUE ; for( hcaptr = entryptS[k][ crowdmaxS[k] ]->next ; hcaptr != NULL ; hcaptr = hcaptr->next ) { if( !( startH <= hcaptr->x_coord && hcaptr->x_coord <= endH ) ) { cover_allmax = FALSE ; break ; } } } else { cover_allmax = FALSE ; } intersect_max = FALSE ; if( 1 <= nk && nk <= numRowsG ) { for( i = startH ; i <= endH ; i++ ) { if( HcapacityS[nk][i]->density == crowdmaxS[nk] ) { intersect_max = TRUE ; break ; } } } penalty_here = 0.0 ; penalty_one = 0.0 ; penalty_two = 0.0 ; for( i = vt_beg ; i <= vt_end ; i++ ) { diff_here = feedpptrG[i][h]->actual - feedpptrG[i][h]->needed ; if( diff_here < 0 ) { penalty_here-- ; } if( h > 2 ) { back_two_diff = feedpptrG[i][h-2]->actual - feedpptrG[i][h-2]->needed ; back_one_diff = feedpptrG[i][h-1]->actual - feedpptrG[i][h-1]->needed ; } else if( h == 2 ) { back_two_diff = 0 ; back_one_diff = feedpptrG[i][h-1]->actual - feedpptrG[i][h-1]->needed ; } else { back_two_diff = 0 ; back_one_diff = 0 ; } if( h <= chan_node_noG - 2 ) { next_two_diff = feedpptrG[i][h+2]->actual - feedpptrG[i][h+2]->needed ; next_one_diff = feedpptrG[i][h+1]->actual - feedpptrG[i][h+1]->needed ; } else if( h == chan_node_noG - 1 ) { next_two_diff = 0 ; next_one_diff = feedpptrG[i][h+1]->actual - feedpptrG[i][h+1]->needed ; } else { next_two_diff = 0 ; next_one_diff = 0 ; } range_one_diff = diff_here + back_one_diff + next_one_diff ; range_two_diff = range_one_diff + back_two_diff + next_two_diff; if( range_one_diff < 0 ) { penalty_one-- ; } if( range_two_diff < 0 ) { penalty_two-- ; } feedpptrG[i][h]->needed-- ; } for( i = nvt_beg ; i <= nvt_end ; i++ ) { feedpptrG[i][nh]->needed++ ; diff_here = feedpptrG[i][nh]->actual - feedpptrG[i][nh]->needed ; if( diff_here < 0 ) { penalty_here++ ; } if( nh > 2 ) { back_two_diff = feedpptrG[i][nh-2]->actual - feedpptrG[i][nh-2]->needed ; back_one_diff = feedpptrG[i][nh-1]->actual - feedpptrG[i][nh-1]->needed ; } else if( nh == 2 ) { back_two_diff = 0 ; back_one_diff = feedpptrG[i][nh-1]->actual - feedpptrG[i][nh-1]->needed ; } else { back_two_diff = 0 ; back_one_diff = 0 ; } if( nh <= chan_node_noG - 2 ) { next_two_diff = feedpptrG[i][nh+2]->actual - feedpptrG[i][nh+2]->needed ; next_one_diff = feedpptrG[i][nh+1]->actual - feedpptrG[i][nh+1]->needed ; } else if( nh == chan_node_noG - 1 ) { next_two_diff = 0 ; next_one_diff = feedpptrG[i][nh+1]->actual - feedpptrG[i][nh+1]->needed ; } else { next_two_diff = 0 ; next_one_diff = 0 ; } range_one_diff = diff_here + back_one_diff + next_one_diff ; range_two_diff = range_one_diff + back_two_diff + next_two_diff; if( range_one_diff < 0 ) { penalty_one++ ; } if( range_two_diff < 0 ) { penalty_two++ ; } } if( cover_allmax && intersect_max ) { ctrack_penalty = crowdmaxS[nk] - crowdmaxS[k] ; } else if( cover_allmax && !intersect_max ) { ctrack_penalty = -1 ; } else if( !cover_allmax && intersect_max ) { ctrack_penalty = 1 ; } else { ctrack_penalty = 0 ; } penalty = ctrackContS * ctrack_penalty + factor_hereS * penalty_here + factor_oneS * penalty_one + factor_twoS * penalty_two ; if( penalty <= 0 ) { if( 1 <= k && k <= numRowsG ) { for( i = startH ; i <= endH ; i++ ) { denptr = HcapacityS[k][i] ; if( denptr->next != NULL ) { denptr->next->prev = denptr->prev ; } denptr->prev->next = denptr->next ; density = --denptr->density ; headptr = entryptS[k][density] ; if( headptr->next != NULL ) { denptr->next = headptr->next ; denptr->next->prev = denptr ; denptr->prev = headptr ; headptr->next = denptr ; } else { headptr->next = denptr ; denptr->prev = headptr ; denptr->next = NULL ; } } if( cover_allmax ) { crowdmaxS[k]-- ; } } if( 1 <= nk && nk <= numRowsG ) { for( i = startH ; i <= endH ; i++ ) { denptr = HcapacityS[nk][i] ; if( denptr->next != NULL ) { denptr->next->prev = denptr->prev ; } denptr->prev->next = denptr->next ; density = ++denptr->density ; // Need to check bounds and reallocate if density has // exceeded OVERHEAD. This should be quite rare. if (density >= entrysizeS) { INT row, j; for( row = 1 ; row <= numRowsG ; row++ ) { entryptS[row] = (HCAPPTR *)Ysafe_realloc( entryptS[row], ( entrysizeS + OVERHEAD_DELTA + 1 ) * sizeof( HCAPPTR )) ; for( j = entrysizeS + 1; j <= entrysizeS + OVERHEAD_DELTA ; j++ ) { entryptS[row][j] = (HCAPPTR)Ysafe_calloc( 1,sizeof(HCAPBOX)) ; } } entrysizeS += OVERHEAD_DELTA; } headptr = entryptS[nk][density] ; if( headptr->next != NULL ) { denptr->next = headptr->next ; denptr->next->prev = denptr ; denptr->prev = headptr ; headptr->next = denptr ; } else { headptr->next = denptr ; denptr->prev = headptr ; denptr->next = NULL ; } } if( intersect_max ) { crowdmaxS[nk]++ ; } } segptr->switchvalue = new_SwValue ; } else { for( i = vt_beg ; i <= vt_end ; i++ ) { feedpptrG[i][h]->needed++ ; } for( i = nvt_beg ; i <= nvt_end ; i++ ) { feedpptrG[i][nh]->needed-- ; } } } } free_cglb_initial() { INT i , j , last_j , row ; Ysafe_free( node_rightS ) ; for( i = 1 ; i <= numRowsG ; i++ ) { for( j = 1 ; j <= chan_node_noG ; j++ ) { Ysafe_free( HcapacityS[i][j] ) ; } Ysafe_free( HcapacityS[i] ) ; } Ysafe_free( HcapacityS ) ; Ysafe_free( crowdmaxS ) ; for( row = 1 ; row <= numRowsG ; row++ ) { for( j = 0 ; j <= entrysizeS ; j++ ) { Ysafe_free( entryptS[row][j] ) ; } Ysafe_free( entryptS[row] ) ; } Ysafe_free( entryptS ) ; Ysafe_free( swLsegptrS ) ; } reinitial_Hdensity() { INT i , j ; for( i = 1 ; i <= numRowsG ; i++ ) { for( j = 1 ; j <= chan_node_noG ; j++ ) { HcapacityS[i][j]->density = 0 ; } } } update_switchvalue() { INT net , x , tilted_seg ; PINBOXPTR ptr1 , ptr2 , netptr ; SEGBOXPTR segptr ; LswitchsegS = 0 ; tilted_seg = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { for( netptr = steinerHeadG[net]->next;netptr; netptr = netptr->next ){ netptr->xpos = tearrayG[ netptr->newx ]->xpos ; /* update the steiner poINT position according to the reference pin position. */ } for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ) { ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; x = ABS( ptr1->xpos - ptr2->xpos ) ; if( ptr1->row != ptr2->row ) { if( add_Lcorner_feedG && x >= average_feed_sepG ) { segptr->flag = FALSE ; if( segptr->switchvalue == nswLINE ) { segptr->switchvalue = swL_up ; } } else { segptr->flag = TRUE ; /* if( x >= average_feed_sep ) { */ if( x ) { if( segptr->switchvalue == nswLINE ) { segptr->switchvalue = swL_up ; } } else { segptr->switchvalue = nswLINE ; } } ++tilted_seg ; } else if( ABS( ptr1->pinloc - ptr2->pinloc ) > 1 ) { segptr->flag = FALSE ; if( x >= average_feed_sepG ) { if( segptr->switchvalue == nswLINE ) { segptr->switchvalue = swL_up ; } } else { segptr->switchvalue = nswLINE ; } } else { segptr->flag = TRUE ; segptr->switchvalue = nswLINE ; } if( segptr->switchvalue != nswLINE ) { swLsegptrS[ ++LswitchsegS ] = segptr ; } } } fprintf(fpoG," the number of tilted segment = %d\n", tilted_seg ) ; fprintf(fpoG," the number of switchable L segment = %d\n", LswitchsegS ); } rebuild_cbucket() { INT row , j , last_j ; HCAPPTR hcaptr , headptr ; for( row = 1 ; row <= numRowsG ; row++ ) { crowdmaxS[row] = 0 ; for( j = 0 ; j <= entrysizeS ; j++ ) { entryptS[row][j]->next = NULL ; } } for( row = 1 ; row <= numRowsG ; row++ ) { for( j = 1 ; j <= chan_node_noG ; j++ ) { hcaptr = HcapacityS[row][j] ; // Watch for density exceeding OVERHEAD and increase // array sizes accordingly. if (hcaptr->density > entrysizeS) { INT lrow, k; for( lrow = 1 ; lrow <= numRowsG ; lrow++ ) { entryptS[lrow] = (HCAPPTR *)Ysafe_realloc( entryptS[lrow], ( entrysizeS + OVERHEAD_DELTA + 1 ) * sizeof( HCAPPTR )) ; for( k = entrysizeS + 1; k <= entrysizeS + OVERHEAD_DELTA ; k++ ) { entryptS[lrow][k] = (HCAPPTR)Ysafe_calloc( 1,sizeof(HCAPBOX)) ; } } entrysizeS += OVERHEAD_DELTA; } headptr = entryptS[row][ hcaptr->density ] ; if( headptr->next != NULL ) { hcaptr->next = headptr->next ; hcaptr->next->prev = hcaptr ; hcaptr->prev = headptr ; headptr->next = hcaptr ; } else { headptr->next = hcaptr ; hcaptr->prev = headptr ; hcaptr->next = NULL ; } if( hcaptr->density > crowdmaxS[row] ) { crowdmaxS[row] = hcaptr->density ; } } } } #ifdef DEBUG check_cbucket() { INT row, j ; HCAPPTR dptr , denptr ; for( row = 1 ; row <= numRowsG ; row++ ) { for( j = 1 ; j <= chan_node_noG ; j++ ) { denptr = HcapacityS[row][j] ; for( dptr = entryptS[row][denptr->density]->next ; dptr ; dptr = dptr->next ) { if( dptr == denptr ) { break ; } } if( dptr == NULL ) { printf(" something is going wrong\n" ) ; abort() ; } } } } print_bucket( row ) INT row ; { INT j ; HCAPPTR denptr ; FILE *fp ; fp = TWOPEN("bucket.dat", "a", ABORT ) ; fprintf(fp, "\n ROW = %d\n", row ) ; fprintf(fp, " sizeof densitybox = %d\n", sizeof(HCAPBOX) ) ; fprintf(fp, " %d %d\n", HcapacityS[row][1], HcapacityS[row][2] ) ; fprintf(fp," density cbin denptr nextptr prevptr\n" ) ; for( j = 1 ; j <= chan_node_noG ; j++ ) { denptr = HcapacityS[row][j] ; fprintf(fp," %7d %5d %12x %12x %12x\n", denptr->density, denptr->x_coord, denptr, denptr->next, denptr->prev ) ; } fprintf(fp,"\n\n" ) ; for( j = crowdmaxS[row] ; j >= 0 ; j-- ) { denptr = entryptS[row][j]->next ; if( denptr == NULL ) continue ; fprintf(fp,"\n denptr density x_coord\n" ) ; for( ; denptr ; denptr = denptr->next ) { fprintf(fp, " %12x %7d %7d\n", denptr, denptr->density, denptr->x_coord ) ; } } TWCLOSE(fp) ; } #endif graywolf-0.1.4+20170307gite1bf319/src/twsc/changrid.c000066400000000000000000000210551305746555600214610ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: changrid.c DESCRIPTION:channel gridding code. CONTENTS: changrid( ) pre_findrcost() DATE: Mar 27, 1989 REVISIONS: Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. Wed Aug 28 14:27:04 EDT 1991 - added more debug. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) changrid.c (Yale) version 4.5 8/29/91" ; #endif #endif #include "standard.h" #include "groute.h" changrid( ) { CHANGRDPTR **gdptr , grdptr , cgdptr , ngdptr ; PINBOXPTR netptr ; INT row , net , channel , terminal ; INT *numPins , *PinInChan ; INT count , i, k, comparegdx() ; numPins = (INT *)Ysafe_calloc( numChansG+1, sizeof(INT) ) ; PinInChan = (INT *)Ysafe_calloc( numChansG+1, sizeof(INT) ) ; for( net = 1 ; net <= numnetsG ; net++ ) { for( netptr = netarrayG[net]->pins ; netptr ; netptr = netptr->next ) { if( (INT) netptr->pinloc == BOTCELL ) { numPins[ netptr->row ]++ ; } else if( (INT) netptr->pinloc == TOPCELL ) { numPins[ netptr->row + 1 ]++ ; } else { /* pinloc == 0 pin on pads or macros */ if( netptr->row > 0 ) { numPins[ netptr->row ]++ ; } if( netptr->row < numChansG ) { numPins[ netptr->row + 1 ]++ ; } } } } gdptr = (CHANGRDPTR **)Ysafe_malloc( (numChansG+1) * sizeof(CHANGRDPTR *) ) ; for( channel = 1 ; channel <= numChansG ; channel++ ) { gdptr[channel] = ( CHANGRDPTR * )Ysafe_malloc( ( numPins[channel] + 1 ) * sizeof( CHANGRDPTR ) ) ; } k = maxtermG + 2 * numChansG ; TgridG = ( TGRIDPTR * )Ysafe_malloc( ( k+1 ) * sizeof( TGRIDPTR ) ) ; for( terminal = 1 ; terminal <= k ; terminal++ ) { TgridG[ terminal ] = ( TGRIDPTR )Ysafe_malloc( sizeof(TGRIDBOX) ) ; } for( net = 1 ; net <= numnetsG ; net++ ) { for( netptr = netarrayG[net]->pins ;netptr;netptr=netptr->next ) { row = netptr->row ; terminal = netptr->terminal ; #ifdef DEBUG if( tearrayG[ terminal ] == PINNULL ) { printf(" netptr for pin = %8d is NULL; net:%d row:%d\n" , terminal , net , row ) ; fflush(stdout) ; } #endif grdptr = ( CHANGRDPTR )Ysafe_calloc( 1, sizeof(CHANGRDBOX)) ; if( (INT) netptr->pinloc == BOTCELL ) { channel = row ; count = ++(PinInChan[ channel ]) ; gdptr[ channel ][ count ] = grdptr ; TgridG[ terminal ]->up = grdptr ; TgridG[ terminal ]->down = grdptr ; grdptr->netptr = tearrayG[ terminal ] ; } else if( (INT) netptr->pinloc == TOPCELL ) { channel = row + 1 ; count = ++(PinInChan[ channel ]) ; gdptr[ channel ][ count ] = grdptr ; TgridG[ terminal ]->up = grdptr ; TgridG[ terminal ]->down = grdptr ; grdptr->netptr = tearrayG[ terminal ] ; } else { /* pinloc == NEITHER pin on pads or macros */ if( 1 <= row && row <= numChansG - 1 ) { channel = row ; count = ++(PinInChan[ channel ]) ; gdptr[ channel ][ count ] = grdptr ; TgridG[ terminal ]->down = grdptr ; grdptr->netptr = tearrayG[ terminal ] ; channel = row + 1 ; count = ++(PinInChan[ channel ]) ; grdptr = gdptr[ channel ][ count ] = ( CHANGRDPTR )Ysafe_calloc( 1,sizeof(CHANGRDBOX)) ; TgridG[ terminal ]->up = grdptr ; grdptr->netptr = tearrayG[ terminal ] ; } else if( row == 0 ) { count = ++(PinInChan[ 1 ]) ; gdptr[ 1 ][ count ] = grdptr ; TgridG[ terminal ]->up = grdptr ; TgridG[ terminal ]->down = grdptr ; grdptr->netptr = tearrayG[ terminal ] ; } else { /* row == numChansG */ count = ++(PinInChan[ numChansG ]) ; gdptr[ numChansG ][ count ] = grdptr ; TgridG[ terminal ]->up = grdptr ; TgridG[ terminal ]->down = grdptr ; grdptr->netptr = tearrayG[ terminal ] ; } } } } for( channel = 1 ; channel <= numChansG ; channel++ ) { Yquicksort( (char *) ( gdptr[channel] + 1 ) , numPins[channel] , sizeof( CHANGRDPTR ), comparegdx ) ; } BeginG = ( CHANGRDPTR * )Ysafe_calloc( numChansG + 1, sizeof(CHANGRDPTR ) ) ; EndG = ( CHANGRDPTR * )Ysafe_calloc( numChansG + 1, sizeof(CHANGRDPTR ) ) ; for( channel = 1 ; channel <= numChansG ; channel++ ) { BeginG[channel] = ( CHANGRDPTR )Ysafe_calloc( 1, sizeof(CHANGRDBOX) ) ; BeginG[channel]->netptr = ( PINBOXPTR )Ysafe_calloc(1,sizeof(PINBOX)); BeginG[channel]->netptr->xpos = gxstartG - 1 ; BeginG[channel]->netptr->terminal = maxtermG + channel ; BeginG[channel]->netptr->row = channel ; BeginG[channel]->netptr->pinloc = BOTCELL ; tearrayG[maxtermG + channel] = BeginG[channel]->netptr ; EndG[channel] = ( CHANGRDPTR )Ysafe_calloc( 1,sizeof(CHANGRDBOX)) ; EndG[channel]->netptr = ( PINBOXPTR )Ysafe_calloc( 1,sizeof(PINBOX)) ; EndG[channel]->netptr->xpos = gxstopG + 1 ; EndG[channel]->netptr->terminal = maxtermG + numChansG + channel ; EndG[channel]->netptr->row = channel ; EndG[channel]->netptr->pinloc = BOTCELL ; tearrayG[maxtermG + numChansG + channel] = EndG[channel]->netptr ; } for( channel = 1 ; channel <= numChansG ; channel++ ) { TgridG[ maxtermG + channel ]->up = BeginG[ channel ] ; TgridG[ maxtermG + channel ]->down = BeginG[ channel ] ; TgridG[ maxtermG + numChansG + channel ]->up = EndG[ channel ] ; TgridG[ maxtermG + numChansG + channel ]->down = EndG[ channel ] ; } for( channel = 1 ; channel <= numChansG ; channel++ ) { if( numPins[channel] == 0 ) { BeginG[channel]->nextgrd = NULL ; EndG[channel]->prevgrd = NULL ; } else if( numPins[channel] == 1 ) { BeginG[channel]->nextgrd = gdptr[channel][1] ; gdptr[channel][1]->prevgrd = BeginG[channel] ; EndG[channel]->prevgrd = gdptr[channel][1] ; gdptr[channel][1]->nextgrd = EndG[channel] ; } else { BeginG[channel]->nextgrd = gdptr[channel][1] ; gdptr[channel][1]->prevgrd = BeginG[channel] ; for( i = 1 ; i <= numPins[channel]-1 ; i++ ) { cgdptr = gdptr[channel][i] ; ngdptr = gdptr[channel][i+1] ; cgdptr->nextgrd = ngdptr ; ngdptr->prevgrd = cgdptr ; } ngdptr->nextgrd = EndG[channel] ; EndG[channel]->prevgrd = ngdptr ; } } for( channel = 1 ; channel <= numChansG ; channel++ ) { Ysafe_free( gdptr[ channel ] ) ; } Ysafe_free( gdptr ) ; Ysafe_free( numPins ) ; Ysafe_free( PinInChan ) ; } pre_findrcost() { SEGBOXPTR segptr ; PINBOXPTR ptr1 , ptr2 ; INT net ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ) { ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; if( ABS( ptr1->row - ptr2->row ) > 1 ) { segptr->switchvalue = nswLINE ; if( ptr1->xpos < blk_most_leftG ) { if( ptr1->row > ptr2->row ) { segptr->pin1ptr = tearrayG[ maxtermG + ptr2->row + 1 ] ; } else { segptr->pin1ptr = tearrayG[ maxtermG + ptr2->row ] ; } } else if( ptr2->xpos > blk_most_riteG ) { if( ptr2->row > ptr1->row ) { segptr->pin2ptr = tearrayG[ maxtermG + numChansG + ptr1->row + 1 ] ; } else { segptr->pin2ptr = tearrayG[ maxtermG + numChansG + ptr1->row ] ; } } else { printf("segment other than connecting pin has row") ; printf(" difference greater than 1\n" ) ; } } } } } graywolf-0.1.4+20170307gite1bf319/src/twsc/coarseglb.c000066400000000000000000000624001305746555600216420ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * Copyright (C) 2013 Tim Edwards cblock ; for( pinptr = cellptr->pins; pinptr ; pinptr = pinptr->nextpin ){ pinptr->row = block ; } } } set_up_grid( ) { INT i , j , x , row_rite ; INT left, right, bottom, top ; INT row , cell , last_cell , class ; INT curr_row_rite , max_desire, prev_row_rite , padside ; TIBOXPTR tptr ; numChansG = numRowsG + 1 ; accumulate_feedS = (INT *)Ysafe_malloc( numChansG * sizeof(INT) ) ; /* set up the grid points in each rows for coarse routing */ if( average_pin_sepG <= 3.25 * average_pin_sepG ) { hznode_sepG = 2.3 * average_feed_sepG ; } else { hznode_sepG = 7.5 * average_pin_sepG ; } /* horizontal node separation */ half_hzsepS = hznode_sepG / 2 ; blk_most_leftG = barrayG[1]->bxcenter + barrayG[1]->bleft ; for( row = 2 ; row <= numRowsG ; row++ ) { if( barrayG[row]->bxcenter + barrayG[row]->bleft < blk_most_leftG ) { blk_most_leftG = barrayG[row]->bxcenter + barrayG[row]->bleft ; } } blk_most_riteG = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { last_cell = pairArrayG[row][ pairArrayG[row][0] ] ; row_rite = carrayG[ last_cell ]->cxcenter + carrayG[ last_cell ]->tileptr->right ; if( row_rite > blk_most_riteG ) { blk_most_riteG = row_rite ; } } max_desire = barrayG[1]->desire ; for( row = 2 ; row <= numRowsG ; row++ ) { if( max_desire < barrayG[row]->desire ) { max_desire = barrayG[row]->desire ; } } if( blk_most_riteG - blk_most_leftG >= max_desire ) { chan_node_noG = ( blk_most_riteG - blk_most_leftG) / hznode_sepG + 1 ; chan_node_noG += chan_node_noG ; } else { chan_node_noG = max_desire / hznode_sepG + 1 ; chan_node_noG += chan_node_noG ; } /* chan_node_noG is the number of horizontal edges in each row. Make one more node in case the row length is longer because of feedthrough cells add in */ feedpptrG = (FEED_DATA **)Ysafe_malloc( numChansG * sizeof(FEED_DATA *) ); for( i = 1 ; i <= numRowsG ; i++ ) { feedpptrG[i] = (FEED_DATA *) Ysafe_malloc( ( chan_node_noG + 1 ) * sizeof( FEED_DATA ) ) ; for( j = 1 ; j <= chan_node_noG ; j++ ) { feedpptrG[i][j] = (FEED_DATA)Ysafe_calloc( 1,sizeof(FEED_DBOX) ) ; } } diff_in_rowfeedS = (INT *)Ysafe_malloc( numChansG * sizeof(INT) ) ; feed_diffS = (INT *)Ysafe_calloc( chan_node_noG + 1, sizeof( INT )) ; fdcel_addedG = (INT *)Ysafe_calloc( numChansG, sizeof( INT ) ) ; feed_shortS = (INT *)Ysafe_calloc( numChansG, sizeof( INT ) ) ; fdcel_needG = (INT **)Ysafe_calloc( numChansG, sizeof(INT *) ); for( i = 1 ; i <= numRowsG ; i++ ) { fdcel_needG[i] = (INT *)Ysafe_calloc( chan_node_noG+1, sizeof(INT) ) ; } /* in order to take care of the circuits with macros we need to do the following */ row_rite_classG = (INT *) Ysafe_malloc( numChansG * sizeof(INT) ) ; right_most_in_classG = (INT *)Ysafe_malloc( numChansG * sizeof(INT) ) ; class = 0 ; prev_row_rite = -1 ; row_rite_classG[1] = class ; for( row = 1 ; row <= numRowsG ; row++ ) { curr_row_rite = barrayG[row]->bxcenter + barrayG[row]->bleft + barrayG[row]->desire ; if( curr_row_rite == prev_row_rite ) { row_rite_classG[row] = class ; } else { row_rite_classG[row] = ++class ; prev_row_rite = curr_row_rite ; } } right_Pads_left_edgeS = INFINITY ; for( cell = numcellsG + 1 ; cell <= lastpadG ; cell++ ) { padside = carrayG[cell]->padptr->padside ; if( padside == R ) { tptr = carrayG[cell]->tileptr ; left = tptr->left ; right = tptr->right ; bottom = tptr->bottom ; top = tptr->top ; YtranslateT( &left, &bottom, &right, &top, (INT)carrayG[cell]->corient ) ; x = carrayG[cell]->cxcenter + left ; if( x < right_Pads_left_edgeS ) { right_Pads_left_edgeS = x ; } } } } initialize_feed_need() { INT i , row ; FEED_DATA *feedptr ; for( row = 1 ; row <= numRowsG ; row++ ) { fdcel_addedG[row] = 0 ; feedptr = feedpptrG[row] ; for( i = 1 ; i <= chan_node_noG ; i++ ) { feedptr[i]->needed = 0 ; feedptr[i]->actual = 0 ; } } feed_config() ; } feed_config( ) { INT row , cell , cxcenter , k ; CBOXPTR cellptr ; IPBOXPTR imptr ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = carrayG[ cell ] ; cxcenter = cellptr->cxcenter ; row = cellptr->cblock ; for( imptr = cellptr->imptr ; imptr ; imptr = imptr->next ) { if( cellptr->corient <= 1 ) { imptr->xpos = cxcenter + imptr->txpos ; } else { if( cellptr->clength % 2 == 0 ) { imptr->xpos = cxcenter - imptr->txpos ; } else { imptr->xpos = cxcenter - imptr->txpos - 1 ; } } k = set_node( imptr->xpos ) ; feedpptrG[row][k]->actual++ ; } } } set_node( x ) INT x ; { DOUBLE h ; h = (DOUBLE)( x - blk_most_leftG ) / (DOUBLE)hznode_sepG + 1.5 ; if( h < 1 ) { return( 1 ) ; } else if( h > chan_node_noG ) { return( chan_node_noG ) ; } else { return( (INT)h ) ; } } compute_feed_diff( iteration ) INT iteration ; { INT i , j , k , range , left_node , rite_node ; if( ignore_feedsG || try_not_to_add_explicit_feedsG ) { range = chan_node_noG ; } else if( iteration <= 1 ) { if( add_Lcorner_feedG ) { range = 5 + iteration ; } else { range = iteration ; } } else { range = chan_node_noG ; } for( i = 1 ; i <= numRowsG ; i++ ) { feed_shortS[i] = 0 ; for( j = 1 ; j <= chan_node_noG ; j++ ) { feed_diffS[j] = feedpptrG[i][j]->actual - feedpptrG[i][j]->needed ; feed_shortS[i] -= feed_diffS[j] ; } for( j = 1 ; j <= chan_node_noG ; j++ ) { if( feed_diffS[j] < 0 ) { left_node = rite_node = j ; for( k = 1 ; k <= range ; k++ ) { if( left_node > 1 ) { if( feed_diffS[--left_node] > 0 ) { if( feed_diffS[left_node] + feed_diffS[j] < 0 ) { feed_diffS[j] += feed_diffS[left_node] ; feed_diffS[left_node] = 0 ; } else { feed_diffS[left_node] += feed_diffS[j] ; feed_diffS[j] = 0 ; break ; } } } if( rite_node < chan_node_noG ) { if( feed_diffS[++rite_node] > 0 ) { if( feed_diffS[rite_node] + feed_diffS[j] < 0 ) { feed_diffS[j] += feed_diffS[rite_node] ; feed_diffS[rite_node] = 0 ; } else { feed_diffS[rite_node] += feed_diffS[j] ; feed_diffS[j] = 0 ; break ; } } } } } if( feed_diffS[j] < 0 ) { fdcel_needG[i][j] = - feed_diffS[j] ; } else { fdcel_needG[i][j] = 0 ; } } } } space_for_feed( ) { PINBOXPTR pinptr ; CBOXPTR cellptr ; INT row , i , Flag , shiftFlag , *Aray ; INT nodex , node , shift , patch_shift ; INT locFdWidth = fdWidthG; // if ( ignore_feedsG ) locFdWidth = 0; shiftFlag = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { Flag = 1 ; Aray = pairArrayG[row] ; accumulate_feedS[row] = 0 ; for( node = 1 ; node <= chan_node_noG ; node++ ) { if( fdcel_needG[row][node] != 0 ) { Flag = 0 ; /* the first position need to add feed thru cell */ break ; } } if( Flag ) { continue ; /* no need to add actual feed thru cells */ } shiftFlag = 1 ; nodex = blk_most_leftG + ( node - 1 ) * hznode_sepG ; cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; if( Aray[0] == 1 ) { patch_shift = locFdWidth * feed_shortS[row] ; cellptr->cxcenter += patch_shift ; for( pinptr = cellptr->pins;pinptr; pinptr = pinptr->nextpin ) { pinptr->xpos += patch_shift ; } fdcel_addedG[row] += feed_shortS[row] ; continue ; } if( nodex >= cellptr->cxcenter ) { if( feed_shortS[row] > 0 ) { patch_shift = locFdWidth * feed_shortS[row] ; cellptr->cxcenter += patch_shift ; for( pinptr = cellptr->pins;pinptr;pinptr=pinptr->nextpin ) { pinptr->xpos += patch_shift ; } fdcel_addedG[row] += feed_shortS[row] ; } continue ; } for( i = 1 ; i <= Aray[0] ; i++ ) { cellptr = carrayG[ Aray[i] ] ; if( cellptr->cxcenter > nodex && cellptr->cclass != -2 ) { break ; } } nodex += hznode_sepG ; for( ; node <= chan_node_noG ; node++ , nodex += hznode_sepG ) { accumulate_feedS[row] += fdcel_needG[row][node] ; shift = accumulate_feedS[row] * locFdWidth ; for( ; i <= Aray[0] ; i++ ) { cellptr = carrayG[ Aray[i] ] ; if( cellptr->cclass == -3 ) { break ; } else if( cellptr->cxcenter < nodex ) { cellptr->cxcenter += shift ; for( pinptr=cellptr->pins;pinptr;pinptr=pinptr->nextpin ){ pinptr->xpos += shift ; } } else { break ; } } if( i > Aray[0] ) { break ; } } for( ; i <= Aray[0] ; i++ ) { carrayG[ Aray[i] ]->cxcenter += shift ; for( pinptr = carrayG[ Aray[i] ]->pins ;pinptr; pinptr = pinptr->nextpin ) { pinptr->xpos += shift ; } } if( feed_shortS[row] > accumulate_feedS[row] ) { patch_shift = locFdWidth * ( feed_shortS[row] - accumulate_feedS[row] ) ; if( carrayG[ Aray[ Aray[0] ] ]->cclass == -3 ) { for( i = Aray[0] - 1 ; i >= 1 ; i-- ) { if( carrayG[ Aray[i] ]->cclass != -3 ) { i++ ; break ; } } } else { i = Aray[0] ; } for( ; i <= Aray[0] ; i++ ) { cellptr = carrayG[ Aray[i] ] ; cellptr->cxcenter += patch_shift ; for( pinptr = cellptr->pins;pinptr;pinptr=pinptr->nextpin ) { pinptr->xpos += patch_shift ; } } fdcel_addedG[row] += feed_shortS[row] ; } else { fdcel_addedG[row] += accumulate_feedS[row] ; } } /* added by Carl 12/7/91 */ for( row = 1 ; row <= numRowsG ; row++ ) { if( fdcel_addedG[row] < 0 ) { fdcel_addedG[row] = 0 ; } } /* added by Carl 12/7/91 */ return( shiftFlag ) ; } update_feed_config( iteration ) INT iteration ; { INT cell , padside , shift ; INT *Aray , i , k , row , row_left , row_rite ; INT last , orient , curr_rite , next_left , lastcell_rite ; INT feedx , last_feedx , first_cell_left ; CBOXPTR cellptr , nextptr , currptr ; PINBOXPTR pin ; FEED_DATA *feedptr ; IPBOXPTR imptr ; INT locFdWidth = fdWidthG; // if ( ignore_feedsG ) locFdWidth = 0; /********************************************************************* * if we need to add in feed through cells , we first create a * * gap space between adjacent cells where real feed through cells * * will be placed later on. Thus the new available number of feed * * through cells in each bins will be equal to the number of implicit * * feed through pins in this bin plus the gap space in this bin * * divide by the width of feed through cells. * **********************************************************************/ for( row = 1 ; row <= numRowsG ; row++ ) { Aray = pairArrayG[row] ; feedptr = feedpptrG[row] ; for( k = 1 ; k <= chan_node_noG ; k++ ) { feedptr[k]->actual = 0 ; feedptr[k]->needed = 0 ; } currptr = carrayG[ Aray[1] ] ; first_cell_left = currptr->cxcenter + currptr->tileptr->left ; row_left = barrayG[row]->bxcenter + barrayG[row]->bleft ; if( row_left != first_cell_left ) { feedx = row_left + locFdWidth / 2 ; for( ; feedx < first_cell_left ; feedx += locFdWidth ) { k = set_node( feedx ) ; feedptr[k]->actual++ ; } } last = Aray[0] - 1 ; for( i = 1 ; i <= last ; i++ ) { nextptr = carrayG[ Aray[i+1] ] ; orient = currptr->corient ; for( imptr = currptr->imptr ; imptr ; imptr = imptr->next ) { if( orient <= 1 ) { imptr->xpos = currptr->cxcenter + imptr->txpos ; } else { if( currptr->clength % 2 == 0 ) { imptr->xpos = currptr->cxcenter - imptr->txpos ; } else { imptr->xpos = currptr->cxcenter - imptr->txpos - 1 ; } } k = set_node( imptr->xpos ) ; feedptr[k]->actual++ ; } curr_rite = currptr->cxcenter + currptr->tileptr->right ; next_left = nextptr->cxcenter + nextptr->tileptr->left ; if( curr_rite != next_left ) { for( feedx = curr_rite + locFdWidth / 2 ; feedx < next_left ; feedx += locFdWidth ) { k = set_node( feedx ) ; feedptr[k]->actual++ ; } } currptr = nextptr ; } orient = currptr->corient ; for( imptr = currptr->imptr ; imptr ; imptr = imptr->next ) { if( orient <= 1 ) { imptr->xpos = currptr->cxcenter + imptr->txpos ; } else { if( currptr->clength % 2 == 0 ) { imptr->xpos = currptr->cxcenter - imptr->txpos ; } else { imptr->xpos = currptr->cxcenter - imptr->txpos - 1 ; } } k = set_node( imptr->xpos ) ; feedptr[k]->actual++ ; } } blk_most_riteG = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; row_rite = cellptr->cxcenter + cellptr->tileptr->right ; if( row_rite > blk_most_riteG ) { blk_most_riteG = row_rite ; } } decide_right_most_in_class() ; if( iteration >= 2 && !no_feed_at_endG ) { for( row = 1 ; row <= numRowsG ; row++ ) { cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; lastcell_rite = cellptr->cxcenter + cellptr->tileptr->right ; feedx = lastcell_rite + locFdWidth / 2 ; last_feedx = right_most_in_classG[ row_rite_classG[row] ] - ( locFdWidth + 1 ) / 2 ; feedptr = feedpptrG[row] ; for( ; feedx <= last_feedx ; feedx += locFdWidth ) { k = set_node( feedx ) ; feedptr[k]->actual++ ; } } } if( rowsG == 0 && blk_most_riteG >= right_Pads_left_edgeS ) { shift = blk_most_riteG - right_Pads_left_edgeS + 30 ; right_Pads_left_edgeS += shift ; for( cell = numcellsG + 1 ; cell <= lastpadG ; cell++ ) { padside = carrayG[cell]->padptr->padside ; if( padside == R || padside == MR || padside == MUR || padside == MLR ) { carrayG[cell]->cxcenter += shift ; for( pin = carrayG[cell]->pins; pin ; pin = pin->nextpin ){ pin->xpos += shift ; } } } } } no_of_feedthru_cells() { INT i , row , n , difference , lastcell_rite , total_feedthrus ; CBOXPTR cellptr ; FEED_DATA *feedptr ; INT locFdWidth = fdWidthG; // if (ignore_feedsG) locFdWidth = 0; total_feedthrus = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { difference = 0 ; feedptr = feedpptrG[row] ; for( i = 1 ; i <= chan_node_noG ; i++ ) { difference += feedptr[i]->actual - feedptr[i]->needed ; } if( difference < 0 ) { diff_in_rowfeedS[row] = -difference ; if( no_feed_at_endG ) { printf(" not enough feed were added in\n" ) ; exit(0) ; } } else { diff_in_rowfeedS[row] = 0 ; } cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; lastcell_rite = cellptr->cxcenter + cellptr->tileptr->right ; if( locFdWidth == 0 || cellptr->cclass == -3 ) { n = 0 ; } else { n = ( right_most_in_classG[ row_rite_classG[row] ] - lastcell_rite ) / locFdWidth ; } total_feedthrus += ( fdcel_addedG[row] + diff_in_rowfeedS[row] + n ) ; } return( total_feedthrus ) ; } addin_feedcell() { INT row , i , k , r , last , feednum , row_left ; INT curr_rite , next_left , half_fdWidthG , feedx , last_feedx ; INT *Aray , *nAray , last_rite_edge , first_cell_left ; CBOXPTR current , nextone , lastptr ; INT locFdWidth = fdWidthG; // if ( ignore_feedsG ) locFdWidth = 0; half_fdWidthG = locFdWidth / 2 ; feednum = 0 ; /* fp = TWOPEN( "rowlen.dat" , "a", ABORT ) ; fprintf(fp,"\n the row length after coarse global routing are\n" ) ; fprintf(fp," row row_length desire over/under fdthrus\n" ) ; */ for( row = 1 ; row <= numRowsG ; row++ ) { Aray = pairArrayG[row] ; lastptr = carrayG[ Aray[ Aray[0] ] ] ; last_rite_edge = lastptr->cxcenter + lastptr->tileptr->right ; if( !no_feed_at_endG ) { r = ( right_most_in_classG[ row_rite_classG[row] ] - last_rite_edge ) / locFdWidth + 1 ; } else { r = 0 ; } /* n = fdcel_addedG[row] + diff_in_rowfeedS[row] ; fprintf(fp," %3d %10d %6d %10d %6d\n", row, last_rite_edge - barrayG[row]->bxcenter - barrayG[row]->bleft , barrayG[row]->desire, last_rite_edge - barrayG[row]->desire - barrayG[row]->bxcenter - barrayG[row]->bleft , n ) ; */ if( fdcel_addedG[row] == 0 ) { if( r > 1 ) { Aray = (INT *)Ysafe_realloc( Aray , (2 * ( r + Aray[0] + diff_in_rowfeedS[row] + 1 ) + (extra_cellsG / numRowsG) * 4) * sizeof(INT) ) ; feedx = last_rite_edge + half_fdWidthG ; last_feedx = right_most_in_classG[ row_rite_classG[row] ] - ( locFdWidth + 1 ) / 2 ; for( ; feedx <= last_feedx ; feedx += locFdWidth ) { addfeed( row , feedx , ++feednum ) ; Aray[ ++Aray[0] ] = numcellsG + numtermsG + feednum ; } last_feedx += diff_in_rowfeedS[row] * locFdWidth ; for( ; feedx <= last_feedx ; feedx += locFdWidth ) { addfeed( row , feedx , ++feednum ) ; Aray[ ++Aray[0] ] = numcellsG + numtermsG + feednum ; k = set_node( feedx ) ; feedpptrG[row][k]->actual++ ; } } pairArrayG[row] = Aray ; continue ; } nAray = (INT *)Ysafe_malloc( (2 * ( Aray[0] + fdcel_addedG[row] + diff_in_rowfeedS[row] + r + 1 ) + (extra_cellsG / numRowsG ) * 4 ) * sizeof( INT ) ) ; nAray[0] = 0 ; current = carrayG[ Aray[1] ] ; first_cell_left = current->cxcenter + current->tileptr->left ; row_left = barrayG[row]->bxcenter + barrayG[row]->bleft ; if( row_left != first_cell_left ) { feedx = row_left + locFdWidth / 2 ; for( ; feedx < first_cell_left ; feedx += locFdWidth ) { addfeed( row , feedx , ++feednum ) ; nAray[ ++nAray[0] ] = numcellsG + numtermsG + feednum ; } } last = Aray[0] - 1 ; for( i = 1 ; i <= last ; i++ ) { nAray[ ++nAray[0] ] = Aray[i] ; nextone = carrayG[ Aray[i+1] ] ; curr_rite = current->cxcenter + current->tileptr->right ; next_left = nextone->cxcenter + nextone->tileptr->left ; if( curr_rite < next_left ) { feedx = curr_rite + half_fdWidthG ; for( ; feedx < next_left ; feedx += locFdWidth ) { addfeed( row , feedx , ++feednum ) ; nAray[ ++nAray[0] ] = numcellsG + numtermsG + feednum ; } } current = nextone ; } nAray[ ++nAray[0] ] = Aray[ Aray[0] ] ; if( !no_feed_at_endG ) { feedx = last_rite_edge + half_fdWidthG ; last_feedx = right_most_in_classG[ row_rite_classG[row] ] - ( locFdWidth + 1 ) / 2; for( ; feedx <= last_feedx ; feedx += locFdWidth ) { addfeed( row , feedx , ++feednum ) ; nAray[ ++nAray[0] ] = numcellsG + numtermsG + feednum ; } last_feedx += diff_in_rowfeedS[row] * locFdWidth ; for( ; feedx <= last_feedx ; feedx += locFdWidth ) { addfeed( row , feedx , ++feednum ) ; nAray[ ++nAray[0] ] = numcellsG + numtermsG + feednum ; k = set_node( feedx ) ; feedpptrG[row][k]->actual++ ; } } pairArrayG[row] = nAray ; Ysafe_free( Aray ) ; } actual_feed_thru_cells_addedG = feednum ; /* Added by Tim, 8/26/2013 */ expand_heat_index(); /* TWCLOSE(fp) ; */ } final_feed_config( ) { IPBOXPTR imptr ; FEED_DATA *feedptr ; CBOXPTR first_cptr , last_cptr ; INT i , row , longest_row , max_length , k , length , *Aray ; INT delta_row_len ; for( row = 1 ; row <= numRowsG ; row++ ) { Aray = pairArrayG[row] ; for( i = 1 ; i <= Aray[0] ; i++ ) { for( imptr = carrayG[ Aray[i] ]->imptr ; imptr ; imptr = imptr->next ) { k = set_node( imptr->xpos ) ; if( feedpptrG[row][k]->firstimp ) { feedpptrG[row][k]->lastimp = imptr ; } else { feedpptrG[row][k]->firstimp = imptr ; feedpptrG[row][k]->lastimp = imptr ; } } } } total_feed_in_the_rowG = (INT *)Ysafe_malloc( numChansG * sizeof(INT) ) ; for( row = 1 ; row <= numRowsG ; row++ ) { k = 0 ; feedptr = feedpptrG[row] ; for( i = 1 ; i <= chan_node_noG ; i++ ) { k += feedptr[i]->actual ; } total_feed_in_the_rowG[row] = k ; } fprintf(fpoG,"After Feeds are Added:\n"); fprintf(fpoG,"BLOCK TOTAL CELL LENGTHS OVER/UNDER TARGET\n"); max_length = 0 ; for( i = 1 ; i <= numRowsG ; i++ ) { Aray = pairArrayG[i] ; first_cptr = carrayG[ Aray[1] ] ; last_cptr = carrayG[ Aray[ Aray[0] ] ] ; length = last_cptr->cxcenter + last_cptr->tileptr->right - first_cptr->cxcenter - first_cptr->tileptr->left ; delta_row_len = length - barrayG[i]->desire ; fprintf( fpoG, "%3d %7d %6d\n", i, length , delta_row_len ); if( max_length < length ) { longest_row = i ; max_length = length ; } } fprintf( fpoG, "\nLONGEST Row is:%d Its length is:%d\n", longest_row , max_length ) ; longest_row_lengthG = max_length ; printf("\n longest Row is:%d Its length is:%d\n", longest_row , max_length ) ; } free_cglb_data() { INT i , net ; PINBOXPTR netptr ; ADJASEGPTR adjptr , saveptr ; for( i = 1 ; i <= numRowsG ; i++ ) { Ysafe_free( fdcel_needG[i] ) ; } Ysafe_free( fdcel_needG ) ; Ysafe_free( fdcel_addedG ) ; Ysafe_free( feed_diffS ) ; Ysafe_free( feed_shortS ) ; Ysafe_free( row_rite_classG) ; Ysafe_free( right_most_in_classG) ; Ysafe_free( accumulate_feedS ) ; Ysafe_free( diff_in_rowfeedS ) ; for( net = 1 ; net <= numnetsG ; net++ ) { for( netptr = netarrayG[net]->pins ; netptr ;netptr = netptr->next ) { for( adjptr = netptr->adjptr->next ; adjptr ; adjptr = saveptr ) { saveptr = adjptr->next ; Ysafe_free( adjptr ) ; } netptr->adjptr->next = NULL ; } for( netptr = steinerHeadG[net]->next;netptr;netptr = netptr->next ) { for( adjptr = netptr->adjptr->next ; adjptr ; adjptr = saveptr ) { saveptr = adjptr->next ; Ysafe_free( adjptr ) ; } netptr->adjptr->next = NULL ; } } } graywolf-0.1.4+20170307gite1bf319/src/twsc/config.h000066400000000000000000000024351305746555600211550ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) config.h (Yale) version 4.4 2/17/91" FILE: config.h DESCRIPTION:TimberwolfSC insert file for configuration parameters. CONTENTS: DATE: Mar 27, 1989 REVISIONS: Sun Feb 17 21:11:18 EST 1991 - moved numMacroG to pad.h ----------------------------------------------------------------- */ #ifndef CONFIG_H #define CONFIG_H #ifdef CONFIG_VARS #define EXTERN #else #define EXTERN extern #endif typedef struct macrobox { INT mx ; INT my ; } MACROBOX ; typedef struct rowbox { INT startx ; INT endx ; INT endx1 ; INT startx2 ; INT ypos ; INT desiredL ; } ROWBOX ; EXTERN MACROBOX *macroArrayG ; EXTERN ROWBOX *rowArrayG ; EXTERN INT max_blklengthG ; EXTERN INT route2actG; /* added for placement adjusted for routing */ EXTERN INT track_pitchG; /* used only if global routing is performed */ EXTERN INT gridCellG; /* used only if global routing is performed */ EXTERN INT desiredLG ; EXTERN DOUBLE *macspaceG ; EXTERN INT *padArrayG ; EXTERN INT extraSpaceG ; EXTERN INT coreHeightG ; EXTERN INT coreWidthG ; EXTERN INT separationG ; EXTERN INT spaceG ; EXTERN INT maxHeight ; EXTERN INT lastG ; #undef EXTERN #endif /* CONFIG_H */ graywolf-0.1.4+20170307gite1bf319/src/twsc/configpads.c000066400000000000000000000602151305746555600220200ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: configpads.c DESCRIPTION:Configure pads CONTENTS: DATE: Jan 29, 1989 - added heading. REVISIONS: Jan 29, 1989 - removed message about pad limited designs. Mar 30, 1989 - changed tile datastructure. Apr 30, 1989 - fixed problem with padgroups. Rewrote major sections of the algorithm. Thu Feb 14 02:41:45 EST 1991 - new algorithm for placing pads. Still need to do VARIABLE_PADS. Fri Feb 15 15:13:49 EST 1991 - added VARIABLE PAD code. Sun Feb 17 21:10:35 EST 1991 - added min_pad_spacing. Thu Mar 7 01:52:16 EST 1991 - now perform pad rotations correctly. Tue Mar 19 16:01:40 CST 1991 - added core expansion code. Thu Apr 18 01:45:56 EDT 1991 - fixed problem with align_pads Thu Aug 29 15:44:00 CDT 1991 - added overflow processing code. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) configpads.c version 4.12 11/7/91" ; #endif #include #include #include #include #include /* ***************** STATIC FUNCTION DEFINITIONS ******************* */ static BOOL check_overflow( P1(BOOL retain_pad_groups) ) ; static move_clockwise( P4(INT pad, INT side, INT cw_side, INT moveable_cw) ) ; static move_counterclockwise( P4(INT pad,INT side,INT ccw_side,INT m_ccw ) ) ; static update_pad_position( P3(PADBOXPTR pad,INT current_side, INT move_side) ); static expand_core( P1(INT side) ) ; static INT compare_overflow( P2(INT *side1, INT *side2) ) ; static update_pad_groups( P1(void) ) ; static resort_place_array( P1(void) ) ; static child_constraints(P5(PADBOXPTR pad,INT side,DOUBLE lb,DOUBLE ub,BOOL s)); static place_variable( P3(INT first,INT numpads,INT side) ) ; /* ***************** STATIC VARIABLE DEFINITIONS ******************* */ static INT overflowS[5] ; /* amount of overflow on each side */ static INT side_lengthS[5] ; /* sum of pad lengths on a side */ static INT first_pad_on_sideS[5] ; /* index of first pad on side */ static INT last_pad_on_sideS[5] ; /* index of last pad on side */ static INT pad_extraS ; /* insure that sort works correctly */ align_pads() { INT pad ; /* counter */ INT side ; /* current pad side */ INT last ; /* index of last pad on side */ INT first ; /* index of first pad on side */ INT count ; /* count number of overflow iterations */ INT length ; /* length of current pad */ INT needed ; /* extra space needed on each side */ INT numpads ; /* number of pads on this side */ INT cum_space ; /* cum_space on this side */ INT padspacing ; /* padspacing method for current side*/ INT extra_space ; /* slack on a side */ BOOL overflow_exists ; /* if set, overflow still exists */ BOOL retain_pad_groups ; /* if set, padgroups will not be moved from side */ PADBOXPTR padptr ; /* current pad info */ DOUBLE left_edge ; /* left edge of the placed pad */ DOUBLE extra_space_per_pad ; /* how much left over per pad */ count = 0 ; retain_pad_groups = TRUE ; pad_extraS = 100000 ; do { overflow_exists = check_overflow( retain_pad_groups ) ; if( overflow_exists ){ resort_place_array() ; } if( ++count >= 3 ){ retain_pad_groups = FALSE ; } } while( overflow_exists ) ; update_pad_groups() ; for( side = 1 ; side <= 4 ; side++ ) { if(!(first_pad_on_sideS[side])){ /* there are no pads on this side */ continue ; } extra_space = perdimG[ side%2 ] - side_lengthS[side] ; /* check to see if we have overflow */ if( extra_space <= 0 ){ /* we must perform abut padspacing on this side */ padspacing = ABUT_PADS ; } else { /* do what the user requested */ padspacing = padspacingG ; } first = first_pad_on_sideS[side] ; last = last_pad_on_sideS[side] ; numpads = last - first + 1 ; switch( padspacing ){ case UNIFORM_PADS: extra_space_per_pad = (DOUBLE) extra_space / (DOUBLE) (numpads+1) ; left_edge = (DOUBLE) coreG[side%2][MINI] ; for( pad = 1; pad <= numpads; pad++ ){ padptr = placearrayG[first + pad - 1] ; /* calculate the placement of the left edge of the pad */ left_edge += extra_space_per_pad ; /* now find the center of the current pad */ padptr->position = ((INT) left_edge ) + padptr->length / 2 ; /* now set left edge for next pad */ left_edge += (DOUBLE) (padptr->length + min_pad_spacingG) ; } break ; case ABUT_PADS: extra_space_per_pad = (DOUBLE) extra_space / 2.0 ; left_edge = (DOUBLE) coreG[side%2][MINI] + extra_space_per_pad ; for( pad = 1; pad <= numpads; pad++ ){ padptr = placearrayG[first + pad - 1] ; /* now find the center of the current pad */ padptr->position = ((INT) left_edge ) + padptr->length / 2 ; /* now set left edge for next pad */ left_edge += (DOUBLE) (padptr->length + min_pad_spacingG) ; } break ; case VARIABLE_PADS: /* we now we can fit it on this side */ place_variable( first, numpads, side ) ; break ; case EXACT_PADS: break ; } /* end switch */ } /* end loop on sides */ } /* end align_pads */ /* ***************************************************************** */ static BOOL check_overflow( retain_pad_groups ) BOOL retain_pad_groups ; { INT i ; /* counter */ INT pad ; /* counter */ INT side ; /* current pad side */ INT cw_pad ; /* pad to move in clockwise direction */ INT ccw_pad ; /* pad to move in ccw direction */ INT length ; /* length of current pad */ INT clockwise ; /* the side in the clockwise direction */ INT counterclockwise ; /* the side in the ccw direction */ INT overflow_cw ; /* amount of overflow when pad is moved cw */ INT overflow_ccw ; /* amount of overflow when pad is moved ccw */ INT moveable_cw ; /* size of pad to be moved cw */ INT moveable_ccw ; /* size of pad to be moved ccw */ INT side_open[5] ; /* whether side has been processed */ INT sort_overflow[5] ; /* index for sorted overflow */ INT compare_overflow() ; /* sort the sides for overflow */ PADBOXPTR padptr ; /* current pad info */ /* first accummulate the sum of all the pads on a given side */ /* also find the first and last pad on a given side */ for( side = 1 ; side <= 4 ; side++ ) { overflowS[side] = 0 ; side_lengthS[side] = 0 ; first_pad_on_sideS[side] = 0 ; last_pad_on_sideS[side] = -1 ; } for( pad = 1 ; pad <= numpadsG ; pad++ ) { padptr = placearrayG[pad] ; side = padptr->padside ; length = padptr->length ; /* this will add one too many min_pad_spacing */ /* subtract it below */ side_lengthS[side] += length + min_pad_spacingG ; if(!(first_pad_on_sideS[side])){ first_pad_on_sideS[side] = pad ; } last_pad_on_sideS[side] = pad ; } /* check for overflow on the sides */ for( side = 1 ; side <= 4 ; side++ ) { /* adjust extra min_pad_spacing */ if(first_pad_on_sideS[side]){ /* there are pads on this side */ side_lengthS[side] -= min_pad_spacingG ; } overflowS[side] = side_lengthS[side] - perdimG[ side%2 ] ; } /* check to see if we have overflow */ if( overflowS[L] <= 0 && overflowS[R] <= 0 && overflowS[B] <= 0 && overflowS[T] <= 0 ){ /* there is no overflow */ return( FALSE ) ; } /* overflow exists so resolve the conflict. */ /* first sort the overflow */ for( i = 1 ; i <= 4; i++ ){ /* initialize sort_overflow array */ sort_overflow[i] = i ; side_open[i] = TRUE ; } Yquicksort( &(sort_overflow[1]), 4, sizeof(INT), compare_overflow ); for( i = 1; i <= 4; i++ ){ side = sort_overflow[i] ; side_open[side] = FALSE ; if( overflowS[side] <= 0 ){ continue ; } /* find clockwise side */ clockwise = side + 1 ; if( clockwise > 4 ) clockwise = 1 ; /* wrap around */ /* find counter clockwise side */ counterclockwise = side - 1 ; if( counterclockwise < 1 ) counterclockwise = 4 ; /* wrap around */ do { /* look for the last valid pad on side to move clockwise */ /* make sure side is still open */ cw_pad = 0 ; if( side_open[clockwise] ){ for( pad = last_pad_on_sideS[side];pad >= first_pad_on_sideS[side]; pad-- ){ padptr = placearrayG[pad] ; if( padptr->padside != side ){ /* this means we already moved this pad from this side */ continue ; } if( retain_pad_groups && padptr->hierarchy != NONE ){ /* if the retain_pad_group switch is on, we ignore any */ /* pad in a padgroup */ continue ; } if( padptr->valid_side[ALL] || padptr->valid_side[clockwise] ){ cw_pad = pad ; moveable_cw = padptr->length + min_pad_spacingG ; break ; } } /* end pad = last_pad_on_side... */ } /* end side_open[clockwise... */ /* look for the first valid pad on side to move counterclockwise */ /* make sure side is still open */ ccw_pad = 0 ; if( side_open[counterclockwise] ){ for( pad = first_pad_on_sideS[side]; pad <= last_pad_on_sideS[side]; pad++ ){ padptr = placearrayG[pad] ; if( padptr->padside != side ){ /* this means we already moved this pad from this side */ continue ; } if( retain_pad_groups && padptr->hierarchy != NONE ){ /* if the retain_pad_group switch is on, we ignore any */ /* pad in a padgroup */ continue ; } if( padptr->valid_side[ALL] || padptr->valid_side[counterclockwise] ){ ccw_pad = pad ; moveable_ccw = padptr->length + min_pad_spacingG ; break ; } } /* end pad = first_pad_on_side... */ } /* end side_open[counterclockwise... */ if( cw_pad && ccw_pad ){ /* this is the case where there are two valid pads which can be moved */ /* pick the pad && side which has smaller overflow */ overflow_cw = overflowS[clockwise] + moveable_cw ; ; overflow_ccw = overflowS[counterclockwise] + moveable_ccw ; ; if( overflow_cw <= overflow_ccw ){ move_clockwise( cw_pad, side, clockwise, moveable_cw ) ; } else { move_counterclockwise( ccw_pad, side, counterclockwise, moveable_ccw ) ; } } else if( cw_pad ){ move_clockwise( cw_pad, side, clockwise, moveable_cw ) ; } else if( ccw_pad ){ move_counterclockwise( ccw_pad, side, counterclockwise, moveable_ccw ) ; } else { /* no more pads to move, we need to expand core */ expand_core( side ) ; return( TRUE ) ; } } while( overflowS[side] > 0 ) ; } /* end for( i = 1; i <= 4; i++ ) ... */ /* if we get here, we had some overflow */ return( TRUE ) ; } /* end check_overflow */ static move_clockwise( pad, side, clockwise_side, moveable_cw ) INT pad, side, clockwise_side, moveable_cw ; { PADBOXPTR padptr ; /* current pad info */ /* move pad */ padptr = placearrayG[pad] ; padptr->padside = clockwise_side ; /* determine position */ update_pad_position( padptr, side, clockwise_side ) ; /* reset the overflows */ overflowS[side] -= moveable_cw ; overflowS[clockwise_side] += moveable_cw ; } /* end move_clockwise */ static move_counterclockwise( pad, side, counterclockwise, moveable_ccw ) INT pad, side, counterclockwise, moveable_ccw ; { PADBOXPTR padptr ; /* current pad info */ /* move pad */ padptr = placearrayG[pad] ; padptr->padside = counterclockwise ; update_pad_position( padptr, side, counterclockwise ) ; /* determine position */ /* reset the overflows */ overflowS[side] -= moveable_ccw ; overflowS[counterclockwise] += moveable_ccw ; } /* end move_counterclockwise */ static update_pad_position( padptr, current_side, move_side ) PADBOXPTR padptr ; /* current pad info */ INT current_side ; INT move_side ; { INT dimension ; /* the X or Y dimension */ dimension = move_side % 2 ; switch( current_side ){ case L: padptr->position = coreG[dimension][MINI] - ++pad_extraS; break ; case T: padptr->position = coreG[dimension][MAXI] + ++pad_extraS ; break ; case R: padptr->position = coreG[dimension][MAXI] + ++pad_extraS ; break ; case B: padptr->position = coreG[dimension][MINI] - ++pad_extraS; break ; } /* end switch side ... */ } /* end update_pad_position */ static expand_core( side ) INT side ; { INT i ; /* counter */ INT pad ; /* counter */ INT overflow_amount ; /* amount to expand */ INT amount ; /* amount to add to each pad half of a side */ INT expansion ; /* amount to expand a dimension */ PADBOXPTR padptr ; /* current pad info */ overflow_amount = 0 ; /* determine how much to expand by */ /* normally we assume that all sides can help reduce overflow */ /* if we find that the overflow_amount < 0 or overflow_amount is only */ /* 25% of the overflow on a side, it means that some sides */ /* have non moveable pads. We need to make the overflow amount the given side */ for( i = 1; i <= 4 ; i++ ){ overflow_amount += overflowS[i] ; } if( overflow_amount < 0 || overflow_amount < 0.25 * overflowS[side] ){ overflow_amount = overflowS[side] ; } /* now divide the amount equally in both dimensions */ expansion = overflow_amount / 2 ; if( expansion <= 0 ) expansion = 1 ; amount = expansion / 2 ; coreG[X][MINI] -= amount ; coreG[X][MAXI] += (expansion - amount ) ; coreG[Y][MINI] -= amount ; coreG[Y][MAXI] += (expansion - amount ) ; /* expand in X and Y directions */ /* we to search all the pads since they may not be in order */ for( pad = 1 ; pad <= numpadsG ; pad++ ) { padptr = placearrayG[pad] ; side = padptr->padside ; padptr->position += amount ; } /* now reset the perimeters */ perdimG[X] = coreG[X][MAXI] - coreG[X][MINI] ; perdimG[Y] = coreG[Y][MAXI] - coreG[Y][MINI] ; } /* end expand_core */ static INT compare_overflow( side1, side2 ) INT *side1, *side2 ; { /* sort largest to smallest */ return( overflowS[*side2] - overflowS[*side1] ) ; } /* end compare_overflow */ static INT compare_placearray( padptr1, padptr2 ) PADBOXPTR *padptr1, *padptr2 ; { PADBOXPTR pad1, pad2; pad1 = *padptr1 ; pad2 = *padptr2 ; if( pad1->padside != pad2->padside) { return( pad1->padside - pad2->padside ) ; } if( pad1->position < pad2->position ){ return( -1 ) ; } else if( pad1->position > pad2->position ){ return( 1 ) ; } else { return( 0 ) ; } } /* end compare_placearray */ static resort_place_array() { Yquicksort( &(placearrayG[1]), numpadsG, sizeof(PADBOXPTR), compare_placearray ); } /* end resort_place_array */ /* ***************************************************************** */ /* set the lo_pos and hi_pos fields for the pads */ static update_pad_groups() { INT i ; /* pad counter */ DOUBLE lobound ; /* lower bound on position */ DOUBLE hibound ; /* upper bound on position */ BOOL spacing_restricted ; /* whether spacing is restricted */ PADBOXPTR pad ; /* current pad */ if( padspacingG != VARIABLE_PADS ){ return ; } /* now update the lo_pos and hi_pos fields of the pad */ for( i = 1 ; i <= totalpadsG; i++ ) { pad = padarrayG[i]; /* make copy of these we don't want to change roots copy */ lobound = pad->lowerbound ; hibound = pad->upperbound ; spacing_restricted = pad->fixed ; if( pad->padtype == PADGROUPTYPE && pad->hierarchy == ROOT ){ child_constraints( pad, pad->padside, lobound, hibound, spacing_restricted ) ; } else if( pad->padtype == PADTYPE && pad->hierarchy == NONE ) { /* the case of a pad that is not in a padgroup */ calc_constraints( pad, pad->padside, &lobound, &hibound, &spacing_restricted, &(pad->lo_pos), &(pad->hi_pos) ) ; } } } /* end update_pad_groups */ /* this will set the constaints for pad groups and children of them */ static child_constraints( pad, side, lb, ub, spacing_restricted ) PADBOXPTR pad ; INT side ; DOUBLE lb, ub ; BOOL spacing_restricted ; { INT i ; /* pad counter */ INT howmany ; /* number of children */ PADBOXPTR child ; /* current child */ calc_constraints( pad, side, &lb, &ub, &spacing_restricted, &(pad->lo_pos), &(pad->hi_pos) ); if( pad->padtype != PADTYPE ){ howmany = pad->children[HOWMANY] ; for( i = 1 ;i <= howmany ; i++ ){ child = padarrayG[ pad->children[i] ] ; child_constraints( child, side, lb, ub,spacing_restricted ) ; } } } /* end child_constraints */ /* ***************************************************************** */ calc_constraints( pad, side, lb, ub, spacing_restricted,lowpos, uppos ) PADBOXPTR pad ; INT side ; DOUBLE *lb, *ub ; BOOL *spacing_restricted ; INT *lowpos, *uppos ; { DOUBLE lowbound, hibound ; /* determine spacing restrictions */ if( *spacing_restricted ){ /* this is the case that the spacing has been restricted */ if( pad->fixed ){ /* if the padgroup bounds have been fixed, */ /* force position to be within bound */ /* assume we are ok and then correct it */ lowbound = pad->lowerbound ; if( lowbound < *lb ){ lowbound = *lb ; } if( lowbound > *ub ){ lowbound = *ub ; } hibound = pad->upperbound ; if( hibound < *lb ){ hibound = *lb ; } if( hibound > *ub ){ hibound = *ub ; } } else { /* this pad is not fixed use the given ub and lb */ lowbound = *lb ; hibound = *ub ; } } else { if( pad->fixed ){ /* the padgroup bounds have not been fixed */ /* just take the pad's restricted position */ lowbound = pad->lowerbound; hibound = pad->upperbound; *spacing_restricted = TRUE ; } } if( *spacing_restricted ){ *lowpos = (INT) ( lowbound * (DOUBLE)perdimG[side%2] ) ; *lowpos += coreG[side%2][MINI] ; *uppos = (INT) ( hibound * (DOUBLE)perdimG[side%2] ) ; *uppos += coreG[side%2][MINI] ; } else { *lowpos = -1 ; *uppos = PINFINITY ; } /* **** END spacing restriction calculations *** */ /* return low bound */ *lb = lowbound ; *ub = hibound ; } /* end calc_constraints */ /* ***************************************************************** */ static place_variable( first, numpads, side ) INT first, numpads, side ; { INT pad ; /* counter */ INT left_edge ; /* current left edge of pad */ INT right_edge ; /* current right edge of pad */ INT half_length ; /* half the span of a pad */ INT valid_left_edge ;/* this position is open for the pad leftedge*/ INT valid_right_edge;/* this position is open for the pad rightedge*/ PADBOXPTR padptr ; /* current pad info */ valid_left_edge = 0 ; for( pad = 0; pad < numpads; pad++ ){ padptr = placearrayG[first + pad ] ; /* now find the left edge of the current pad */ half_length = padptr->length / 2 ; left_edge = padptr->position - half_length ; valid_left_edge = MAX( valid_left_edge, padptr->lo_pos ) ; if( left_edge < valid_left_edge ){ /* need to remove overlap */ /* so left edge of pad becomes valid_left_edge */ left_edge = valid_left_edge ; /* calculate new padptr position */ padptr->position = valid_left_edge + half_length ; } /* now calculate the new valid left edge */ valid_left_edge = left_edge + padptr->length + min_pad_spacingG ; } valid_right_edge = coreG[side%2][MAXI] ; /* now condense pads if they exceed the length of the side */ for( pad = numpads-1; pad >= 0; pad-- ){ padptr = placearrayG[first + pad] ; /* now find the left edge of the current pad */ half_length = padptr->length / 2 ; half_length = padptr->length - half_length ; right_edge = padptr->position + half_length ; valid_right_edge = MIN( valid_right_edge, padptr->hi_pos ) ; if( right_edge > valid_right_edge ){ /* need to remove overlap */ /* so left edge of pad becomes valid_left_edge */ right_edge = valid_right_edge ; /* calculate new padptr position */ padptr->position = valid_right_edge - half_length ; } else { break ; } /* now calculate the new valid right edge */ valid_right_edge = right_edge - padptr->length - min_pad_spacingG ; } } /* end place_variable */ /* ***************************************************************** */ dimension_pads() { INT i ; /* pad counter */ PADBOXPTR pad ; /* current pad */ PINBOXPTR pin ; /* current pin */ CBOXPTR cptr ; /* current cell */ for( i = 1 ; i <= numpadsG; i++ ) { pad = padarrayG[i]; cptr = carrayG[ pad->cellnum ] ; switch( pad->padside) { case L: cptr->cxcenter = coreG[X][MINI] - pad->height / 2 ; cptr->cycenter = pad->position ; break; case T: cptr->cxcenter = pad->position ; cptr->cycenter = coreG[Y][MAXI] + pad->height / 2 ; break; case R: cptr->cxcenter = coreG[X][MAXI] + pad->height / 2 ; cptr->cycenter = pad->position ; break; case B: cptr->cxcenter = pad->position ; cptr->cycenter = coreG[Y][MINI] - pad->height / 2 ; break; } /* end switch on side */ /* now update the pins */ for( pin = cptr->pins; pin ; pin = pin->nextpin ){ REL_POST( cptr->corient, pin->txpos[1], pin->typos[1], /* result */ pin->txpos[0], pin->typos[0], /* cell relative */ 0, 0 ) ; /* cell relative */ /* global positions */ pin->xpos = pin->txpos[1] + cptr->cxcenter ; pin->ypos = pin->typos[1] + cptr->cycenter ; } } } /* dimension_pads */ /* ***************************************************************** */ orient_pads() { INT i ; /* counter */ PADBOXPTR pad ; /* current pad info */ CBOXPTR cptr ; /* current cell */ for( i = 1; i <= numpadsG; i++ ){ pad = placearrayG[i]; cptr = carrayG[ pad->cellnum ] ; switch( pad->padside) { case L: /* rotate 270 | -90 */ cptr->corient = (SHORT) 7 ; cptr->cycenter = cptr->cxcenter; break; case T: /* rotate180 */ cptr->corient = (SHORT) 3 ; break; case R: /* rotate90 */ cptr->corient = (SHORT) 6 ; cptr->cycenter = cptr->cxcenter; break; case B: cptr->corient = (SHORT) 0 ; break; default: OUT1("\nNON-PADS or PAD w/o side not rotated "); break; } } } /* end orient_pads */ /* ***************************************************************** */ graywolf-0.1.4+20170307gite1bf319/src/twsc/configure.c000066400000000000000000000767311305746555600216760ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * Copyright (C) 2013 Tim Edwards * Copyright (C) 2015 Staf Verhaegen * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: configure.c DESCRIPTION:cell topology configuration routines. CONTENTS: configure() DATE: Mar 27, 1989 REVISIONS: Fri Jan 25 18:29:22 PST 1991 - fixed problem with different row heights. Tue Mar 19 16:27:35 CST 1991 - fixed calculation problem with rowSep. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) configure.c (Yale) version 4.12 3/19/91" ; #endif #endif #define CONFIG_VARS #include "standard.h" #include "config.h" #include "parser.h" #include "pads.h" #include "main.h" #include "readpar.h" #include /* * Configure the rows of standard cells along with possibly * one or more macro blocks; The macro blocks may be * specified as: MUL,MUR,MLL,MLR, ML,MR,MB,MT, MM, MTT, or MBB */ #define MAXMACRO 50 INT totalRG ; BOOL doubleback_rows_start_at_oneG ; extern INT individual_rowSepsG ; extern INT total_row_lengthG ; extern DOUBLE indentG ; extern DOUBLE *relativeLenG ; extern DOUBLE *rowSepsG ; extern INT *rowSepsAbsG ; /* static definitions */ static INT heightS ; static INT widthS ; static INT mttshiftS ; static INT mbbshiftS ; configure() { INT block ; INT pad ; INT row ; INT macro ; INT totalBlock ; DOUBLE ratio ; BBOXPTR *oldbarray ; BBOXPTR boxptr ; DOUBLE totalF ; DOUBLE modulation ; DOUBLE constant ; DOUBLE dsumS ; INT topRowY , centerY ; INT k ; INT macNumber ; INT trow ; INT brow ; INT rows ; INT bot ; INT left ; INT edge ; INT rite ; INT top ; INT padside ; INT middleRow ; INT URmacro , Rmacro ; INT count_mtt , count_mbb ; INT Mf ; INT rowcenter ; INT rowtop ; INT l, r, b, t ; INT xc, yc ; CBOXPTR padptr ; TIBOXPTR tptr ; if (macroArrayG) { Ysafe_free(macroArrayG); } macroArrayG = (MACROBOX *) Ysafe_malloc((MAXMACRO + 1) * sizeof(MACROBOX)); macNumber = 0 ; numRowsG = numRowsG ; if (rowArrayG) { Ysafe_free(rowArrayG); } rowArrayG = (ROWBOX *) Ysafe_malloc( (numRowsG + 1) * sizeof( ROWBOX ) ) ; for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].endx1 = -1 ; rowArrayG[row].startx2 = -1 ; } /* Total cell length = totalRowLength = totalRG ; numRowsG is entered by the user ; rowSepG and rowSepAbsG are also entered by the user ; row center-to-center spacing = (rowSepG + 1) * rowHeight + rowSepAbsG ; */ totalRG = celllenG ; rowHeightG = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { rowHeightG += barrayG[row]->btop - barrayG[row]->bbottom ; } rowHeightG /= numRowsG ; /* Let bottom = 0 and top = (numRowsG - 1) * ((rowSepG + 1) * rowHeightG + rowSepAbsG) + rowHeightG / 2 ; Position of each row n is as follows: starts at x = 0 ; y = (n - 1) * ((rowSepG + 1) * rowHeightG + rowSepAbsG) + rowHeightG / 2 ; */ if( intelG ) { if( doubleback_rows_start_at_oneG ) { for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].startx = 0 ; if( row % 2 == 1 ) { rowArrayG[row].ypos = (row / 2) * (rowSepG + 2) * rowHeightG + rowSepAbsG + rowHeightG / 2 ; } else { rowArrayG[row].ypos = ((row / 2) - 1) * (rowSepG + 2) * rowHeightG + rowSepAbsG + 3 * rowHeightG / 2 ; } } } else { for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].startx = 0 ; if( row % 2 == 1 ) { rowArrayG[row].ypos = (row / 2) * (rowSepG + 2) * rowHeightG + rowSepAbsG + rowHeightG / 2 ; } else { rowArrayG[row].ypos = ((row/2) - 1) * (rowSepG + 2) * rowHeightG + rowSepG * rowHeightG + rowSepAbsG + 3 * rowHeightG / 2 ; } } } } else { if( individual_rowSepsG > 0 ) { for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].startx = 0 ; if( row == 1 ){ rowcenter = barrayG[1]->bheight / 2 ; } else { rowcenter = rowtop + rowSepsG[row] * barrayG[row]->bheight + rowSepsAbsG[row] + barrayG[row]->bheight / 2 ; } rowArrayG[row].ypos = rowcenter ; rowtop = rowcenter + barrayG[row]->bheight - barrayG[row]->bheight / 2; /* ***** the old way - does not take into account different row heights rowArrayG[row].ypos = (rowSepsG[row] + 1.0) * rowHeightG + rowSepsAbsG[row] + rowArrayG[row-1].ypos ; */ } } else { /* take into account different row heights */ for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].startx = 0 ; if( row == 1 ){ rowcenter = barrayG[1]->bheight / 2 ; } else { rowcenter = rowtop + rowSepG * barrayG[row]->bheight + rowSepAbsG + barrayG[row]->bheight / 2 ; } rowArrayG[row].ypos = rowcenter ; rowtop = rowcenter + barrayG[row]->bheight - barrayG[row]->bheight / 2; /* ***** the old way - does not take into account different row heights rowArrayG[row].ypos = (row - 1) * ((rowSepG + 1.0) * rowHeightG + rowSepAbsG) + rowHeightG / 2 ; */ } } } if( numRowsG > 1 ) { totalF = 0.0 ; for( r = 1 ; r <= numRowsG ; r++ ) { totalF += relativeLenG[r] ; } topRowY = rowArrayG[numRowsG].ypos ; centerY = (topRowY + rowArrayG[1].ypos) / 2 ; Mf = (INT) ( (DOUBLE) totalRG / totalF ) ; dsumS = 0.0 ; for( r = 1 ; r <= numRowsG ; r++ ) { dsumS += relativeLenG[r] * (DOUBLE)(ABS(rowArrayG[r].ypos - centerY)); } dsumS /= totalF ; dsumS *= 1.0 / (DOUBLE)( topRowY - centerY ) ; constant = 1.0 + (1.0 - indentG) * (1.0 - dsumS) ; for( r = 1 ; r <= numRowsG ; r++ ) { rowArrayG[r].endx = (INT)((DOUBLE) Mf * constant * relativeLenG[r]); modulation = 1.0 + (1.0 - indentG) * ( ((DOUBLE)(ABS(rowArrayG[r].ypos - centerY)) / (DOUBLE)(topRowY - centerY)) - dsumS); rowArrayG[r].desiredL = (INT) ( (DOUBLE) Mf * relativeLenG[r] * modulation ) ; } } else { rowArrayG[1].endx = totalRG ; rowArrayG[1].desiredL = rowArrayG[1].endx ; } /* Define extra spaceG = rowSepG * rowHeightG + rowSepAbsG */ extraSpaceG = rowSepG * rowHeightG + rowSepAbsG; for( k = 1 ; k <= 15 ; k++ ) { if( macspaceG[k] < 0.0 ) { macspaceG[k] = extraSpaceG ; } else { macspaceG[k] *= rowHeightG ; } } middleRow = numRowsG / 2 ; /* Now its time to add in a macro block. Suppose we have such a macro block with a location specification as: MUL,MUR,MLL,MLR, ML,MR,MB,MT, or MM ---macro is heightS units tall and widthS units wide. */ if (padArrayG) { Ysafe_free(padArrayG); } padArrayG = (INT *) Ysafe_malloc( (numtermsG + 1) * sizeof( INT ) ) ; for( pad = 1 ; pad <= numtermsG ; pad++ ) { padArrayG[pad] = 0 ; } numMacroG = 0 ; for( pad = numcellsG + 1 ; pad <= lastpadG ; pad++ ) { padside = carrayG[pad]->padptr->padside ; if( padside == MUL || padside == ML || padside == MLL ) { padArrayG[++numMacroG] = pad ; } } for( pad = numcellsG + 1 ; pad <= lastpadG ; pad++ ) { padside = carrayG[pad]->padptr->padside ; if( padside == MT || padside == MM || padside == MB ) { padArrayG[++numMacroG] = pad ; } } for( pad = numcellsG + 1 ; pad <= lastpadG ; pad++ ) { padside = carrayG[pad]->padptr->padside ; if( padside == MUR ) { padArrayG[++numMacroG] = pad ; URmacro = numMacroG ; } } for( pad = numcellsG + 1 ; pad <= lastpadG ; pad++ ) { padside = carrayG[pad]->padptr->padside ; if( padside == MR ) { padArrayG[++numMacroG] = pad ; Rmacro = numMacroG ; } } for( pad = numcellsG + 1 ; pad <= lastpadG; pad++ ) { padside = carrayG[pad]->padptr->padside ; if( padside == MLR ) { padArrayG[++numMacroG] = pad ; } } for( macro = 1 ; macro <= numMacroG ; macro++ ) { pad = padArrayG[macro] ; padptr = carrayG[pad] ; tptr = padptr->tileptr ; l = tptr->left ; r = tptr->right ; b = tptr->bottom ; t = tptr->top ; YtranslateT( &l, &b, &r, &t, (INT) padptr->corient ) ; heightS = t - b ; widthS = r - l ; macNumber++ ; switch( padptr->padptr->padside ) { case MUL : for( row = numRowsG ; row >= 1 ; row-- ) { if( rowArrayG[row].ypos + (rowSepG * rowHeightG + rowSepAbsG) * 0.33 <= rowArrayG[numRowsG].ypos - heightS ) { break ; } } /* shorten the rows between row + 1 and numRowsG by: widthS + macspaceG[MUL] ; Number of "rows" affected is: numRowsG - row ; Add to all "rows" by the amount: (rows * (widthS + macspaceG[MUL]) ) / numRowsG ; */ rows = numRowsG - row ; for( row++ ; row <= numRowsG ; row++ ) { rowArrayG[row].startx = widthS + macspaceG[MUL] ; rowArrayG[row].desiredL -= widthS + macspaceG[MUL] ; } for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].endx += (rows * (widthS + macspaceG[MUL]) ) / numRowsG ; rowArrayG[row].desiredL += (rows * (widthS + macspaceG[MUL]) ) / numRowsG ; } macroArrayG[macNumber].mx = widthS / 2 ; macroArrayG[macNumber].my = (rowArrayG[numRowsG].ypos + rowHeightG / 2) - heightS / 2 ; break ; case MUR : for( row = numRowsG ; row >= 1 ; row-- ) { if( rowArrayG[row].ypos + (rowSepG * rowHeightG + rowSepAbsG) * 0.33 <= rowArrayG[numRowsG].ypos - heightS ) { break ; } } /* shorten the rows between row + 1 and numRowsG by: widthS + macspaceG[MUR] ; Number of "rows" affected is: numRowsG - row ; Add to all "rows" by the amount: (rows * (widthS + macspaceG[MUR]) ) / numRowsG ; */ rows = numRowsG - row ; for( row++ ; row <= numRowsG ; row++ ) { rowArrayG[row].endx -= widthS + macspaceG[MUR] ; rowArrayG[row].desiredL -= widthS + macspaceG[MUR] ; } for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].endx += (rows * (widthS + macspaceG[MUR]) ) / numRowsG ; rowArrayG[row].desiredL += (rows * (widthS + macspaceG[MUR]) ) / numRowsG ; } macroArrayG[macNumber].mx = rowArrayG[numRowsG].endx + macspaceG[MUR] + widthS / 2 ; macroArrayG[macNumber].my = (rowArrayG[numRowsG].ypos + rowHeightG / 2) - heightS / 2 ; break ; case MLL : for( row = 1 ; row <= numRowsG ; row++ ) { if( rowArrayG[row].ypos - (rowSepG * rowHeightG + rowSepAbsG) * 0.33 >= rowArrayG[1].ypos + heightS ) { break ; } } /* shorten the rows between 1 and row - 1 by: widthS + macspaceG[MLL] ; Number of "rows" affected is: row - 1 ; Add to all "rows" by the amount: (rows * (widthS + macspaceG[MLL]) ) / numRowsG ; */ rows = row - 1 ; for( row-- ; row >= 1 ; row-- ) { rowArrayG[row].startx = widthS + macspaceG[MLL] ; rowArrayG[row].desiredL -= widthS + macspaceG[MLL] ; } for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].endx += (rows * (widthS + macspaceG[MLL]) ) / numRowsG ; rowArrayG[row].desiredL += (rows * (widthS + macspaceG[MLL]) ) / numRowsG ; } macroArrayG[macNumber].mx = widthS / 2 ; macroArrayG[macNumber].my = (rowArrayG[1].ypos - rowHeightG / 2) + heightS / 2 ; break ; case MLR : for( row = 1 ; row <= numRowsG ; row++ ) { if( rowArrayG[row].ypos - (rowSepG * rowHeightG + rowSepAbsG) * 0.33 >= rowArrayG[1].ypos + heightS ) { break ; } } /* shorten the rows between 1 and row - 1 by: widthS + macspaceG[MLR] ; Number of "rows" affected is: row - 1 ; Add to all "rows" by the amount: (rows * (widthS + macspaceG[MLR]) ) / numRowsG ; */ rows = row - 1 ; for( row-- ; row >= 1 ; row-- ) { rowArrayG[row].endx -= widthS + macspaceG[MLR] ; rowArrayG[row].desiredL -= widthS + macspaceG[MLR] ; } for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].endx += (rows * (widthS + macspaceG[MLR]) ) / numRowsG ; rowArrayG[row].desiredL += (rows * (widthS + macspaceG[MLR]) ) / numRowsG ; } if( URmacro != 0 ) { macroArrayG[URmacro].mx += (rows * (widthS + macspaceG[MLR]) ) / numRowsG ; } if( Rmacro != 0 ) { macroArrayG[Rmacro].mx += (rows * (widthS + macspaceG[MLR]) ) / numRowsG ; } macroArrayG[macNumber].mx = rowArrayG[1].endx + macspaceG[MLR] + widthS / 2 ; macroArrayG[macNumber].my = (rowArrayG[1].ypos - rowHeightG / 2) + heightS / 2 ; break ; case ML : bot = rowArrayG[middleRow].ypos - heightS / 2 ; top = bot + heightS ; for( row = 1 ; row <= numRowsG ; row++ ) { if( rowArrayG[row].ypos - rowHeightG / 2 - (rowSepG * rowHeightG + rowSepAbsG) * 0.33 >= top ) { break ; } } trow = row ; for( row = numRowsG ; row >= 1 ; row-- ) { if( rowArrayG[row].ypos + rowHeightG / 2 + (rowSepG * rowHeightG + rowSepAbsG) * 0.33 <= bot ) { break ; } } brow = row ; /* shorten the rows between brow and trow by: widthS + macspaceG[ML] ; Number of "rows" affected is: trow - brow - 1 ; Add to all "rows" by the amount: (rows * (widthS + macspaceG[ML]) ) / numRowsG ; */ rows = trow - brow - 1 ; for( row = brow + 1 ; row < trow ; row++ ) { rowArrayG[row].startx = widthS + macspaceG[ML] ; rowArrayG[row].desiredL -= widthS + macspaceG[ML] ; } for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].endx += (rows * (widthS + macspaceG[ML]) ) / numRowsG ; rowArrayG[row].desiredL += (rows * (widthS + macspaceG[ML]) ) / numRowsG ; } macroArrayG[macNumber].mx = widthS / 2 ; macroArrayG[macNumber].my = rowArrayG[middleRow].ypos; break ; case MR : bot = rowArrayG[middleRow].ypos - heightS / 2 ; top = bot + heightS ; for( row = 1 ; row <= numRowsG ; row++ ) { if( rowArrayG[row].ypos - rowHeightG / 2 - (rowSepG * rowHeightG + rowSepAbsG) * 0.33 >= top ) { break ; } } trow = row ; for( row = numRowsG ; row >= 1 ; row-- ) { if( rowArrayG[row].ypos + rowHeightG / 2 + (rowSepG * rowHeightG + rowSepAbsG) * 0.33 <= bot ) { break ; } } brow = row ; /* shorten the rows between brow and trow by: widthS + macspaceG[MR] ; Number of "rows" affected is: trow - brow - 1 ; Add to all "rows" by the amount: (rows * (widthS + macspaceG[MR]) ) / numRowsG ; */ rows = trow - brow - 1 ; for( row = brow + 1 ; row < trow ; row++ ) { rowArrayG[row].endx -= widthS + macspaceG[MR] ; rowArrayG[row].desiredL -= widthS + macspaceG[MR] ; } for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].endx += (rows * (widthS + macspaceG[MR]) ) / numRowsG ; rowArrayG[row].desiredL += (rows * (widthS + macspaceG[MR]) ) / numRowsG ; } if( URmacro != 0 ) { macroArrayG[URmacro].mx += (rows * (widthS + macspaceG[MR]) ) / numRowsG ; } macroArrayG[macNumber].mx = rowArrayG[middleRow].endx + macspaceG[MR] + widthS / 2 ; macroArrayG[macNumber].my = rowArrayG[middleRow].ypos; break ; case MM : bot = rowArrayG[middleRow].ypos - heightS / 2 ; top = bot + heightS ; /* left = (rowArrayG[middleRow].startx + rowArrayG[middleRow].endx ) / 2 - widthS / 2 ; */ left = (rowArrayG[middleRow].startx + rowArrayG[middleRow].endx ) / 2 ; rite = left + widthS ; for( row = 1 ; row <= numRowsG ; row++ ) { if( rowArrayG[row].ypos - rowHeightG / 2 - (rowSepG * rowHeightG + rowSepAbsG) * 0.67 >= top ) { break ; } } trow = row ; for( row = numRowsG ; row >= 1 ; row-- ) { if( rowArrayG[row].ypos + rowHeightG / 2 + (rowSepG * rowHeightG + rowSepAbsG) * 0.67 <= bot ) { break ; } } brow = row ; /* split the rows between brow and trow by: widthS + 2 * macspaceG[MM] ; Number of "rows" affected is: trow - brow - 1 ; Add to all "rows" by the amount: (rows * (widthS + 2 * macspaceG[MM]) ) / numRowsG ; */ rows = trow - brow - 1 ; for( row = brow + 1 ; row < trow ; row++ ) { rowArrayG[row].endx1 = left - macspaceG[MM] ; rowArrayG[row].startx2 = rite + macspaceG[MM] ; rowArrayG[row].desiredL -= widthS + 2 * macspaceG[MM]; } for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].endx += (rows * (widthS + 2 * macspaceG[MM]) ) / numRowsG ; rowArrayG[row].desiredL += (rows * (widthS + 2 * macspaceG[MM]) ) / numRowsG ; } macroArrayG[macNumber].mx = (left + rite) / 2 ; macroArrayG[macNumber].my = (bot + top) / 2 ; break ; case MB : bot = rowArrayG[1].ypos - rowHeightG / 2 ; top = bot + heightS ; left = (rowArrayG[1].startx + rowArrayG[1].endx ) / 2 - widthS / 2 ; rite = left + widthS ; for( row = 1 ; row <= numRowsG ; row++ ) { if( rowArrayG[row].ypos - rowHeightG / 2 - (rowSepG * rowHeightG + rowSepAbsG) * 0.67 >= top ) { break ; } } trow = row ; brow = 0 ; /* split the rows between brow and trow by: widthS + 2 * macspaceG[MB] ; Number of "rows" affected is: trow - brow - 1 ; Add to all "rows" by the amount: (rows * (widthS + 2 * macspaceG[MB]) ) / numRowsG ; */ rows = trow - brow - 1 ; for( row = brow + 1 ; row < trow ; row++ ) { rowArrayG[row].endx1 = left - macspaceG[MB] ; rowArrayG[row].startx2 = rite + macspaceG[MB] ; rowArrayG[row].desiredL -= widthS + 2 * macspaceG[MB]; } for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].endx += (rows * (widthS + 2 * macspaceG[MB]) ) / numRowsG ; rowArrayG[row].desiredL += (rows * (widthS + 2 * macspaceG[MB]) ) / numRowsG ; } macroArrayG[macNumber].mx = (left + rite) / 2 ; macroArrayG[macNumber].my = (bot + top) / 2 ; break ; case MT : top = rowArrayG[numRowsG].ypos + rowHeightG / 2 ; bot = top - heightS ; left = (rowArrayG[numRowsG].startx + rowArrayG[numRowsG].endx ) / 2 - widthS / 2 ; rite = left + widthS ; trow = numRowsG + 1 ; for( row = numRowsG ; row >= 1 ; row-- ) { if( rowArrayG[row].ypos + rowHeightG / 2 + (rowSepG * rowHeightG + rowSepAbsG) * 0.67 <= bot ) { break ; } } brow = row ; /* split the rows between brow and trow by: widthS + 2 * macspaceG[MT] ; Number of "rows" affected is: trow - brow - 1 ; Add to all "rows" by the amount: (rows * (widthS + 2 * macspaceG[MT]) ) / numRowsG ; */ rows = trow - brow - 1 ; for( row = brow + 1 ; row < trow ; row++ ) { rowArrayG[row].endx1 = left - macspaceG[MT] ; rowArrayG[row].startx2 = rite + macspaceG[MT] ; rowArrayG[row].desiredL -= widthS + 2 * macspaceG[MT]; } for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].endx += (rows * (widthS + 2 * macspaceG[MT]) ) / numRowsG ; rowArrayG[row].desiredL += (rows * (widthS + 2 * macspaceG[MT]) ) / numRowsG ; } macroArrayG[macNumber].mx = (left + rite) / 2 ; macroArrayG[macNumber].my = (bot + top) / 2 ; break ; default: fprintf(fpoG,"screwup in finding padside\n"); YexitPgm(PGMFAIL); break ; } } /* * Now its time to generate a pad placement around the * periphery of the just defined core topology. * First determine coreWidthG and coreHeight. */ coreHeightG = rowArrayG[numRowsG].ypos + rowHeightG - rowHeightG / 2 ; coreWidthG = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { if( rowArrayG[row].endx > coreWidthG ) { coreWidthG = rowArrayG[row].endx ; } } for( macro = 1 ; macro <= numMacroG ; macro++ ) { pad = padArrayG[macro] ; padptr = carrayG[pad] ; tptr = padptr->tileptr ; l = tptr->left ; r = tptr->right ; b = tptr->bottom ; t = tptr->top ; YtranslateT( &l, &b, &r, &t, (INT) padptr->corient ) ; edge = macroArrayG[macro].mx + r ; if( edge > coreWidthG ) { coreWidthG = edge ; } } /* * Add in the MTT and MBB macros, if there are any */ mbbshiftS = 0 ; heightS = 0 ; widthS = 0 ; count_mbb = 0 ; for( pad = numcellsG + 1 ; pad <= lastpadG ; pad++ ) { padptr = carrayG[pad] ; if( padptr->padptr->padside == MBB ) { tptr = padptr->tileptr ; l = tptr->left ; r = tptr->right ; b = tptr->bottom ; t = tptr->top ; YtranslateT( &l, &b, &r, &t, (INT) padptr->corient ) ; if( t - b > heightS ){ heightS = t - b ; } widthS += r - l ; count_mbb++ ; } } if( count_mbb > 0 ) { mbbshiftS = heightS + rowSepG * rowHeightG + rowSepAbsG; /* * Shift all rows up by heightS + rowSepG * rowHeightG + rowSepAbsG */ for( row = 1 ; row <= numRowsG ; row++ ) { rowArrayG[row].ypos += mbbshiftS ; } coreHeightG += mbbshiftS ; if( widthS > coreWidthG ) { coreWidthG = widthS ; } spaceG = coreWidthG - widthS ; separationG = spaceG / (count_mbb + 1) ; if( separationG < 0 ) { separationG = 0 ; } maxHeight = heightS ; heightS = 0 ; widthS = 0 ; lastG = separationG ; for( pad = numcellsG + 1 ; pad <= lastpadG ; pad++ ) { padptr = carrayG[pad] ; if( padptr->padptr->padside == MBB ) { tptr = padptr->tileptr ; l = tptr->left ; r = tptr->right ; b = tptr->bottom ; t = tptr->top ; YtranslateT( &l, &b, &r, &t, (INT) padptr->corient ) ; heightS = t - b ; widthS = r - l ; padptr->cxcenter = lastG + widthS / 2 ; padptr->cycenter = maxHeight - heightS / 2 - 1 ; lastG += separationG + widthS ; } } } mttshiftS = 0 ; heightS = 0 ; widthS = 0 ; count_mtt = 0 ; for( pad = numcellsG + 1 ; pad <= lastpadG ; pad++ ) { padptr = carrayG[pad] ; if( padptr->padptr->padside == MTT ) { tptr = padptr->tileptr ; l = tptr->left ; r = tptr->right ; b = tptr->bottom ; t = tptr->top ; YtranslateT( &l, &b, &r, &t, (INT) padptr->corient ) ; if( t - b > heightS ){ heightS = t - b ; } widthS += r - l ; count_mtt++ ; } } if( count_mtt > 0 ) { mttshiftS = heightS + rowSepG * rowHeightG + rowSepAbsG; coreHeightG += mttshiftS ; if( widthS > coreWidthG ) { coreWidthG = widthS ; } spaceG = coreWidthG - widthS ; separationG = spaceG / (count_mtt + 1) ; if( separationG < 0 ) { separationG = 0 ; } heightS = 0 ; widthS = 0 ; lastG = separationG ; for( pad = numcellsG + 1 ; pad <= lastpadG ; pad++ ) { padptr = carrayG[pad] ; if( padptr->padptr->padside == MTT ) { tptr = padptr->tileptr ; l = tptr->left ; r = tptr->right ; b = tptr->bottom ; t = tptr->top ; YtranslateT( &l, &b, &r, &t, (INT) padptr->corient ) ; heightS = t - b ; widthS = r - l ; padptr->cxcenter = lastG + widthS / 2 ; padptr->cycenter = (coreHeightG - mttshiftS) + rowSepG * rowHeightG + rowSepAbsG + heightS / 2 ; lastG += separationG + widthS ; } } } /* * Now its time to set the positions of the macros */ for( macro = 1 ; macro <= numMacroG ; macro++ ) { pad = padArrayG[macro] ; carrayG[pad]->cxcenter = macroArrayG[macro].mx ; carrayG[pad]->cycenter = macroArrayG[macro].my + mbbshiftS ; } /* * Now its time to blastG away the old barrayG and * generate the new one. */ /* * Find the number of blocks */ block = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { block++ ; if( rowArrayG[row].endx1 > 0 ) { block++ ; } } totalBlock = block ; oldbarray = barrayG ; barrayG = (BBOXPTR *) Ysafe_malloc( (totalBlock + 1) * sizeof(BBOXPTR) ) ; for( block = 1 ; block <= totalBlock ; block++ ) { barrayG[block] = (BBOXPTR) Ysafe_malloc( sizeof(BBOX) ) ; } block = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { boxptr = oldbarray[row] ; if( rowArrayG[row].endx1 > 0 ) { block++ ; barrayG[block]->bxcenter = (rowArrayG[row].startx + rowArrayG[row].endx1 ) / 2 ; barrayG[block]->bycenter = rowArrayG[row].ypos ; barrayG[block]->bleft = rowArrayG[row].startx - barrayG[block]->bxcenter ; barrayG[block]->bright = rowArrayG[row].endx1 - barrayG[block]->bxcenter ; barrayG[block]->bbottom = boxptr->bbottom ; barrayG[block]->btop = boxptr->btop ; barrayG[block]->bheight = boxptr->btop - boxptr->bbottom ; barrayG[block]->blength = rowArrayG[row].endx1 - rowArrayG[row].startx ; barrayG[block]->bclass = boxptr->bclass ; barrayG[block]->borient = boxptr->borient ; barrayG[block]->oldsize = 0 ; block++ ; barrayG[block]->bxcenter = (rowArrayG[row].startx2 + rowArrayG[row].endx ) / 2 ; barrayG[block]->bycenter = rowArrayG[row].ypos ; barrayG[block]->bleft = rowArrayG[row].startx2 - barrayG[block]->bxcenter ; barrayG[block]->bright = rowArrayG[row].endx - barrayG[block]->bxcenter ; barrayG[block]->bbottom = boxptr->bbottom ; barrayG[block]->btop = boxptr->btop ; barrayG[block]->bheight = boxptr->btop - boxptr->bbottom ; barrayG[block]->blength = rowArrayG[row].endx - rowArrayG[row].startx2 ; barrayG[block]->bclass = boxptr->bclass ; barrayG[block]->borient = boxptr->borient ; ratio = (DOUBLE) barrayG[block - 1]->blength / (DOUBLE) (barrayG[block - 1]->blength + barrayG[block]->blength) ; barrayG[block]->desire = 1 + (INT)((1.0 - ratio) * rowArrayG[row].desiredL) ; barrayG[block - 1]->desire = 1 + (INT)(ratio * rowArrayG[row].desiredL) ; barrayG[block]->oldsize = 0 ; } else { block++ ; barrayG[block]->bxcenter = (rowArrayG[row].startx + rowArrayG[row].endx ) / 2 ; barrayG[block]->bycenter = rowArrayG[row].ypos ; barrayG[block]->bleft = rowArrayG[row].startx - barrayG[block]->bxcenter ; barrayG[block]->bright = rowArrayG[row].endx - barrayG[block]->bxcenter ; barrayG[block]->bbottom = boxptr->bbottom ; barrayG[block]->btop = boxptr->btop ; barrayG[block]->bheight = boxptr->btop - boxptr->bbottom ; barrayG[block]->blength = rowArrayG[row].endx - rowArrayG[row].startx ; barrayG[block]->bclass = boxptr->bclass ; barrayG[block]->borient = boxptr->borient ; barrayG[block]->desire = rowArrayG[row].desiredL ; barrayG[block]->oldsize = 0 ; } } /* * Now blow array the old block array, rowArrayG, macroArray */ for( row = 1 ; row <= numRowsG ; row++ ) { Ysafe_free( oldbarray[row] ) ; } Ysafe_free( oldbarray ) ; numRowsG = totalBlock ; fprintf(fpoG,"\n******************\nBLOCK DATA\n"); desiredLG = 0 ; for( block = 1 ; block <= numRowsG ; block++ ) { barrayG[block]->orig_desire = barrayG[block]->desire ; desiredLG += barrayG[block]->desire ; fprintf(fpoG,"block:%d desire:%d\n",block,barrayG[block]->desire); D( "configure", xc = barrayG[block]->bxcenter ; yc = barrayG[block]->bycenter ; fprintf( stderr, "\tblock:%d l:%d r:%d b:%d t:%d\n", block, barrayG[block]->bleft+xc, barrayG[block]->bright+xc, barrayG[block]->bbottom+yc, barrayG[block]->btop+yc ) ; ) ; } fprintf(fpoG,"Total Desired Length: %d\n", desiredLG ) ; random_placement() ; /* * Ah ha, done */ return ; } random_placement() { INT cell , row , borient , blk , widthS ; INT block ; INT empty ; INT *filledTo ; INT *endRow ; CBOXPTR cellptr ; /* * And now, folks, its time for cell placement, that is, * real random cell placement */ filledTo = (INT *) Ysafe_malloc( (numRowsG + 1) * sizeof( INT ) ) ; endRow = (INT *) Ysafe_malloc( (numRowsG + 1) * sizeof( INT ) ) ; for( row = 1 ; row <= numRowsG ; row++ ) { filledTo[row] = barrayG[row]->bxcenter + barrayG[row]->bleft ; endRow[row] = barrayG[row]->bxcenter + barrayG[row]->bright ; } /* * On first pass, place the cells with specific block assignments */ for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { cellptr = carrayG[cell] ; blk = cellptr->cblock ; if( blk == 0 ) { continue ; } borient = barrayG[blk]->borient ; cellptr->cblock = blk ; widthS = cellptr->tileptr->right - cellptr->tileptr->left ; if( cellptr->cycenter > 0 ) { carrayG[cell]->cxcenter = barrayG[blk]->bxcenter + barrayG[blk]->bleft + cellptr->cxcenter + widthS / 2 ; carrayG[cell]->cycenter = barrayG[blk]->bycenter ; } else { carrayG[cell]->cxcenter = barrayG[blk]->bxcenter + barrayG[blk]->bright + cellptr->cxcenter - (widthS - widthS / 2) ; carrayG[cell]->cycenter = barrayG[blk]->bycenter ; } if( borient == 2 ) { cellptr->corient = 1 ; } else { /* borient was 1 */ cellptr->corient = 0 ; } } /* * Final pass, place all unassigned cells */ for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( carrayG[cell]->cblock != 0 ) { continue ; } /* * cute strategy: place cell in the most empty row */ empty = INT_MIN ; for( row = 1 ; row <= numRowsG ; row++ ) { if( endRow[row] - filledTo[row] > empty ) { empty = endRow[row] - filledTo[row] ; block = row ; } } borient = barrayG[block]->borient ; widthS = carrayG[cell]->tileptr->right - carrayG[cell]->tileptr->left ; carrayG[cell]->cblock = block ; if( borient > 0 ) { carrayG[cell]->cxcenter = filledTo[block] + widthS / 2 ; carrayG[cell]->cycenter = barrayG[block]->bycenter ; if( borient == 2 ) { carrayG[cell]->corient = 1 ; } else { /* borient was 1 */ carrayG[cell]->corient = 0 ; } } else { carrayG[cell]->cycenter = filledTo[block] + widthS / 2 ; carrayG[cell]->cxcenter = barrayG[block]->bxcenter ; if( borient == -2 ) { carrayG[cell]->corient = 4 ; } else { /* borient was -1 */ carrayG[cell]->corient = 7 ; } } filledTo[block] += widthS ; } Ysafe_free( filledTo ); Ysafe_free( endRow ); /* now finish by placing the pads */ placepads() ; return ; } /* used for split rows only, which we don't allow any more RtoB( row , from ) INT row , from ; { INT y , block , block1 , block2 , endx1 , startx2 ; y = rowArrayG[row].ypos ; block1 = 0 ; block2 = 0 ; for( block = 1 ; block <= numRowsG ; block++ ) { if( barrayG[block]->bycenter == y ) { block1 = block ; break ; } } for( block++ ; block <= numRowsG ; block++ ) { if( barrayG[block]->bycenter == y ) { block2 = block ; break ; } } if( block1 == 0 ) { fprintf(fpoG,"RtoB failed to find block corresponding"); fprintf(fpoG," to row:%d\n", row ) ; YexitPgm(PGMFAIL) ; } if( block2 == 0 ) { block = block1 ; } else { endx1 = barrayG[block1]->bxcenter + barrayG[block1]->bright ; startx2 = barrayG[block2]->bxcenter + barrayG[block2]->bleft ; if( from > 0 ) { if( endx1 < startx2 ) { block = block1 ; } else { block = block2 ; } } else { if( startx2 > endx1 ) { block = block2 ; } else { block = block1 ; } } } return(block) ; } */ graywolf-0.1.4+20170307gite1bf319/src/twsc/countf.c000066400000000000000000000243611305746555600212030ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: countf.c DESCRIPTION:feed estimation code. CONTENTS: countf() prep_feed_count_1() prep_feed_count() insert_row( flag ) INT flag ; feed_situation( row , net ) INT row , net ; DATE: Mar 27, 1989 REVISIONS: Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) countf.c (Yale) version 4.10 2/23/92" ; #endif #endif #include "standard.h" #include "groute.h" #include "feeds.h" #include "main.h" #include "ucxxglb.h" #include "readpar.h" #include "parser.h" #include "pads.h" /* global definitions */ INT *xfeeds_in_rowG ; INT est_fdsG ; /* static variables */ static INT offsetS ; static INT est_final_feedS ; static INT **row_mapS ; static BOOL num_callS = FALSE ; countf() { PINBOXPTR netptr ; INT check , a , value ; INT net , i , row , toprow , botrow ; INT TOP_ROW_FOR_NET ; INT orig_toprow , orig_botrow ; DOUBLE fd_reduction = 0.0 ; /* needed initialization WPS */ if( num_callS == FALSE ) { num_callS = TRUE ; prep_feed_count_1() ; row_mapS = ( INT ** ) Ysafe_malloc( (numRowsG + 2) * sizeof(INT *)); for( row = 0 ; row <= numRowsG + 1 ; row++ ) { row_mapS[row] = (INT *) Ysafe_malloc( 3 * sizeof( INT ) ); } insert_row( 0 ) ; } else { prep_feed_count() ; insert_row( 1 ) ; } for( net = 1 ; net <= numnetsG ; net++ ) { if(!(netptr = netarrayG[net]->pins)) { continue ; } for( i = 0 ; i <= numRowsG + 1 ; i++ ) { row_mapS[ i ][ RITE_MOST ] = NO_PINS ; row_mapS[ i ][ FEED_FLAG ] = NOT_DONE ; } for( ; netptr ; netptr = netptr->next ) { row = netptr->row ; row_mapS[ row ][ RITE_MOST ] = netptr->xpos ; if( row_mapS[ row ][ FEED_FLAG ] == NOT_DONE ) { row_mapS[ row ][ FEED_FLAG ] = feed_situation( row , net ) ; } } botrow = 0 ; toprow = numRowsG + 1 ; for( ; botrow <= numRowsG + 1 ; botrow++ ) { if( row_mapS[ botrow ][ RITE_MOST ] != NO_PINS ) { break ; } } for( ; toprow >= 0 ; toprow-- ) { if( row_mapS[ toprow ][ RITE_MOST ] != NO_PINS ) { break ; } } orig_toprow = toprow ; orig_botrow = botrow ; for( netptr = netarrayG[net]->pins ;netptr; netptr=netptr->next ) { if( netptr->cell <= numcellsG ) { continue ; } row = netptr->row ; if( row <= orig_toprow && row >= orig_botrow ) { continue ; } if( row > toprow ) { toprow = row ; } if( row < botrow ) { botrow = row ; } row_mapS[ row ][ RITE_MOST ] = netptr->xpos ; if( row_mapS[ row ][ FEED_FLAG ] == NOT_DONE ) { row_mapS[ row ][ FEED_FLAG ] = feed_situation( row , net ) ; } } if( toprow != botrow ) { row = toprow ; TOP_ROW_FOR_NET = YES ; for( row-- ; row >= botrow ; row-- ) { if( row_mapS[ row ][ RITE_MOST ] == NO_PINS ) { continue ; } if( TOP_ROW_FOR_NET == YES ) { if( row_mapS[ toprow ][ FEED_FLAG ] == 1 || row_mapS[ toprow ][ FEED_FLAG ] == 3 ) { feeds_in_rowG[toprow]++ ; xfeeds_in_rowG[toprow]++ ; } } if( row > botrow ) { if( row_mapS[row][ FEED_FLAG ] != 4 ) { feeds_in_rowG[row]++ ; xfeeds_in_rowG[row]++ ; } } if( row == botrow ) { if( row_mapS[botrow][ FEED_FLAG ] == 2 || row_mapS[botrow][ FEED_FLAG ] == 3 ) { feeds_in_rowG[botrow]++ ; xfeeds_in_rowG[botrow]++ ; } } check = toprow - row - 1 ; if( check != 0 ) { for( a = toprow - 1 ; a > row ; a--){ feeds_in_rowG[a]++ ; xfeeds_in_rowG[a]++ ; } } toprow = row ; TOP_ROW_FOR_NET = NO ; } } else { /* toprow == botrow */ if( row_mapS[toprow][ FEED_FLAG ] == 3 ) { feeds_in_rowG[toprow]++ ; xfeeds_in_rowG[toprow]++ ; } } } est_fdsG = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { if( xfeeds_in_rowG[row] > 0 ) { est_fdsG += xfeeds_in_rowG[row] ; } } if( iterationG == 3 ) { est_final_feedS = est_fdsG * /* exp( -(log(250000.0) - log(22000.0))); */ exp( -(log(280000.0) - log(22000.0))); /* these are the numbers for the dec12k circuit --Carl */ if( est_final_feedS - offsetS < 0 ) { est_final_feedS = offsetS ; } } if( iterationG >= 3 ) { if( est_fdsG > 0 ) { if( est_fdsG - offsetS > 0 ) { fd_reduction = ((DOUBLE) est_final_feedS - (DOUBLE) offsetS) / ((DOUBLE) est_fdsG - (DOUBLE) offsetS); } else { fd_reduction = 0.0 ; } if( fd_reduction < 1.0 ) { if( iterationG <= 100 ) { fd_reduction += (1.0 - fd_reduction) * (((double)iterationG / 100.0 ) * ((double)iterationG / 100.0) ); } else { fd_reduction = 1.0 ; } } else { fd_reduction = 1.0 ; } } else { fd_reduction = 0.0 ; } /* else fd_reduction = 0.0 ; */ } fd_reduction *= 1.25 ; /* we no longer add just min. feeds */ for( row = 1 ; row <= numRowsG ; row++ ) { value = (INT)(fd_reduction * feeds_in_rowG[row]) ; if( value > 0 && fdWidthG > 0 ) { feeds_in_rowG[row] = 1 + value ; } else { feeds_in_rowG[row] = 0 ; } } value = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { value += feeds_in_rowG[row] ; } return( value * fdWidthG ) ; } prep_feed_count_1() { INT row ; DOUBLE total_row_len ; total_row_len = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { total_row_len += (DOUBLE) barrayG[row]->blength ; } xfeeds_in_rowG = (INT *) Ysafe_malloc( (1 + numRowsG) * sizeof(INT) ); offsetS = - (INT)((DOUBLE) implicit_feed_countG * 0.33) ; for( row = 1 ; row <= numRowsG ; row++ ) { feeds_in_rowG[row] = (INT)( (DOUBLE) offsetS * ((DOUBLE)(barrayG[row]->blength) / total_row_len) ) ; xfeeds_in_rowG[row] = 0 ; } return ; } prep_feed_count() { INT row ; DOUBLE total_row_len ; total_row_len = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { total_row_len += (DOUBLE) barrayG[row]->blength ; } for( row = 1 ; row <= numRowsG ; row++ ) { feeds_in_rowG[row] = (INT)( (DOUBLE) offsetS * ((DOUBLE)(barrayG[row]->blength) / total_row_len) ) ; xfeeds_in_rowG[row] = 0 ; } return ; } insert_row( flag ) INT flag ; { PINBOXPTR pinptr ; INT row , cell , pad ; INT yc , yb , blk , xc ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { row = carrayG[cell]->cblock ; for( pinptr = carrayG[cell]->pins ; pinptr ;pinptr=pinptr->nextpin ) { pinptr->row = row ; } } if( flag == 0 ) { for( pad = numcellsG + 1 ; pad <= lastpadG ; pad++ ) { for( pinptr = carrayG[pad]->pins;pinptr;pinptr=pinptr->nextpin ) { xc = carrayG[pad]->cxcenter + pinptr->txpos[1] ; yc = carrayG[pad]->cycenter + pinptr->typos[1] ; for( blk = 1 ; blk <= numRowsG ; blk++ ) { if( barrayG[blk]->bycenter >= yc ) { break ; } } if( blk == 1 ) { yb = barrayG[1]->bycenter + barrayG[1]->bbottom ; if( yc < yb ) { row = 0 ; } else { row = 1 ; } } else if( blk > numRowsG ) { if( yc > barrayG[numRowsG]->bycenter + barrayG[numRowsG]->btop ) { row = numRowsG + 1 ; pinptr->pinloc = BOTCELL ; } else { row = numRowsG ; } } else { yb = barrayG[blk]->bycenter ; if( yb - yc < yc - barrayG[blk - 1]->bycenter ) { row = blk ; } else { row = blk - 1 ; } } pinptr->row = row ; } if( carrayG[pad]->padptr->padside == 0 && rowsG > 0 ) { /* case of a port on left or right and below 1st row */ /* reset 'row' for purposes of this 'if' only */ if( row == 0 ){ row = 1 ; } else if( row == numRowsG + 1 ) { row = numRowsG ; } /* must then be a left or right side port */ /* Note: there is only one pin per port, obviously */ if( xc < barrayG[row]->bxcenter ) { carrayG[pad]->padptr->padside = L ; } else { carrayG[pad]->padptr->padside = R ; } } } } return ; } feed_situation( row , net ) INT row , net ; { PINBOXPTR nptr ; INT pinup, pindown , pinloc ; /* * The following code is used for the return value: * * pins top,bot but NOT truly equivalent: 0 * pins only on top of row for this net: 1 * pins only on bot of row for this net: 2 * pins top,bot but no passthru for net: 3 * passthru exists for this net: 4 */ pinup = 0 ; pindown = 0 ; for( nptr = netarrayG[net]->pins; nptr; nptr = nptr->next ) { if( nptr->row != row ) { continue ; } if( nptr->eqptr ) { if( nptr->eqptr->unequiv == 1 ) { continue ; } } pinloc = nptr->pinloc ; if( pinloc == NEITHER ) { return(4) ; } if( pinloc > NEITHER ) { pinup = 1 ; } else { pindown = 1 ; } } if( pinup == 1 && pindown == 0 ) { return(1) ; } else if( pinup == 0 && pindown == 1 ) { return(2) ; } else if( pinup == 1 && pindown == 1 ) { return(3) ; } else { return(0); } } graywolf-0.1.4+20170307gite1bf319/src/twsc/crossbus.c000066400000000000000000000427471305746555600215600ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: crossbus.c DESCRIPTION:cross bus code. CONTENTS: handle_crossbuses() check_violations() reduce_violations() DATE: Mar 27, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) crossbus.c (Yale) version 4.5 10/14/90" ; #endif #endif #include "standard.h" #include "main.h" #include "groute.h" #include "pads.h" /* global definitions */ extern INT left_row_boundaryG ; extern INT row_extentG ; extern BOOL exclude_noncrossbus_padsG ; handle_crossbuses() { PINBOXPTR netptr ; FENCEBOXPTR fence , fence2, save_fence , prev_fence ; INT cell , net , process , row_area , area ; INT length , max_x , min_x , max_y , min_y , count , cross_bus ; INT block , x , y , avg_length , left , right ; INT large_pos , large_neg , ro_height , tmp , i ; INT distance , j , save_j , side ; INT *left_pins , *rite_pins , *top_pins , *bot_pins , bound ; left_pins = (INT *) Ysafe_malloc( (1 + numtermsG) * sizeof( INT ) ) ; rite_pins = (INT *) Ysafe_malloc( (1 + numtermsG) * sizeof( INT ) ) ; top_pins = (INT *) Ysafe_malloc( (1 + numtermsG) * sizeof( INT ) ) ; bot_pins = (INT *) Ysafe_malloc( (1 + numtermsG) * sizeof( INT ) ) ; large_pos = 10000000 ; large_neg = -10000000 ; if( rowHeightG % 2 == 1 ) { ro_height = rowHeightG + 1 ; } else { ro_height = rowHeightG ; } for( net = 1 ; net <= numnetsG ; net++ ) { length = 0 ; count = 0 ; process = 0 ; left_pins[0] = 0 ; rite_pins[0] = 0 ; top_pins[0] = 0 ; bot_pins[0] = 0 ; min_x = large_pos ; min_y = large_pos ; max_x = large_neg ; max_y = large_neg ; for( netptr = netarrayG[net]->pins;netptr ; netptr = netptr->next ) { if( netptr->cell > numcellsG ) { process = 1 ; x = carrayG[ netptr->cell ]->cxcenter ; y = carrayG[ netptr->cell ]->cycenter ; if( carrayG[ netptr->cell ]->padptr ){ side = carrayG[ netptr->cell ]->padptr->padside ; } else { side = 0 ; } if( side == 1 /* L */ ) { left_pins[ ++left_pins[0] ] = netptr->cell ; } else if( side == 2 /* T */ ) { top_pins[ ++top_pins[0] ] = netptr->cell ; } else if( side == 3 /* R */ ) { rite_pins[ ++rite_pins[0] ] = netptr->cell ; } else if( side == 4 /* B */ ) { bot_pins[ ++bot_pins[0] ] = netptr->cell ; } if( x < min_x ) { min_x = x ; } if( x > max_x ) { max_x = x ; } if( y < min_y ) { min_y = y ; } if( y > max_y ) { max_y = y ; } } else { count++ ; length += carrayG[netptr->cell]->clength ; } } /* close of first pass thru all pins for this net */ if( !process ) { continue ; } if( count == 0 ) { continue ; } avg_length = length / count ; if( avg_length < (INT) mean_widthG ) { avg_length = (INT) mean_widthG ; } if( avg_length % 2 == 1 ) { avg_length++ ; } if( left_pins[0] > 0 && rite_pins[0] > 0 ) { for( i = 1 ; i <= left_pins[0] ; i++ ) { distance = 10000000 ; for( j = 1 ; j <= rite_pins[0] ; j++ ) { if( ABS( carrayG[ left_pins[i] ]->cycenter - carrayG[ rite_pins[j] ]->cycenter) < distance ) { distance = ABS( carrayG[ left_pins[i] ]->cycenter - carrayG[ rite_pins[j] ]->cycenter) ; save_j = j ; } } if( distance <= 5 * ro_height ) { min_y = carrayG[ left_pins[i] ]->cycenter ; max_y = carrayG[ rite_pins[save_j] ]->cycenter ; if( min_y > max_y ) { tmp = min_y ; min_y = max_y ; max_y = tmp ; } bound = 3 * (1 + (count - 1)/2) * ro_height ; /* while( max_y - min_y < 9 * ro_height ) */ while( max_y - min_y < bound ) { min_y -= ro_height / 2 ; max_y += ro_height / 2 ; } min_x = carrayG[ left_pins[i] ]->cxcenter ; max_x = carrayG[ rite_pins[save_j] ]->cxcenter ; for( netptr = netarrayG[net]->pins ;netptr; netptr = netptr->next ) { if( netptr->cell > numcellsG ) { continue ; } fence = carrayG[netptr->cell]->fence ; carrayG[netptr->cell]->fence = (FENCEBOXPTR) Ysafe_malloc( sizeof(FENCEBOX) ) ; carrayG[netptr->cell]->fence->next_fence = fence ; carrayG[netptr->cell]->fence->min_block = min_y ; carrayG[netptr->cell]->fence->max_block = max_y ; carrayG[netptr->cell]->fence->min_xpos = min_x ; carrayG[netptr->cell]->fence->max_xpos = max_x ; } } } } else if( top_pins[0] > 0 && bot_pins[0] > 0 ) { for( i = 1 ; i <= bot_pins[0] ; i++ ) { distance = 10000000 ; for( j = 1 ; j <= top_pins[0] ; j++ ) { if( ABS( carrayG[ bot_pins[i] ]->cxcenter - carrayG[ top_pins[j] ]->cxcenter) < distance ) { distance = ABS( carrayG[ bot_pins[i] ]->cxcenter - carrayG[ top_pins[j] ]->cxcenter) ; save_j = j ; } } if( distance <= 4 * avg_length ) { min_x = carrayG[ bot_pins[i] ]->cxcenter ; max_x = carrayG[ top_pins[save_j] ]->cxcenter ; if( min_x > max_x ) { tmp = min_x ; min_x = max_x ; max_x = tmp ; } bound = 2 * (2 + (count - 1)/2) * avg_length ; /* while( max_x - min_x < 6 * avg_length ) */ while( max_x - min_x < bound ) { min_x -= avg_length / 2 ; max_x += avg_length / 2 ; } min_y = carrayG[ bot_pins[i] ]->cycenter ; max_y = carrayG[ top_pins[save_j] ]->cycenter ; netptr = netarrayG[net]->pins ; for( ; netptr ; netptr = netptr->next ) { if( netptr->cell > numcellsG ) { continue ; } fence = carrayG[netptr->cell]->fence ; carrayG[netptr->cell]->fence = (FENCEBOXPTR) Ysafe_malloc( sizeof(FENCEBOX) ) ; carrayG[netptr->cell]->fence->next_fence = fence ; carrayG[netptr->cell]->fence->min_block = min_y ; carrayG[netptr->cell]->fence->max_block = max_y ; carrayG[netptr->cell]->fence->min_xpos = min_x ; carrayG[netptr->cell]->fence->max_xpos = max_x ; } } } } else { if( min_x < left_row_boundaryG ) { min_x = left_row_boundaryG ; } if( min_x > left_row_boundaryG + row_extentG ) { min_x = left_row_boundaryG + row_extentG ; } if( max_x < left_row_boundaryG ) { max_x = left_row_boundaryG ; } if( max_x > left_row_boundaryG + row_extentG ) { max_x = left_row_boundaryG + row_extentG ; } if( min_y < barrayG[1]->bycenter ) { min_y = barrayG[1]->bycenter ; } if( min_y > barrayG[numRowsG]->bycenter ) { min_y = barrayG[numRowsG]->bycenter ; } if( max_y < barrayG[1]->bycenter ) { max_y = barrayG[1]->bycenter ; } if( max_y > barrayG[numRowsG]->bycenter ) { max_y = barrayG[numRowsG]->bycenter ; } min_x -= (3 + (count * 3)) * avg_length ; max_x += (3 + (count * 3)) * avg_length ; min_y -= (3 + (count * 3)) * rowHeightG ; max_y += (3 + (count * 3)) * rowHeightG ; netptr = netarrayG[net]->pins ; for( ; netptr ; netptr = netptr->next ) { if( netptr->cell > numcellsG ) { continue ; } fence = carrayG[netptr->cell]->fence ; carrayG[netptr->cell]->fence = (FENCEBOXPTR) Ysafe_malloc( sizeof(FENCEBOX) ) ; carrayG[netptr->cell]->fence->next_fence = fence ; carrayG[netptr->cell]->fence->min_block = min_y ; carrayG[netptr->cell]->fence->max_block = max_y ; carrayG[netptr->cell]->fence->min_xpos = min_x ; carrayG[netptr->cell]->fence->max_xpos = max_x ; } } } for( cell = 1 ; cell <= numcellsG ; cell++ ) { fence = carrayG[cell]->fence ; if( !fence ) { continue ; } for( ; fence ; fence = fence->next_fence ) { for( block = 1 ; block <= numRowsG ; block++ ) { if( barrayG[block]->bycenter >= fence->min_block ) { fence->min_block = block ; break ; } } for( block = numRowsG ; block >= 1 ; block-- ) { if( barrayG[block]->bycenter <= fence->max_block ) { fence->max_block = block ; break ; } } } fence = carrayG[cell]->fence ; for( ; fence ; fence = fence->next_fence ) { if( fence->min_xpos < left_row_boundaryG ) { fence->min_xpos = left_row_boundaryG ; } if( fence->max_xpos > left_row_boundaryG + row_extentG ) { fence->max_xpos = left_row_boundaryG + row_extentG ; } } fence = carrayG[cell]->fence ; cross_bus = 0 ; for( ; fence ; fence = fence->next_fence ) { if( (fence->min_xpos <= left_row_boundaryG && fence->max_xpos >= left_row_boundaryG + row_extentG) || (fence->min_block <= 1 && fence->max_block >= numRowsG)){ cross_bus = 1 ; break ; } } if( cross_bus ) { fence = carrayG[cell]->fence ; prev_fence = NULL ; for( ; fence ; ) { if( (fence->min_xpos <= left_row_boundaryG && fence->max_xpos >= left_row_boundaryG + row_extentG) || (fence->min_block <= 1 && fence->max_block >= numRowsG )){ prev_fence = fence ; fence = fence->next_fence ; continue ; } if( prev_fence == NULL ) { carrayG[cell]->fence = fence->next_fence ; Ysafe_free( fence ) ; fence = carrayG[cell]->fence ; } else { prev_fence->next_fence = fence->next_fence ; Ysafe_free( fence ) ; fence = prev_fence->next_fence ; } } /* intersecting crossbuses of the same orienation and merge'm */ fence = carrayG[cell]->fence ; for( ; fence ; fence = fence->next_fence ) { if( fence->min_block <= 1 && fence->max_block >= numRowsG ){ fence2 = fence->next_fence ; prev_fence = fence ; for( ; fence2 ; ) { if( fence2->min_block <= 1 && fence2->max_block >= numRowsG ){ if( fence->min_xpos > fence2->max_xpos || fence2->min_xpos > fence->max_xpos ) { prev_fence = fence2 ; fence2 = fence2->next_fence ; continue ; } if( fence->min_xpos > fence2->min_xpos ) { fence->min_xpos = fence2->min_xpos ; } if( fence->max_xpos < fence2->max_xpos ) { fence->max_xpos = fence2->max_xpos ; } prev_fence->next_fence = fence2->next_fence ; Ysafe_free( fence2 ) ; fence2 = prev_fence->next_fence ; } else { prev_fence = fence2 ; fence2 = fence2->next_fence ; } } } } fence = carrayG[cell]->fence ; for( ; fence ; fence = fence->next_fence ) { if( fence->min_xpos <= left_row_boundaryG && fence->max_xpos >= left_row_boundaryG + row_extentG ){ fence2 = fence->next_fence ; prev_fence = fence ; for( ; fence2 ; ) { if( fence2->min_xpos <= left_row_boundaryG && fence2->max_xpos >= left_row_boundaryG + row_extentG ){ if( fence->min_block > fence2->max_block || fence2->min_block > fence->max_block ) { prev_fence = fence2 ; fence2 = fence2->next_fence ; continue ; } if( fence->min_block > fence2->min_block ) { fence->min_block = fence2->min_block ; } if( fence->max_block < fence2->max_block ) { fence->max_block = fence2->max_block ; } prev_fence->next_fence = fence2->next_fence ; Ysafe_free( fence2 ) ; fence2 = prev_fence->next_fence ; } else { prev_fence = fence2 ; fence2 = fence2->next_fence ; } } } } } else { /* keep only largest fence */ fence = carrayG[cell]->fence ; row_area = 0 ; for( ; fence ; fence = fence->next_fence ) { left = fence->min_xpos ; if( left < left_row_boundaryG ) { left = left_row_boundaryG ; } right = fence->max_xpos ; if( right > left_row_boundaryG + row_extentG ) { right = left_row_boundaryG + row_extentG ; } area = (right - left) * (fence->max_block - fence->min_block) ; if( area > row_area ) { row_area = area ; save_fence = fence ; } } fence = carrayG[cell]->fence ; prev_fence = NULL ; for( ; fence ; ) { if( fence == save_fence ) { prev_fence = fence ; fence = fence->next_fence ; continue ; } if( prev_fence == NULL ) { carrayG[cell]->fence = fence->next_fence ; Ysafe_free( fence ) ; fence = carrayG[cell]->fence ; } else { prev_fence->next_fence = fence->next_fence ; Ysafe_free( fence ) ; fence = prev_fence->next_fence ; } } if( exclude_noncrossbus_padsG ) { Ysafe_free( carrayG[cell]->fence ) ; carrayG[cell]->fence = NULL ; } } } count = 0 ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { fence = carrayG[cell]->fence ; if( fence ) { count++ ; } else { continue ; } /* printf("Constrained Cell #%d:\n ", cell ) ; for( ; fence ; fence = fence->next_fence ) { printf(" X: %5d, %5d R:%3d, %3d\n", fence->min_xpos , fence->max_xpos , fence->min_block , fence->max_block ) ; } printf("\n"); */ } fprintf(fpoG,"Percentage of constrained cells:%f\n", (DOUBLE) count / (DOUBLE) numcellsG ) ; fflush(stdout); Ysafe_free( left_pins ) ; Ysafe_free( rite_pins ) ; Ysafe_free( top_pins ) ; Ysafe_free( bot_pins ) ; return ; } check_violations() { FENCEBOXPTR fence ; INT cell , total_r , total_l , x , error , row_error ; INT max_x , min_x , row , min_block , max_block ; INT r_error ; total_r = 0 ; total_l = 0 ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { fence = carrayG[cell]->fence ; if( !fence ) { continue ; } x = carrayG[cell]->cxcenter ; row = carrayG[cell]->cblock ; error = 10000000 ; row_error = 10000000 ; for( ; fence && (!(error == 0 && row_error == 0)) ; fence = fence->next_fence ) { max_x = fence->max_xpos ; min_x = fence->min_xpos ; min_block = fence->min_block ; max_block = fence->max_block ; if( x > max_x ) { if( x - max_x < error ) { error = x - max_x ; r_error = 1 ; if( row > max_block ) { if( row - max_block < row_error ) { row_error = row - max_block ; } } else if( row < min_block ) { if( min_block - row < row_error ) { row_error = min_block - row; } } else { row_error = 0 ; } } } else if( x < min_x ) { if( min_x - x < error ) { error = min_x - x ; r_error = 0 ; if( row > max_block ) { if( row - max_block < row_error ) { row_error = row - max_block ; } } else if( row < min_block ) { if( min_block - row < row_error ) { row_error = min_block - row; } } else { row_error = 0 ; } } } else { error = 0 ; if( row > max_block ) { if( row - max_block < row_error ) { row_error = row - max_block ; } } else if( row < min_block ) { if( min_block - row < row_error ) { row_error = min_block - row; } } else { row_error = 0 ; } } } if( !( error == 0 && row_error == 0) ) { if( error > (INT) mean_widthG ) { if( r_error == 1 ) { total_r += error ; /* fprintf(fpoG,"Right Violation for cell #%d ", cell ); fprintf(fpoG,"X ERROR by %d\n", error ) ; */ } else { total_l += error ; /* fprintf(fpoG,"Left Violation for cell #%d ", cell ); fprintf(fpoG,"X ERROR by %d\n", error ) ; */ } /* fprintf(fpoG,"Row Error by %d rows\n", row_error ) ; */ } } } fprintf(fpoG,"Total placement violations to the left:%d\n", total_l ); fprintf(fpoG,"Total placement violations to the rite:%d\n", total_r ); return ; } reduce_violations() { FENCEBOXPTR fence , save_fence ; INT cell , x , error , work , l_error , r_error , row ; INT max_x , min_x , i ; work = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { for( i = 1 ; i <= pairArrayG[row][0] ; i++ ) { cell = pairArrayG[row][i] ; fence = carrayG[cell]->fence ; if( !fence ) { continue ; } x = carrayG[cell]->cxcenter ; l_error = 10000000 ; error = 10000000 ; r_error = 10000000 ; for( ; fence && error != 0 ; fence = fence->next_fence ) { max_x = fence->max_xpos ; min_x = fence->min_xpos ; if( error == 0 ) { } else if( x > max_x || x < min_x ) { if( x > max_x ) { if( x - max_x < error ) { r_error = x - max_x ; save_fence = fence ; } } else { if( min_x - x < error ) { l_error = min_x - x ; save_fence = fence ; } } } else { error = 0 ; } } if( error != 0 ) { work++ ; if( l_error < r_error ) { /* we should shift the cell to the right */ carrayG[ pairArrayG[row][i] ]->cxcenter = save_fence->min_xpos + 3 * (INT)(mean_widthG) ; } else { /* we should shift the cell to the left */ carrayG[ pairArrayG[row][i] ]->cxcenter = save_fence->max_xpos - 3 * (INT)(mean_widthG) ; } } } } return( work ) ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/date.h000066400000000000000000000001071305746555600206170ustar00rootroot00000000000000#define DATE "@(#) Yale compilation date:Mon May 25 21:19:07 EDT 1992" graywolf-0.1.4+20170307gite1bf319/src/twsc/debug.c000066400000000000000000000164501305746555600207730ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: debug.c DESCRIPTION:Various debug functions. CONTENTS: cellbox_data( first_cell , last_cell ) INT first_cell , last_cell ; cellterm_data( first_cell , last_cell ) INT first_cell , last_cell ; dbx_terminal( first_net , last_net ) INT first_net , last_net ; dbx_grd( ptr1 , ptr2 ) CHANGRDPTR ptr1 , ptr2 ; pairCheck( first_row , last_row ) INT first_row , last_row ; fcellheight( pin , fcell , status ) INT pin , *fcell , status ; dbx_track( start_chan , end_chan ) INT start_chan , end_chan ; DATE: Mar 27, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) debug.c (Yale) version 4.5 9/7/90" ; #endif #endif #include "standard.h" #include "groute.h" #include "pads.h" cellbox_data( first_cell , last_cell ) INT first_cell , last_cell ; { FILE *fp ; CBOXPTR ptr ; INT cell ; INT padside ; fp = TWOPEN( "cellbox.dat" , "w", ABORT ) ; fprintf(fp," cell xcenter ycenter corient padside row class\n" ) ; for( cell = first_cell ; cell <= last_cell ; cell++ ) { ptr = carrayG[ cell ] ; if( ptr->padptr ){ padside = ptr->padptr->padside ; } else { padside = 0 ; } fprintf( fp , "%5d %6d %6d %2d %2d %4d %4d\n" , cell , ptr->cxcenter , ptr->cycenter , ptr->corient , padside , ptr->cblock , ptr->cclass ) ; } TWCLOSE( fp ) ; } cellterm_data( first_cell , last_cell ) INT first_cell , last_cell ; { FILE *fp ; CBOXPTR ptr ; PINBOXPTR termptr ; INT cell , corient, padside ; fp = TWOPEN( "cellterm.dat" , "w", ABORT ) ; for( cell = first_cell ; cell <= last_cell ; cell++ ) { fprintf(fp,"\n cell xcenter ycenter corient padside left right\n"); ptr = carrayG[ cell ] ; if( ptr->padptr ){ padside = ptr->padptr->padside ; } else { padside = 0 ; } corient = ptr->corient ; fprintf( fp , "%5d %6d %6d %2d %2d %4d %4d\n" , cell , ptr->cxcenter , ptr->cycenter , corient , padside , ptr->tileptr->left , ptr->tileptr->right ) ; fprintf(fp," pin net tx ty xpos ypos newx newy ") ; fprintf(fp,"loc flag\n" ) ; if( cell <= numcellsG ) { for( termptr = ptr->pins ;termptr;termptr = termptr->nextpin ) { fprintf(fp," %5d %4d %4d %4d %6d %6d %6d %6d %3d %2d\n" , termptr->terminal , termptr->net , termptr->txpos[ corient/2 ] , termptr->typos[ corient%2 ] , termptr->xpos , termptr->ypos , termptr->newx , termptr->newy , termptr->pinloc , termptr->flag ); } } else { for( termptr = ptr->pins; termptr; termptr = termptr->next ){ fprintf(fp," %5d %4d %4d %4d %6d %6d %6d %6d %3d %2d\n" , termptr->terminal , termptr->net ,termptr->txpos[1] , termptr->typos[1] , termptr->xpos , termptr->ypos , termptr->newx , termptr->newy , termptr->pinloc , termptr->flag ); } } } TWCLOSE( fp ) ; } dbx_terminal( first_net , last_net ) INT first_net , last_net ; { FILE *fp ; PINBOXPTR netptr ; INT net ; fp = TWOPEN( "netbox.dat" , "w", ABORT ) ; for( net = first_net ; net <= last_net ; net++ ) { fprintf(fp,"net %d\n" , net ) ; fprintf(fp," terminal pinname xpos cell loc row \n"); for( netptr = netarrayG[net]->pins ; netptr ; netptr = netptr->next ) { fprintf(fp," %5d %8s %5d %5d %3d %2d\n" , netptr->terminal , netptr->pinname , netptr->xpos , netptr->cell , netptr->pinloc, netptr->row ) ; } } TWCLOSE( fp ) ; } dbx_grd( ptr1 , ptr2 ) CHANGRDPTR ptr1 , ptr2 ; { CHANGRDPTR ptr ; INT x2 , flag = 0 ; x2 = ptr2->netptr->xpos ; for( ptr = ptr1 ; ptr->netptr->xpos <= x2 ; ptr = ptr->nextgrd ) { if( ptr == ptr2 ) { flag = 1 ; } } if( flag == 1 ) { printf(" they are in the same linked list of channel grid\n" ) ; } else { printf(" they are not in the same linked list of channel grid\n" ) ; } } pairCheck( first_row , last_row ) INT first_row , last_row ; { FILE *fp ; CBOXPTR cellptr ; TIBOXPTR tileptr ; INT row , i , *Aray , cell ; INT most_left , most_rite , n ; INT curr_cell_left , curr_cell_rite , prev_cell_rite ; extern INT fdWidthG ; fp = TWOPEN( "row.dat" , "w", ABORT ) ; /* fprintf(fp,"cedge_binwidth = %d num_edgebin = %d\n", cedge_binwidth, num_edgebin ) ; */ for( row = first_row ; row <= last_row ; row++ ) { Aray = pairArrayG[row] ; fprintf(fp,"\nROW %d\n" , row ) ; fprintf(fp," total number of cells in this row = %d\n",Aray[0] ) ; cellptr = carrayG[ Aray[1] ] ; most_left = cellptr->cxcenter + cellptr->tileptr->left ; cellptr = carrayG[ Aray[Aray[0]] ] ; most_rite = cellptr->cxcenter + cellptr->tileptr->right ; fprintf(fp," most_left is at %d most_rite is at %d\n", most_left , most_rite ) ; fprintf(fp," i cell left right n\n" ) ; prev_cell_rite = carrayG[ Aray[1] ]->cxcenter + carrayG[ Aray[1] ]->tileptr->left ; for( i = 1 ; i <= Aray[0] ; i++ ) { cell = Aray[i] ; cellptr = carrayG[ cell ] ; tileptr = cellptr->tileptr ; curr_cell_left = cellptr->cxcenter + tileptr->left ; curr_cell_rite = cellptr->cxcenter + tileptr->right ; n = ( curr_cell_left - prev_cell_rite ) / fdWidthG ; prev_cell_rite = curr_cell_rite ; fprintf(fp," %3d %5d %5d %5d %3d\n", i , cell , curr_cell_left , curr_cell_rite , n ) ; } } TWCLOSE( fp ) ; } dbx_track( start_chan , end_chan ) INT start_chan , end_chan ; { INT chan ; FILE *fp ; CHANGRDPTR gdptr ; PINBOXPTR netptr ; fp = TWOPEN( "track.dat" , "w", ABORT ) ; for( chan = start_chan ; chan <= end_chan ; chan++ ) { fprintf(fp,"\n channel = %d\n" , chan ) ; fprintf(fp,"\n terminal xpos track net cell\n"); for( gdptr = BeginG[chan] ; gdptr ; gdptr = gdptr->nextgrd ) { netptr = gdptr->netptr ; fprintf(fp ,"%9d %6d %5d %5d %5d \n" , netptr->terminal , netptr->xpos , gdptr->tracks , netptr->net , netptr->cell ) ; } } TWCLOSE( fp ) ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/debug2.c000066400000000000000000000422731305746555600210570ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: debug2.c DESCRIPTION:Various debug functions. CONTENTS: dbx_fdpen() dbx_adj( net ) INT net ; dbx_netseg( net1 , net2 ) INT net1 , net2 ; dbx_seg( segptr ) SEGBOXPTR segptr ; dbx_feed( row1 , row2 ) INT row1 , row2 ; dbx_imp( row1 , row2 ) INT row1 , row2 ; dbx_funcost() mst_graph( net1 , net2 ) INT net1 , net2 ; pre_dbx_Lseg() dbx_Lseg( check_row ) INT check_row ; dbx_proj( check_row ) INT check_row ; dbx_fdasgn( row ) INT row ; check_funccost() DATE: Mar 27, 1989 REVISIONS: Apr 1, 1990 - added check_funccost() ; Added ASSERT checks to check_funccost. Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) debug2.c (Yale) version 4.7 12/15/90" ; #endif #endif #include "standard.h" #include "groute.h" #include "feeds.h" #include "pads.h" #include #include /* extern FEED_SEG_PTR *worker ; extern FEED_DATA **feedpptr ; extern SEGBOX **netsegHead ; extern IPBOXPTR *impFeeds ; extern PINBOXPTR *steinerHead ; extern INT chan_node_no ; extern INT *min_feed , *FeedInRow ; */ dbx_adj( net ) INT net ; { FILE *fp ; PINBOXPTR pin1ptr , pin2ptr , netptr ; ADJASEGPTR adjptr ; SEGBOXPTR segptr ; fp = TWOPEN("adj.dat" , "w", ABORT ) ; fprintf(fp,"\nnet %5d\n\n" , net ) ; for( netptr = netarrayG[net]->pins; netptr ;netptr = netptr->next ) { fprintf(fp," pin %5d\n", netptr->terminal ); fprintf(fp," pin1 pin2 xpos1 xpos2 row1 row2 sw\n" ) ; for( adjptr = netptr->adjptr->next ; adjptr ; adjptr = adjptr->next ) { segptr = adjptr->segptr ; pin1ptr = segptr->pin1ptr ; pin2ptr = segptr->pin2ptr ; fprintf(fp," %5d %5d %5d %5d %4d %4d %2d\n", pin1ptr->terminal , pin2ptr->terminal , pin1ptr->xpos , pin2ptr->xpos , pin1ptr->row , pin2ptr->row , segptr->switchvalue ) ; } } TWCLOSE(fp) ; } dbx_netseg( net1 , net2 ) INT net1 , net2 ; { FILE *fp ; PINBOXPTR pin1ptr , pin2ptr ; SEGBOXPTR segptr ; INT net ; fp = TWOPEN("netseg.dat" , "w", ABORT ) ; for( net = net1 ; net <= net2 ; net++ ) { fprintf(fp,"\nnet %5d\n" , net ) ; fprintf(fp," pin1 pin2 xpos1 xpos2 row1 row2 sw loc1 loc2\n"); for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ) { pin1ptr = segptr->pin1ptr ; pin2ptr = segptr->pin2ptr ; fprintf(fp," %5d %5d %5d %5d %4d %4d %2d %4d %4d\n", pin1ptr->terminal , pin2ptr->terminal , pin1ptr->xpos , pin2ptr->xpos , pin1ptr->row , pin2ptr->row , segptr->switchvalue , pin1ptr->pinloc , pin2ptr->pinloc ) ; } } TWCLOSE(fp) ; } dbx_seg( segptr ) SEGBOXPTR segptr ; { FILE *fp ; PINBOXPTR pin1ptr , pin2ptr ; fp = TWOPEN("seg.dat" , "a", ABORT ) ; pin1ptr = segptr->pin1ptr ; pin2ptr = segptr->pin2ptr ; fprintf(fp,"\nnet %5d\n" , pin1ptr->net ) ; fprintf(fp," pin1 pin2 xpos1 xpos2 row1 row2 sw loc1 loc2\n"); fprintf(fp," %5d %5d %5d %5d %4d %4d %2d %4d %4d\n", pin1ptr->terminal , pin2ptr->terminal , pin1ptr->xpos , pin2ptr->xpos , pin1ptr->row , pin2ptr->row , segptr->switchvalue , pin1ptr->pinloc , pin2ptr->pinloc ) ; TWCLOSE(fp) ; } dbx_feed( row1 , row2 ) INT row1 , row2 ; { FILE *fp ; FEED_DATA *feedptr ; INT i , q , r , t , j , node , row ; INT actual , needed , total_actual , total_needed ; total_actual = 0 ; total_needed = 0 ; fp = TWOPEN("feed.dat" , "w", ABORT ) ; for( row = row1 ; row <= row2 ; row++ ) { actual = 0 ; needed = 0 ; feedptr = feedpptrG[row] ; fprintf(fp,"\nrow %2d" , row ) ; q = chan_node_noG / 10 ; r = chan_node_noG % 10 ; for( i = 0 ; i <= q-1 ; i++ ) { t = 10 * i ; fprintf(fp,"\n\n %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d" , t+1 , t+2 , t+3 , t+4 , t+5 , t+6 , t+7 , t+8 , t+9 , t+10) ; fprintf(fp,"\nactual" ) ; for( j = 1 ; j <= 10 ; j++ ) { node = t + j ; fprintf(fp," %4d", feedptr[node]->actual ) ; } fprintf(fp,"\nneeded" ) ; for( j = 1 ; j <= 10 ; j++ ) { node = t + j ; fprintf(fp," %4d", feedptr[node]->needed ) ; } fprintf(fp,"\n diff " ) ; for( j = 1 ; j <= 10 ; j++ ) { node = t + j ; actual += feedptr[node]->actual ; needed += feedptr[node]->needed ; fprintf(fp," %4d", feedptr[node]->actual - feedptr[node]->needed ) ; } } t = 10 * q ; fprintf(fp,"\n\n %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d" , t+1 , t+2 , t+3 , t+4 , t+5 , t+6 , t+7 , t+8 , t+9 , t+10) ; fprintf(fp,"\nactual" ) ; for( j = 1 ; j <= r ; j++ ) { node = t + j ; fprintf(fp," %4d", feedptr[node]->actual ) ; } fprintf(fp,"\nneeded" ) ; for( j = 1 ; j <= r ; j++ ) { node = t + j ; fprintf(fp," %4d", feedptr[node]->needed ) ; } fprintf(fp,"\n diff " ) ; for( j = 1 ; j <= r ; j++ ) { node = t + j ; actual += feedptr[node]->actual ; needed += feedptr[node]->needed ; fprintf(fp," %4d", feedptr[node]->actual - feedptr[node]->needed ) ; } fprintf(fp,"\n actual feedthru pin in row %d is %d\n", row, actual); fprintf(fp,"\n needed feedthru pin in row %d is %d\n", row, needed); fprintf(fp,"\n total difference in row %d is %d\n", row ,actual - needed ); total_actual += actual ; total_needed += needed ; } fprintf(fp,"\n total actual feedthru pins = %d\n" , total_actual ) ; fprintf(fp,"\n total needed feedthru pins = %d\n" , total_needed ) ; TWCLOSE(fp) ; } dbx_imp( row1 , row2 ) INT row1 , row2 ; { INT row , k ; char *s ; IPBOXPTR imptr ; FILE *fp ; fp = TWOPEN("imp.dat" , "w", ABORT ) ; for( row = row1 ; row <= row2 ; row++ ) { fprintf(fp,"\nrow %d\n" , row ) ; fprintf(fp," node terminal xpos NETBOX position\n" ) ; for( imptr = impFeedsG[row]->next ; imptr ; imptr = imptr->next ) { k = set_node( imptr->xpos ) ; if( feedpptrG[row][k]->firstimp == imptr ) { s = "firstimp" ; } else if( feedpptrG[row][k]->lastimp == imptr ) { s = "lastimp" ; } else { s = " " ; } fprintf(fp," %4d %8d %6d %6s %8s\n", k , imptr->terminal , imptr->xpos , (INT)tearrayG[imptr->terminal] , s ) ; } } TWCLOSE(fp) ; } dbx_funcost() { INT net , cost , minx , miny , maxx , maxy ; DBOXPTR dimptr ; PINBOXPTR netptr ; cost = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[net] ; if( dimptr->numpins <= 1 ) { continue ; } netptr = dimptr->pins ; maxx = minx = netptr->xpos ; maxy = miny = netptr->ypos ; for( netptr = netptr->next ; netptr ; netptr = netptr->next ) { if( netptr->xpos > maxx ) { maxx = netptr->xpos ; } if( netptr->xpos < minx ) { minx = netptr->xpos ; } if( netptr->ypos > maxy ) { maxy = netptr->ypos ; } if( netptr->ypos < miny ) { miny = netptr->ypos ; } } cost += ( maxx - minx ) + ( maxy - miny ) ; } if( cost != funccostG ) { printf("cost = %d funccost = %d\n" , cost , funccostG ) ; } } mst_graph( net1 , net2 ) INT net1 , net2 ; { FILE *fp ; PINBOXPTR pin1ptr , pin2ptr , netptr ; CBOXPTR cellptr1 , cellptr2 , cellptr ; SEGBOXPTR segptr ; INT net , x1 , x2 , y1 , y2 , row , cell ; fp = TWOPEN("net.file" , "w", ABORT ) ; for( net = net1 ; net <= net2 ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ) { pin1ptr = segptr->pin1ptr ; pin2ptr = segptr->pin2ptr ; if( pin1ptr->pinloc > NEITHER ) { cellptr1 = carrayG[pin1ptr->cell] ; if( !cellptr1->padptr || cellptr1->padptr->padside == 0 ) { y1 = cellptr1->cycenter + cellptr1->tileptr->top ; } else { y1 = pin1ptr->ypos ; } } else if( pin1ptr->pinloc < NEITHER ) { cellptr1 = carrayG[pin1ptr->cell] ; if( !cellptr1->padptr || cellptr1->padptr->padside == 0 ) { y1 = cellptr1->cycenter + cellptr1->tileptr->bottom ; } else { y1 = pin1ptr->ypos ; } } else { y1 = pin1ptr->ypos ; } if( pin2ptr->pinloc > NEITHER ) { cellptr2 = carrayG[pin2ptr->cell] ; if( !cellptr2->padptr || cellptr2->padptr->padside == 0 ) { y2 = cellptr2->cycenter + cellptr2->tileptr->top ; } else { y2 = pin2ptr->ypos ; } } else if( pin2ptr->pinloc < NEITHER ) { cellptr2 = carrayG[pin2ptr->cell] ; if( !cellptr2->padptr || cellptr2->padptr->padside == 0 ) { y2 = cellptr2->cycenter + cellptr2->tileptr->bottom ; } else { y2 = pin2ptr->ypos ; } } else { y2 = pin2ptr->ypos ; } fprintf(fp,"%d, %d, %d, %d, %d, color: black\n", net, pin1ptr->xpos , y1 , pin2ptr->xpos , y2 ) ; } for( netptr = netarrayG[net]->pins ; netptr ; netptr = netptr->next ) { if( netptr->pinloc == NEITHER ) { cellptr = carrayG[netptr->cell] ; if( !cellptr->padptr || cellptr->padptr->padside == 0 ) { y1 = cellptr->cycenter + cellptr->tileptr->bottom ; y2 = cellptr->cycenter + cellptr->tileptr->top ; fprintf(fp,"%d, %d, %d, %d, %d, color: black\n", net, netptr->xpos, y1 , netptr->xpos , y2 ) ; } } } } for( row = 1 ; row <= numRowsG ; row++ ) { cellptr1 = carrayG[ pairArrayG[row][1] ] ; cellptr2 = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; x1 = cellptr1->cxcenter + cellptr1->tileptr->left ; x2 = cellptr2->cxcenter + cellptr2->tileptr->right ; y1 = cellptr1->cycenter + cellptr1->tileptr->bottom ; y2 = cellptr2->cycenter + cellptr2->tileptr->top ; fprintf(fp,"0, %d, %d, %d, %d, color: black\n", x1, y1, x1, y2 ) ; fprintf(fp,"0, %d, %d, %d, %d, color: black\n", x1, y2, x2, y2 ) ; fprintf(fp,"0, %d, %d, %d, %d, color: black\n", x1, y1, x2, y1 ) ; fprintf(fp,"0, %d, %d, %d, %d, color: black\n", x2, y1, x2, y2 ) ; } for( cell = numcellsG + 1 ; cell <= numcellsG + numtermsG ; cell++ ) { cellptr = carrayG[cell] ; x1 = cellptr->cxcenter + cellptr->tileptr->left ; x2 = cellptr->cxcenter + cellptr->tileptr->right ; y1 = cellptr->cycenter + cellptr->tileptr->bottom ; y2 = cellptr->cycenter + cellptr->tileptr->top ; fprintf(fp,"0, %d, %d, %d, %d, color: black\n", x1, y1, x1, y2 ) ; fprintf(fp,"0, %d, %d, %d, %d, color: black\n", x1, y2, x2, y2 ) ; fprintf(fp,"0, %d, %d, %d, %d, color: black\n", x1, y1, x2, y1 ) ; fprintf(fp,"0, %d, %d, %d, %d, color: black\n", x2, y1, x2, y2 ) ; } TWCLOSE(fp) ; } dbx_fdasgn( row ) INT row ; { PINBOXPTR netptr , ptr1 , ptr2 ; SEGBOXPTR segptr , nextptr ; FEED_DATA *feedptr ; INT i, k , net ; feedptr = feedpptrG[row] ; for( i =1 ; i <= chan_node_noG ; i++ ) { feedptr[i]->needed = 0 ; } for( net = 1 ; net <= numnetsG ; net++ ) { for( netptr = steinerHeadG[net]->next ; netptr ; netptr = netptr->next ) { if( netptr->flag && netptr->row == row ) { k = set_node(netptr->xpos) ; feedptr[k]->needed++ ; } } for( segptr = netsegHeadG[net]->next ; segptr ; segptr = nextptr ) { nextptr = segptr->next ; ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; if( ptr1->row < row && ptr2->row > row ) { if( segptr->switchvalue == swL_down ) { k = set_node(ptr2->xpos) ; } else { k = set_node(ptr1->xpos) ; } feedptr[k]->needed++ ; } else if( ptr1->row == row && ptr2->row == row ) { if( segptr->switchvalue == swL_down ) { k = set_node(ptr2->xpos) ; feedptr[k]->needed++ ; } else if( segptr->switchvalue == swL_up ) { k = set_node(ptr1->xpos) ; feedptr[k]->needed++ ; } } else if( ptr1->row == row ) { if( segptr->switchvalue == swL_down && !segptr->flag ) { k = set_node(ptr2->xpos) ; feedptr[k]->needed++ ; } else if( (int) ptr1->pinloc == BOTCELL ) { if( segptr->switchvalue == swL_down ) { k = set_node(ptr2->xpos) ; feedptr[k]->needed++ ; } else { k = set_node(ptr1->xpos) ; feedptr[k]->needed++ ; } } } else if( ptr2->row == row ) { if( segptr->switchvalue == swL_up && !segptr->flag ) { k = set_node(ptr1->xpos) ; feedptr[k]->needed++ ; } else if( ptr2->pinloc == TOPCELL ) { if( segptr->switchvalue == swL_down ) { k = set_node(ptr2->xpos) ; feedptr[k]->needed++ ; } else { k = set_node(ptr1->xpos) ; feedptr[k]->needed++ ; } } } } } } check_cost() { CBOXPTR ptr ; DBOXPTR dimptr ; PINBOXPTR netptr , termptr ; INT corient ; INT cell , net , block ; INT x , y , cost ; INT tmp ; INT xmin, ymin, xmax, ymax ; INT Ln, Bn, Rn, Tn ; extern INT extra_cellsG ; INT penal, rpenal ; INT bin ; for( cell = 1 ; cell <= numcellsG + numtermsG ; cell++ ) { ptr = carrayG[ cell ] ; corient = ptr->corient ; block = ptr->cblock ; if( cell <= numcellsG - extra_cellsG ) { ptr->cycenter = barrayG[block]->bycenter ; for( termptr = ptr->pins ;termptr;termptr=termptr->nextpin ) { tmp = termptr->txpos[corient/2] + ptr->cxcenter; ASSERT( tmp == termptr->xpos, NULL, "trouble\n" ) ; termptr->xpos = tmp ; tmp = termptr->typos[corient%2] + ptr->cycenter; ASSERT( tmp == termptr->ypos, NULL, "trouble\n" ) ; termptr->ypos = tmp ; } } else if( cell > numcellsG ) { for( termptr = ptr->pins;termptr; termptr=termptr->nextpin ) { termptr->xpos = termptr->txpos[1] + ptr->cxcenter; termptr->ypos = termptr->typos[1] + ptr->cycenter; } } } cost = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[ net ] ; if( dimptr->ignore == 1 ){ continue ; } if( netptr = dimptr->pins ) { xmin = dimptr->xmin ; xmax = dimptr->xmax ; ymin = dimptr->ymin ; ymax = dimptr->ymax ; Ln = dimptr->Lnum ; Rn = dimptr->Rnum ; Bn = dimptr->Bnum ; Tn = dimptr->Tnum ; dimptr->xmin = dimptr->xmax = netptr->xpos ; dimptr->ymin = dimptr->ymax = netptr->ypos ; dimptr->Lnum = dimptr->Rnum = 1 ; dimptr->Bnum = dimptr->Tnum = 1 ; netptr = netptr->next ; } for( ; netptr ; netptr = netptr->next ) { x = netptr->xpos ; y = netptr->ypos ; if( x < dimptr->xmin ) { dimptr->xmin = x ; dimptr->Lnum = 1 ; } else if( x == dimptr->xmin ) { dimptr->Lnum++ ; if( x == dimptr->xmax ) { dimptr->Rnum++ ; } } else if( x > dimptr->xmax ) { dimptr->xmax = x ; dimptr->Rnum = 1 ; } else if( x == dimptr->xmax ) { dimptr->Rnum++ ; } if( y < dimptr->ymin ) { dimptr->ymin = y ; dimptr->Bnum = 1 ; } else if( y == dimptr->ymin ) { dimptr->Bnum++ ; if( y == dimptr->ymax ) { dimptr->Tnum++ ; } } else if( y > dimptr->ymax ) { dimptr->ymax = y ; dimptr->Tnum = 1 ; } else if( y == dimptr->ymax ) { dimptr->Tnum++ ; } } cost += dimptr->halfPx = dimptr->newhalfPx = dimptr->xmax - dimptr->xmin ; dimptr->halfPy = dimptr->newhalfPy = dimptr->ymax - dimptr->ymin ; cost += (INT)( vertical_wire_weightG * (DOUBLE) dimptr->halfPy ) ; ASSERT( xmin == dimptr->xmin, NULL,"trouble\n" ) ; ASSERT( xmax == dimptr->xmax, NULL,"trouble\n" ) ; ASSERT( ymin == dimptr->ymin, NULL,"trouble\n" ) ; ASSERT( ymax == dimptr->ymax, NULL,"trouble\n" ) ; if( dimptr->numpins > 5 ){ ASSERT( Ln == dimptr->Lnum, NULL,"trouble\n" ) ; ASSERT( Rn == dimptr->Rnum, NULL,"trouble\n" ) ; ASSERT( Bn == dimptr->Bnum, NULL,"trouble\n" ) ; ASSERT( Tn == dimptr->Tnum, NULL,"trouble\n" ) ; } } if( cost != funccostG ){ fprintf( stderr, "funcost:%d cost:%d\n", funccostG, cost ) ; funccostG = cost ; } penal = 0 ; for( block = 1 ; block <= numRowsG ; block++ ) { for( bin = 0 ; bin <= numBinsG ; bin++ ) { penal += ABS( binptrG[block][bin]->penalty ) ; } } sprintf( YmsgG, "binpenalG:%d penal:%d\n", binpenalG, penal ) ; ASSERT( binpenalG == penal, NULL, YmsgG ) ; rpenal = 0 ; for( block = 1 ; block <= numRowsG ; block++ ) { rpenal += ABS(barrayG[block]->oldsize - barrayG[block]->desire) ; } sprintf( YmsgG, "rowpenalG:%d rpenal:%d\n", rowpenalG, rpenal ) ; ASSERT( rowpenalG == rpenal, NULL, YmsgG ) ; } /* end check_funcost */ graywolf-0.1.4+20170307gite1bf319/src/twsc/dimbox.c000066400000000000000000000530371305746555600211710ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: dimbox.c DESCRIPTION:Incremental bounding box routines. CONTENTS: new_dbox( antrmptr , costptr ) TEBOXPTR antrmptr ; INT *costptr ; new_dbox2( antrmptr , bntrmptr , costptr ) TEBOXPTR antrmptr , bntrmptr ; INT *costptr ; wire_boundary1( dimptr ) DBOXPTR dimptr ; check_validbound( dimptr , termptr , nextptr ) DBOXPTR dimptr ; TEBOXPTR termptr , nextptr ; wire_boundary2( c , dimptr ) DBOXPTR dimptr ; INT c ; dbox_pos( antrmptr ) TEBOXPTR antrmptr ; dbox_pos_swap( antrmptr ) TEBOXPTR antrmptr ; DATE: Mar 27, 1989 REVISIONS: May 19, 1989 by Carl --- for gate swaps Nov 4, 1989 - made memoptr dynamic instead of fixed. Mon Nov 18 16:28:30 EST 1991 - fixed initialization problem with check_validbound. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) dimbox.c (Yale) version 4.5 11/18/91" ; #endif #endif #include "standard.h" #define break_pt 5 static INT prev_netS , curr_netS , test_newnetS ; static INT validLS , validRS , validBS , validTS ; static INT kS ; static PINBOXPTR *memoptrS ; init_dimbox() { INT maxpin, get_max_pin() ; maxpin = get_max_pin() ; memoptrS = (PINBOXPTR *) Ysafe_malloc( (++maxpin) * sizeof(PINBOXPTR) ) ; } /* end init_dimbox */ new_dbox( antrmptr , costptr ) PINBOXPTR antrmptr ; INT *costptr ; { register DBOXPTR dimptr ; PINBOXPTR termptr , nextptr ; prev_netS = -1 ; validRS = validLS = validBS = validTS = 0 ; for( termptr = antrmptr ; termptr ; termptr = termptr->nextpin ) { curr_netS = termptr->net ; test_newnetS = ( prev_netS == curr_netS ) ? 0 : 1 ; if( test_newnetS ) { memoptrS[ kS = 0 ] = termptr ; } prev_netS = curr_netS ; dimptr = netarrayG[ curr_netS ] ; memoptrS[ ++kS ] = nextptr = termptr->nextpin ; if( dimptr->dflag == 0 || dimptr->ignore == 1 ) { continue ; } if( dimptr->numpins <= break_pt ) { dimptr->dflag = 0 ; wire_boundary1( dimptr ) ; } else { check_validbound( dimptr , termptr , nextptr ) ; if( nextptr && curr_netS == nextptr->net ) { continue ; } dimptr->dflag = 0 ; wire_boundary2( validLS + 2*validBS + 4*validRS + 8*validTS , dimptr ) ; validRS = validLS = validBS = validTS = 0 ; } /* add2net_set remembers which nets are modified by this move */ add2net_set( curr_netS ) ; dimptr->newhalfPx = dimptr->newxmax - dimptr->newxmin ; dimptr->newhalfPy = dimptr->newymax - dimptr->newymin ; *costptr = *costptr + ( dimptr->newhalfPx - dimptr->halfPx + (INT)(vertical_wire_weightG * (DOUBLE)dimptr->newhalfPy) - (INT)(vertical_wire_weightG * (DOUBLE)dimptr->halfPy) ); } } new_dbox2( antrmptr , bntrmptr , costptr ) PINBOXPTR antrmptr , bntrmptr ; INT *costptr ; { DBOXPTR dimptr ; PINBOXPTR termptr , nextptr ; INT anet , bnet ; INT aflag ; if( antrmptr == PINNULL ) { new_dbox( bntrmptr , costptr ) ; return ; } if( bntrmptr == PINNULL ) { new_dbox( antrmptr , costptr ) ; return ; } validRS = validLS = validBS = validTS = 0 ; aflag = ( antrmptr->net <= bntrmptr->net ) ? 1 : 0 ; if( aflag ) { termptr = antrmptr ; antrmptr = antrmptr->nextpin ; } else { termptr = bntrmptr ; bntrmptr = bntrmptr->nextpin ; } prev_netS = -1 ; for( ; termptr ; termptr = nextptr ) { curr_netS = termptr->net ; test_newnetS = ( prev_netS == curr_netS ) ? 0 : 1 ; if( test_newnetS ) { memoptrS[ kS = 0 ] = termptr ; } prev_netS = curr_netS ; dimptr = netarrayG[ curr_netS ] ; if( antrmptr && bntrmptr ) { if( (anet = antrmptr->net) < (bnet = bntrmptr->net) ) { nextptr = antrmptr ; antrmptr = antrmptr->nextpin ; aflag = 1 ; } else if( anet > bnet ) { nextptr = bntrmptr ; bntrmptr = bntrmptr->nextpin ; aflag = 0 ; } else { /* anet is equal to bnet */ if( aflag ) { /* the current pointer is on antrmptr list*/ nextptr = antrmptr ; antrmptr = antrmptr->nextpin ; } else { /* the current pointer is on bntrmptr list*/ nextptr = bntrmptr ; bntrmptr = bntrmptr->nextpin ; } } } else if( antrmptr == PINNULL && bntrmptr != PINNULL ) { nextptr = bntrmptr ; bntrmptr = bntrmptr->nextpin ; } else if( antrmptr && bntrmptr == PINNULL ) { nextptr = antrmptr ; antrmptr = antrmptr->nextpin ; } else { nextptr = PINNULL ; } memoptrS[ ++kS ] = nextptr ; if( dimptr->dflag == 0 || dimptr->ignore == 1 ) { continue ; } if( dimptr->numpins <= break_pt ) { dimptr->dflag = 0 ; wire_boundary1( dimptr ) ; } else { /* The pin No. of the net is greater than break_pt */ check_validbound( dimptr , termptr , nextptr ) ; if( nextptr && curr_netS == nextptr->net ) { continue ; } dimptr->dflag = 0 ; wire_boundary2( validLS + 2*validBS + 4*validRS + 8*validTS , dimptr ) ; validRS = validLS = validBS = validTS = 0 ; } /* add2net_set remembers which nets are modified by this move */ add2net_set( curr_netS ) ; dimptr->newhalfPx = dimptr->newxmax - dimptr->newxmin ; dimptr->newhalfPy = dimptr->newymax - dimptr->newymin ; *costptr = *costptr + ( dimptr->newhalfPx - dimptr->halfPx + (INT)(vertical_wire_weightG * (DOUBLE)dimptr->newhalfPy) - (INT)(vertical_wire_weightG * (DOUBLE)dimptr->halfPy) ); } } wire_boundary1( dimptr ) DBOXPTR dimptr ; { PINBOXPTR netptr ; INT x , y ; if( netptr = dimptr->pins ) { if( netptr->flag == 1 ) { dimptr->newxmin = dimptr->newxmax = netptr->newx ; dimptr->newymin = dimptr->newymax = netptr->newy ; netptr->flag = 0 ; } else { dimptr->newxmin = dimptr->newxmax = netptr->xpos ; dimptr->newymin = dimptr->newymax = netptr->ypos ; } } for( netptr = netptr->next ; netptr; netptr = netptr->next ) { if( netptr->flag == 1 ) { x = netptr->newx ; y = netptr->newy ; netptr->flag = 0 ; } else { x = netptr->xpos ; y = netptr->ypos ; } if( x < dimptr->newxmin ) { dimptr->newxmin = x ; } else if( x > dimptr->newxmax ) { dimptr->newxmax = x ; } if( y < dimptr->newymin ) { dimptr->newymin = y ; } else if( y > dimptr->newymax ) { dimptr->newymax = y ; } } } check_validbound( dimptr , termptr , nextptr ) DBOXPTR dimptr ; PINBOXPTR termptr , nextptr ; { INT nux , nuy , x , y ; nux = termptr->newx ; nuy = termptr->newy ; x = termptr->xpos ; y = termptr->ypos ; if( test_newnetS ) { dimptr->newxmax = dimptr->xmax ; dimptr->newxmin = dimptr->xmin ; dimptr->newymax = dimptr->ymax ; dimptr->newymin = dimptr->ymin ; dimptr->newRnum = dimptr->Rnum ; dimptr->newLnum = dimptr->Lnum ; dimptr->newBnum = dimptr->Bnum ; dimptr->newTnum = dimptr->Tnum ; } if( nux > dimptr->newxmax ) { dimptr->newxmax = nux ; dimptr->newRnum = 1 ; validRS = 1 ; } else if( x != nux && nux == dimptr->newxmax ) { dimptr->newRnum++ ; validRS = 1 ; } else if( x == dimptr->newxmax && nux < dimptr->newxmax ) { dimptr->newRnum-- ; } if( nux < dimptr->newxmin ) { dimptr->newxmin = nux ; dimptr->newLnum = 1 ; validLS = 1 ; } else if( x != nux && nux == dimptr->newxmin ) { dimptr->newLnum++ ; validLS = 1 ; } else if( x == dimptr->newxmin && nux > dimptr->newxmin ) { dimptr->newLnum-- ; } if( nuy > dimptr->newymax ) { dimptr->newymax = nuy ; dimptr->newTnum = 1 ; validTS = 1 ; } else if( y != nuy && nuy == dimptr->newymax ) { dimptr->newTnum++ ; validTS = 1 ; } else if( y == dimptr->newymax && nuy < dimptr->newymax ) { dimptr->newTnum-- ; } if( nuy < dimptr->newymin ) { dimptr->newymin = nuy ; dimptr->newBnum = 1 ; validBS = 1 ; } else if( y != nuy && nuy == dimptr->newymin ) { dimptr->newBnum++ ; validBS = 1 ; } else if( y == dimptr->newymin && nuy > dimptr->newymin ) { dimptr->newBnum-- ; } if( nextptr == PINNULL || curr_netS != nextptr->net ) { if( !validRS && dimptr->newxmax == dimptr->xmax && dimptr->newRnum > 0 ) { validRS = 1 ; } if( !validLS && dimptr->newxmin == dimptr->xmin && dimptr->newLnum > 0 ) { validLS = 1 ; } if( !validTS && dimptr->newymax == dimptr->ymax && dimptr->newTnum > 0 ) { validTS = 1 ; } if( !validBS && dimptr->newymin == dimptr->ymin && dimptr->newBnum > 0 ) { validBS = 1 ; } } } wire_boundary2( c , dimptr ) DBOXPTR dimptr ; INT c ; { PINBOXPTR netptr ; INT x , y , i ; if( c == 15 ) { for( i = 0 ; i <= kS-1 ; i++ ) { memoptrS[i]->flag = 0 ; } return ; } if( netptr = dimptr->pins ) { if( netptr->flag == 1 ) { netptr->flag = 0 ; switch( c ) { case 0 : /* L , R , B , T false */ dimptr->newxmin = dimptr->newxmax = netptr->newx ; dimptr->newymin = dimptr->newymax = netptr->newy ; break ; case 1 : /* R , B , T false */ dimptr->newxmax = netptr->newx ; dimptr->newymin = dimptr->newymax = netptr->newy ; break ; case 2 : /* L , R , T false */ dimptr->newxmin = dimptr->newxmax = netptr->newx ; dimptr->newymax = netptr->newy ; break ; case 3 : /* R , T false */ dimptr->newxmax = netptr->newx ; dimptr->newymax = netptr->newy ; break ; case 4 : /* L , B , T false */ dimptr->newxmin = netptr->newx ; dimptr->newymin = dimptr->newymax = netptr->newy ; break ; case 5 : /* B , T false */ dimptr->newymin = dimptr->newymax = netptr->newy ; break ; case 6 : /* L , T false */ dimptr->newxmin = netptr->newx ; dimptr->newymax = netptr->newy ; break ; case 7 : /* T false */ dimptr->newymax = netptr->newy ; break ; case 8 : /* L , R , B false */ dimptr->newxmin = dimptr->newxmax = netptr->newx ; dimptr->newymin = netptr->newy ; break ; case 9 : /* R , B false */ dimptr->newxmax = netptr->newx ; dimptr->newymin = netptr->newy ; break ; case 10 : /* L , R false */ dimptr->newxmin = dimptr->newxmax = netptr->newx ; break ; case 11 : /* R false */ dimptr->newxmax = netptr->newx ; break ; case 12 : /* L , B false */ dimptr->newxmin = netptr->newx ; dimptr->newymin = netptr->newy ; break ; case 13 : /* B false */ dimptr->newymin = netptr->newy ; break ; case 14 : /* L false */ dimptr->newxmin = netptr->newx ; break ; } } else { switch( c ) { case 0 : /* L , R , B , T false */ dimptr->newxmin = dimptr->newxmax = netptr->xpos ; dimptr->newymin = dimptr->newymax = netptr->ypos ; break ; case 1 : /* R , B , T false */ dimptr->newxmax = netptr->xpos ; dimptr->newymin = dimptr->newymax = netptr->ypos ; break ; case 2 : /* L , R , T false */ dimptr->newxmin = dimptr->newxmax = netptr->xpos ; dimptr->newymax = netptr->ypos ; break ; case 3 : /* R , T false */ dimptr->newxmax = netptr->xpos ; dimptr->newymax = netptr->ypos ; break ; case 4 : /* L , B , T false */ dimptr->newxmin = netptr->xpos ; dimptr->newymin = dimptr->newymax = netptr->ypos ; break ; case 5 : /* B , T false */ dimptr->newymin = dimptr->newymax = netptr->ypos ; break ; case 6 : /* L , T false */ dimptr->newxmin = netptr->xpos ; dimptr->newymax = netptr->ypos ; break ; case 7 : /* T false */ dimptr->newymax = netptr->ypos ; break ; case 8 : /* L , R , B false */ dimptr->newxmin = dimptr->newxmax = netptr->xpos ; dimptr->newymin = netptr->ypos ; break ; case 9 : /* R , B false */ dimptr->newxmax = netptr->xpos ; dimptr->newymin = netptr->ypos ; break ; case 10 : /* L , R false */ dimptr->newxmin = dimptr->newxmax = netptr->xpos ; break ; case 11 : /* R false */ dimptr->newxmax = netptr->xpos ; break ; case 12 : /* L , B false */ dimptr->newxmin = netptr->xpos ; dimptr->newymin = netptr->ypos ; break ; case 13 : /* B false */ dimptr->newymin = netptr->ypos ; break ; case 14 : /* L false */ dimptr->newxmin = netptr->xpos ; break ; } } } if( !validLS ) { dimptr->newLnum = 1 ; } if( !validRS ) { dimptr->newRnum = 1 ; } if( !validBS ) { dimptr->newBnum = 1 ; } if( !validTS ) { dimptr->newTnum = 1 ; } for( netptr = netptr->next ; netptr; netptr = netptr->next ) { if( netptr->flag == 1 ) { x = netptr->newx ; y = netptr->newy ; netptr->flag = 0 ; } else { x = netptr->xpos ; y = netptr->ypos ; } switch( c ) { case 0 : /* L , R , B , T false */ if( x < dimptr->newxmin ) { dimptr->newxmin = x ; dimptr->newLnum = 1 ; } else if( x > dimptr->newxmax ) { dimptr->newxmax = x ; dimptr->newRnum = 1 ; } else if( x == dimptr->newxmin ) { dimptr->newLnum++ ; if( x == dimptr->newxmax ) { dimptr->newRnum++ ; } } else if( x == dimptr->newxmax ) { dimptr->newRnum++ ; } if( y < dimptr->newymin ) { dimptr->newymin = y ; dimptr->newBnum = 1 ; } else if( y > dimptr->newymax ) { dimptr->newymax = y ; dimptr->newTnum = 1 ; } else if( y == dimptr->newymin ) { dimptr->newBnum++ ; if( y == dimptr->newymax ) { dimptr->newTnum++ ; } } else if( y == dimptr->newymax ) { dimptr->newTnum++ ; } break ; case 1 : /* R , B , T false */ if( x > dimptr->newxmax ) { dimptr->newxmax = x ; dimptr->newRnum = 1 ; } else if( x == dimptr->newxmax ) { dimptr->newRnum++ ; } if( y < dimptr->newymin ) { dimptr->newymin = y ; dimptr->newBnum = 1 ; } else if( y > dimptr->newymax ) { dimptr->newymax = y ; dimptr->newTnum = 1 ; } else if( y == dimptr->newymin ) { dimptr->newBnum++ ; if( y == dimptr->newymax ) { dimptr->newTnum++ ; } } else if( y == dimptr->newymax ) { dimptr->newTnum++ ; } break ; case 2 : /* L , R , T false */ if( x < dimptr->newxmin ) { dimptr->newxmin = x ; dimptr->newLnum = 1 ; } else if( x > dimptr->newxmax ) { dimptr->newxmax = x ; dimptr->newRnum = 1 ; } else if( x == dimptr->newxmin ) { dimptr->newLnum++ ; if( x == dimptr->newxmax ) { dimptr->newRnum++ ; } } else if( x == dimptr->newxmax ) { dimptr->newRnum++ ; } if( y > dimptr->newymax ) { dimptr->newymax = y ; dimptr->newTnum = 1 ; } else if( y == dimptr->newymax ) { dimptr->newTnum++ ; } break ; case 3 : /* R , T false */ if( x > dimptr->newxmax ) { dimptr->newxmax = x ; dimptr->newRnum = 1 ; } else if( x == dimptr->newxmax ) { dimptr->newRnum++ ; } if( y > dimptr->newymax ) { dimptr->newymax = y ; dimptr->newTnum = 1 ; } else if( y == dimptr->newymax ) { dimptr->newTnum++ ; } break ; case 4 : /* L , B , T false */ if( x < dimptr->newxmin ) { dimptr->newxmin = x ; dimptr->newLnum = 1 ; } else if( x == dimptr->newxmin ) { dimptr->newLnum++ ; } if( y < dimptr->newymin ) { dimptr->newymin = y ; dimptr->newBnum = 1 ; } else if( y > dimptr->newymax ) { dimptr->newymax = y ; dimptr->newTnum = 1 ; } else if( y == dimptr->newymin ) { dimptr->newBnum++ ; if( y == dimptr->newymax ) { dimptr->newTnum++ ; } } else if( y == dimptr->newymax ) { dimptr->newTnum++ ; } break ; case 5 : /* B , T false */ if( y < dimptr->newymin ) { dimptr->newymin = y ; dimptr->newBnum = 1 ; } else if( y > dimptr->newymax ) { dimptr->newymax = y ; dimptr->newTnum = 1 ; } else if( y == dimptr->newymin ) { dimptr->newBnum++ ; if( y == dimptr->newymax ) { dimptr->newTnum++ ; } } else if( y == dimptr->newymax ) { dimptr->newTnum++ ; } break ; case 6 : /* L , T false */ if( x < dimptr->newxmin ) { dimptr->newxmin = x ; dimptr->newLnum = 1 ; } else if( x == dimptr->newxmin ) { dimptr->newLnum++ ; } if( y > dimptr->newymax ) { dimptr->newymax = y ; dimptr->newTnum = 1 ; } else if( y == dimptr->newymax ) { dimptr->newTnum++ ; } break ; case 7 : /* T false */ if( y > dimptr->newymax ) { dimptr->newymax = y ; dimptr->newTnum = 1 ; } else if( y == dimptr->newymax ) { dimptr->newTnum++ ; } break ; case 8 : /* L , R , B false */ if( x < dimptr->newxmin ) { dimptr->newxmin = x ; dimptr->newLnum = 1 ; } else if( x > dimptr->newxmax ) { dimptr->newxmax = x ; dimptr->newRnum = 1 ; } else if( x == dimptr->newxmin ) { dimptr->newLnum++ ; if( x == dimptr->newxmax ) { dimptr->newRnum++ ; } } else if( x == dimptr->newxmax ) { dimptr->newRnum++ ; } if( y < dimptr->newymin ) { dimptr->newymin = y ; dimptr->newBnum = 1 ; } else if( y == dimptr->newymin ) { dimptr->newBnum++ ; } break ; case 9 : /* R , B false */ if( x > dimptr->newxmax ) { dimptr->newxmax = x ; dimptr->newRnum = 1 ; } else if( x == dimptr->newxmax ) { dimptr->newRnum++ ; } if( y < dimptr->newymin ) { dimptr->newymin = y ; dimptr->newBnum = 1 ; } else if( y == dimptr->newymin ) { dimptr->newBnum++ ; } break ; case 10 : /* L , R false */ if( x < dimptr->newxmin ) { dimptr->newxmin = x ; dimptr->newLnum = 1 ; } else if( x > dimptr->newxmax ) { dimptr->newxmax = x ; dimptr->newRnum = 1 ; } else if( x == dimptr->newxmin ) { dimptr->newLnum++ ; if( x == dimptr->newxmax ) { dimptr->newRnum++ ; } } else if( x == dimptr->newxmax ) { dimptr->newRnum++ ; } break ; case 11 : /* R false */ if( x > dimptr->newxmax ) { dimptr->newxmax = x ; dimptr->newRnum = 1 ; } else if( x == dimptr->newxmax ) { dimptr->newRnum++ ; } break ; case 12 : /* L , B false */ if( x < dimptr->newxmin ) { dimptr->newxmin = x ; dimptr->newLnum = 1 ; } else if( x == dimptr->newxmin ) { dimptr->newLnum++ ; } if( y < dimptr->newymin ) { dimptr->newymin = y ; dimptr->newBnum = 1 ; } else if( y == dimptr->newymin ) { dimptr->newBnum++ ; } break ; case 13 : /* B false */ if( y < dimptr->newymin ) { dimptr->newymin = y ; dimptr->newBnum = 1 ; } else if( y == dimptr->newymin ) { dimptr->newBnum++ ; } break ; case 14 : /* L false */ if( x < dimptr->newxmin ) { dimptr->newxmin = x ; dimptr->newLnum = 1 ; } else if( x == dimptr->newxmin ) { dimptr->newLnum++ ; } break ; } } } dbox_pos( antrmptr ) PINBOXPTR antrmptr ; { DBOXPTR dimptr ; PINBOXPTR termptr ; for( termptr = antrmptr ; termptr != PINNULL;termptr=termptr->nextpin ) { dimptr = netarrayG[ termptr->net ] ; dimptr->xmin = dimptr->newxmin ; dimptr->xmax = dimptr->newxmax ; dimptr->ymin = dimptr->newymin ; dimptr->ymax = dimptr->newymax ; dimptr->halfPx = dimptr->newhalfPx ; dimptr->halfPy = dimptr->newhalfPy ; if( dimptr->numpins >= break_pt + 1 ) { dimptr->Lnum = dimptr->newLnum ; dimptr->Rnum = dimptr->newRnum ; dimptr->Bnum = dimptr->newBnum ; dimptr->Tnum = dimptr->newTnum ; } termptr->xpos = termptr->newx ; termptr->ypos = termptr->newy ; } } dbox_pos_swap( antrmptr ) PINBOXPTR antrmptr ; { DBOXPTR dimptr ; PINBOXPTR termptr ; for( termptr = antrmptr ; termptr != PINNULL;termptr=termptr->nextpin ) { dimptr = netarrayG[ termptr->net ] ; dimptr->xmin = dimptr->newxmin ; dimptr->xmax = dimptr->newxmax ; dimptr->ymin = dimptr->newymin ; dimptr->ymax = dimptr->newymax ; dimptr->halfPx = dimptr->newhalfPx ; dimptr->halfPy = dimptr->newhalfPy ; if( dimptr->numpins >= break_pt + 1 ) { dimptr->Lnum = dimptr->newLnum ; dimptr->Rnum = dimptr->newRnum ; dimptr->Bnum = dimptr->newBnum ; dimptr->Tnum = dimptr->newTnum ; } } } init_dbox_pos_swap( antrmptr ) PINBOXPTR antrmptr ; { DBOXPTR dimptr ; PINBOXPTR termptr ; for( termptr = antrmptr ; termptr != PINNULL;termptr=termptr->nextpin ) { dimptr = netarrayG[ termptr->net ] ; dimptr->newxmin = dimptr->xmin ; dimptr->newxmax = dimptr->xmax ; dimptr->newymin = dimptr->ymin ; dimptr->newymax = dimptr->ymax ; dimptr->newhalfPx = dimptr->halfPx ; dimptr->newhalfPy = dimptr->halfPy ; if( dimptr->numpins >= break_pt + 1 ) { dimptr->newLnum = dimptr->Lnum ; dimptr->newRnum = dimptr->Rnum ; dimptr->newBnum = dimptr->Bnum ; dimptr->newTnum = dimptr->Tnum ; } } } graywolf-0.1.4+20170307gite1bf319/src/twsc/feedest.c000066400000000000000000000404631305746555600213250ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * Copyright (C) 2015 Staf Verhaegen * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: feedest.c DESCRIPTION:feedthru estimation. CONTENTS: feedest() re_estimate_feed_penalty( ) estimate_pass_thru_penalty( row1 , row2 ) INT row1 , row2 ; update_feedest( net ) INT net ; free_up_feedest_malloc() update_segment_data( segptr ) SEGBOXPTR segptr ; PINBOXPTR makeSTpt( net , ptr1 , ptr2 ) INT net ; PINBOXPTR ptr1 , ptr2 ; SEGBOXPTR makeseg( lowptr , highptr ) PINBOXPTR lowptr , highptr ; dbg_cost() DATE: Mar 27, 1989 REVISIONS: Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. Tue Mar 12 17:08:44 CST 1991 - added back missing computation. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) feedest.c (Yale) version 4.9 3/12/91" ; #endif #endif #define FEEDS_VARS #include "standard.h" #include "groute.h" #include "feeds.h" #include "main.h" /* global definitions */ INT *rowfeed_penaltyG ; extern BOOL absolute_minimum_feedsG ; /* static definitions */ static DOUBLE *fd_estimateS ; static INT *min_feedS ; static INT *row_flagS ; static INT chip_width_penaltyS ; static INT *est_min_ratioS ; feedest() { DOUBLE ratio ; INT net , row , toprow , botrow, maxdesire ; DBOXPTR dimptr ; PINBOXPTR ptr ; fd_estimateS = (DOUBLE *)Ysafe_calloc( numChansG + 1, sizeof(DOUBLE) ) ; min_feedS = (INT *)Ysafe_calloc( numChansG + 1, sizeof(INT) ) ; row_flagS = (INT *)Ysafe_calloc( numChansG + 1, sizeof(INT) ) ; rowfeed_penaltyG = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof(INT) ) ; est_min_ratioS = (INT *)Ysafe_malloc( numChansG * sizeof(INT) ) ; maxdesire = barrayG[1]->desire ; for( row = 2 ; row <= numRowsG ; row++ ) { if( maxdesire < barrayG[row]->desire ) { maxdesire = barrayG[row]->desire ; } } ratio = (DOUBLE)(maxdesire) / (DOUBLE)( barrayG[numRowsG]->bycenter - barrayG[1]->bycenter + rowHeightG ) ; ratio = 1.0 / ratio ; /* to fix Kai-Win's bug */ if( absolute_minimum_feedsG ) { if( ratio >= 1.0 ) { chip_width_penaltyS = barrayG[numRowsG]->bycenter - barrayG[1]->bycenter + rowHeightG ; } else { chip_width_penaltyS = maxdesire ; } } else { /* chip_width_penaltyS = 2.0 * (DOUBLE) rowHeightG ; */ chip_width_penaltyS = 6.9 * (DOUBLE) rowHeightG ; } if( !absolute_minimum_feedsG ) { add_Lcorner_feedG = TRUE ; /* Carl */ for( row = 1 ; row <= numRowsG ; row++ ) { if( FeedInRowG[row] == 0 ) { add_Lcorner_feedG = FALSE ; break ; } } /* Carl */ } else { add_Lcorner_feedG = FALSE ; } for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[net] ; if( !(dimptr->pins) ) { continue ; } switch( dimptr->numpins ) { case 0 : case 1 : break ; case 2 : ptr = dimptr->pins ; toprow = ptr->row ; botrow = ptr->next->row ; if( toprow > botrow ) { for( row = botrow + 1 ; row < toprow ; row++ ) { fd_estimateS[row]++ ; min_feedS[row]++ ; } if( ABS( ptr->xpos - ptr->next->xpos ) >= average_feed_sepG ) { fd_estimateS[botrow] += 0.5 ; fd_estimateS[toprow] += 0.5 ; } } else if( toprow < botrow ) { for( row = toprow + 1 ; row < botrow ; row++ ) { fd_estimateS[row]++ ; min_feedS[row]++ ; } if( ABS( ptr->xpos - ptr->next->xpos ) >= average_feed_sepG ) { fd_estimateS[botrow] += 0.5 ; fd_estimateS[toprow] += 0.5 ; } } row_flagS[botrow] = 0 ; row_flagS[toprow] = 0 ; break ; case 3 : case 4 : case 5 : ptr = dimptr->pins ; toprow = botrow = ptr->row ; row_flagS[toprow] = 1 ; for( ptr = ptr->next ; ptr ; ptr = ptr->next ) { row = ptr->row ; if( row < botrow ) { botrow = row ; } if( row > toprow ) { toprow = row ; } row_flagS[row] = 1 ; } for( row = botrow + 1 ; row < toprow ; row++ ) { if( row_flagS[row] ) { fd_estimateS[row]++ ; row_flagS[row] = 0 ; } else { fd_estimateS[row] += 1.5 ; min_feedS[row]++ ; } } if( toprow > botrow ) { fd_estimateS[botrow] += 0.5 ; fd_estimateS[toprow] += 0.5 ; } row_flagS[botrow] = 0 ; row_flagS[toprow] = 0 ; break ; default : ptr = dimptr->pins ; toprow = botrow = ptr->row ; row_flagS[toprow] = 1 ; for( ptr = ptr->next ; ptr ; ptr = ptr->next ) { row = ptr->row ; if( row < botrow ) { botrow = row ; } if( row > toprow ) { toprow = row ; } row_flagS[row] = 1 ; } for( row = botrow + 1 ; row < toprow ; row++ ) { if( row_flagS[row] ) { fd_estimateS[row]++ ; row_flagS[row] = 0 ; } else { fd_estimateS[row] += 1.5 ; min_feedS[row]++ ; } } if( toprow > botrow ) { fd_estimateS[botrow]++ ; fd_estimateS[toprow]++ ; } row_flagS[botrow] = 0 ; row_flagS[toprow] = 0 ; break ; } } estimate_pass_thru_penalty( 1 , numRowsG ) ; } re_estimate_feed_penalty() { INT i , n , row , row_rite , excess_fd , *old_penalty ; DOUBLE ratio , factor ; FEED_DATA *feedptr ; CBOXPTR cellptr ; old_penalty = (INT *)Ysafe_malloc( numChansG * sizeof(INT) ) ; for( row = 1 ; row <= numRowsG ; row++ ) { old_penalty[row] = rowfeed_penaltyG[row] ; feedptr = feedpptrG[row] ; n = 0 ; for( i = 1 ; i <= chan_node_noG ; i++ ) { n += feedptr[i]->needed ; } fd_estimateS[row] = n ; } estimate_pass_thru_penalty( 1 , numRowsG ) ; if( !enough_built_in_feedG ) { goto out ; } for( row = 1 ; row <= numRowsG ; row++ ) { rowfeed_penaltyG[row] = ( 2 * old_penalty[row] + 3 * rowfeed_penaltyG[row] ) / 5 ; cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; row_rite = cellptr->cxcenter + cellptr->tileptr->right ; if( fdWidthG > 0 ) { excess_fd = fdcel_addedG[row] + 1 - ( right_most_in_classG[ row_rite_classG[row] ] - row_rite ) / fdWidthG; } else { excess_fd = fdcel_addedG[row] + 1 - ( right_most_in_classG[ row_rite_classG[row] ] - row_rite ) ; } if( excess_fd <= 0 ) { continue ; } ratio = (DOUBLE)(fdcel_addedG[row]) / (DOUBLE)(FeedInRowG[row]) ; if( ratio <= 0.01 ) { factor = 4 ; } else if( ratio <= 0.03 ) { factor = 8 ; } else if( ratio <= 0.05 ) { factor = 15 ; } else if( ratio <= 0.08 ) { factor = 25 ; } else if( ratio <= 0.10 ) { factor = 30 ; } else if( ratio <= 0.20 ) { factor = 40 ; } else { factor = 50 ; } rowfeed_penaltyG[row] += factor * ratio * (DOUBLE)(rowHeightG) ; } /* fp = TWOPEN("vcost.dat", "a", ABORT ) ; fprintf(fp, " row newcost oldcost\n" ) ; for( row = 1 ; row <= numRowsG ; row++ ) { fprintf(fp," %3d %7d %7d\n", row, rowfeed_penaltyG[row], old_penalty[row] ) ; } TWCLOSE(fp) ; */ out: Ysafe_free( old_penalty ); } #ifdef Carl estimate_pass_thru_penalty( row1 , row2 ) INT row1 , row2 ; { INT row ; DOUBLE ratio ; if( row1 < 1 ) { row1 = 1 ; } if( row2 > numRowsG ) { row2 = numRowsG ; } ratio = (DOUBLE) implicit_feed_count / (DOUBLE) TotRegPins ; if( ratio > 0.0 ) { ratio += 0.1 ; } if( ratio > 1.0 ) { ratio = 1.0 ; } for( row = row1 ; row <= row2 ; row++ ) { if( !absolute_minimum_feeds ) { rowfeed_penaltyG[row] = (2.0 - ratio * 1.2) * rowHeightG ; } else { rowfeed_penaltyG[row] = chip_width_penaltyS ; } } } #else estimate_pass_thru_penalty( row1 , row2 ) INT row1 , row2 ; { INT row ; DOUBLE actual , estimate , act_est_ratio ; if( row1 < 1 ) { row1 = 1 ; } if( row2 > numRowsG ) { row2 = numRowsG ; } for( row = row1 ; row <= row2 ; row++ ) { actual = FeedInRowG[row] ; estimate = fd_estimateS[row] ; if( actual > min_feedS[row] && !absolute_minimum_feedsG ) { if( estimate > 0.0 ) { act_est_ratio = actual / estimate ; } else { act_est_ratio = INT_MAX ; /* fix by Carl 1/25/89 */ } if( act_est_ratio >= 4 ) { rowfeed_penaltyG[row] = rowHeightG * 0.3 ; } else if( act_est_ratio >= 1.0 ) { rowfeed_penaltyG[row] = ( 0.9 - 0.2 * ( act_est_ratio - 1.0 ) ) * rowHeightG ; } else if( act_est_ratio <= 0.5 ) { rowfeed_penaltyG[row] = 6.9 * rowHeightG ; } else { rowfeed_penaltyG[row] = ( 0.9 + 12.0 * ( 1.0 - act_est_ratio ) ) * rowHeightG ; } } else { rowfeed_penaltyG[row] = chip_width_penaltyS ; } } } #endif update_feedest( net ) INT net ; { DBOXPTR dimptr ; SEGBOXPTR seg ; PINBOXPTR ptr ; INT row , toprow , botrow , row1 , row2 ; dimptr = netarrayG[net] ; if( !(dimptr->pins) ) { return ; } switch( dimptr->numpins ) { case 0 : case 1 : case 2 : return ; case 3 : case 4 : case 5 : ptr = dimptr->pins ; toprow = botrow = ptr->row ; row_flagS[toprow] = 1 ; for( ptr = ptr->next ; ptr ; ptr = ptr->next ) { row = ptr->row ; if( row < botrow ) { botrow = row ; } if( row > toprow ) { toprow = row ; } row_flagS[row] = 1 ; } for( row = botrow + 1 ; row < toprow ; row++ ) { if( row_flagS[row] ) { fd_estimateS[row]-- ; row_flagS[row] = 0 ; } else { fd_estimateS[row] -= 1.5 ; } } if( toprow > botrow ) { fd_estimateS[botrow] -= 0.5 ; fd_estimateS[toprow] -= 0.5 ; } row_flagS[botrow] = 0 ; row_flagS[toprow] = 0 ; break ; default : ptr = dimptr->pins ; toprow = botrow = ptr->row ; row_flagS[toprow] = 1 ; for( ptr = ptr->next ; ptr ; ptr = ptr->next ) { row = ptr->row ; if( row < botrow ) { botrow = row ; } if( row > toprow ) { toprow = row ; } row_flagS[row] = 1 ; } for( row = botrow + 1 ; row < toprow ; row++ ) { if( row_flagS[row] ) { fd_estimateS[row]-- ; row_flagS[row] = 0 ; } else { fd_estimateS[row] -= 1.5 ; } } if( toprow > botrow ) { fd_estimateS[botrow]-- ; fd_estimateS[toprow]-- ; } row_flagS[botrow] = 0 ; row_flagS[toprow] = 0 ; break ; } for( seg = netsegHeadG[net]->next ; seg ; seg = seg->next ) { row1 = seg->pin1ptr->row ; row2 = seg->pin2ptr->row ; if( row1 == row2 ) { if( ABS( seg->pin1ptr->pinloc - seg->pin2ptr->pinloc ) <= 1 ) { continue ; } else { fd_estimateS[row1]++ ; } } else { for( row = row1 + 1 ; row < row2 ; row++ ) { fd_estimateS[row]++ ; } if( seg->pin1ptr->pinloc < NEITHER ) { fd_estimateS[row1]++ ; } if( seg->pin2ptr->pinloc > NEITHER ) { fd_estimateS[row2]++ ; } if( add_Lcorner_feedG && seg->switchvalue != nswLINE ) { fd_estimateS[row1] += 0.5 ; fd_estimateS[row2] += 0.5 ; } } } for( ptr = steinerHeadG[net]->next; ptr ; ptr = ptr->next ) { fd_estimateS[ ptr->row ]++ ; } estimate_pass_thru_penalty( botrow , toprow ) ; } free_up_feedest_malloc() { Ysafe_free( fd_estimateS ) ; Ysafe_free( min_feedS ) ; Ysafe_free( row_flagS ) ; Ysafe_free( rowfeed_penaltyG ) ; Ysafe_free( est_min_ratioS ) ; } update_segment_data( segptr ) SEGBOXPTR segptr ; { PINBOXPTR ptr1 , ptr2 ; ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; segptr->flag = NEW ; if( ptr1->row < ptr2->row ) { segptr->pin1ptr = ptr1 ; segptr->pin2ptr = ptr2 ; if( ABS( ptr1->xpos - ptr2->xpos ) >= average_feed_sepG ) { segptr->switchvalue = swL_up ; } else { segptr->switchvalue = nswLINE ; } } else if( ptr1->row > ptr2->row ) { segptr->pin2ptr = ptr1 ; segptr->pin1ptr = ptr2 ; if( ABS( ptr1->xpos - ptr2->xpos ) >= average_feed_sepG ) { segptr->switchvalue = swL_up ; } else { segptr->switchvalue = nswLINE ; } } else if( (INT) ptr1->pinloc == BOTCELL && (INT) ptr2->pinloc == TOPCELL ) { segptr->pin1ptr = ptr1 ; segptr->pin2ptr = ptr2 ; segptr->switchvalue = nswLINE ; } else if( (INT) ptr1->pinloc == TOPCELL && (INT) ptr2->pinloc == BOTCELL ) { segptr->pin1ptr = ptr2 ; segptr->pin2ptr = ptr1 ; segptr->switchvalue = nswLINE ; } else if( ptr1->xpos <= ptr2->xpos ) { segptr->pin1ptr = ptr1 ; segptr->pin2ptr = ptr2 ; segptr->switchvalue = nswLINE ; } else { segptr->pin1ptr = ptr2 ; segptr->pin2ptr = ptr1 ; segptr->switchvalue = nswLINE ; } } PINBOXPTR makeSTpt( net , ptr1 , ptr2 ) INT net ; PINBOXPTR ptr1 , ptr2 ; { PINBOXPTR ptr ; ptr = (PINBOXPTR)Ysafe_malloc( sizeof(PINBOX) ) ; ptr->xpos = ptr1->xpos ; ptr->ypos = ptr2->ypos ; ptr->terminal = 0 ; if( ptr1->terminal == 0 ) { ptr->newx = ptr1->newx ; } else { ptr->newx = ptr1->terminal ; } /* the 'newx' field is temporary used for storing the y-direction terminal that steiner points refered to */ ptr->row = ptr2->row ; ptr->pinloc = NEITHER ; ptr->newy = 3 * ptr->row ; ptr->net = net ; ptr->adjptr = (ADJASEGPTR)Ysafe_calloc( 1, sizeof(ADJASEG) ) ; ptr->next = steinerHeadG[net]->next ; steinerHeadG[net]->next = ptr ; return( ptr ) ; } SEGBOXPTR makeseg( lowptr , highptr ) PINBOXPTR lowptr , highptr ; { ADJASEG *adj1, *adj2 ; SEGBOXPTR segptr ; segptr = ( SEGBOXPTR )Ysafe_malloc( sizeof(SEGBOX) ) ; if( lowptr->row < highptr->row ) { segptr->pin1ptr = lowptr ; segptr->pin2ptr = highptr ; segptr->switchvalue = swL_up ; } else if( lowptr->row > highptr->row ) { segptr->pin2ptr = lowptr ; segptr->pin1ptr = highptr ; segptr->switchvalue = swL_up ; } else if( (INT) lowptr->pinloc == BOTCELL && (INT) highptr->pinloc == TOPCELL ) { segptr->pin1ptr = lowptr ; segptr->pin2ptr = highptr ; segptr->switchvalue = swL_up ; } else if( (INT) lowptr->pinloc == TOPCELL && (INT) highptr->pinloc == BOTCELL ) { segptr->pin1ptr = highptr ; segptr->pin2ptr = lowptr ; segptr->switchvalue = swL_up ; } else if( lowptr->xpos < highptr->xpos ) { segptr->pin1ptr = lowptr ; segptr->pin2ptr = highptr ; segptr->switchvalue = nswLINE ; } else { segptr->pin2ptr = lowptr ; segptr->pin1ptr = highptr ; segptr->switchvalue = nswLINE ; } adj1 = (ADJASEGPTR)Ysafe_calloc( 1, sizeof(ADJASEG) ) ; adj2 = (ADJASEGPTR)Ysafe_calloc( 1, sizeof(ADJASEG) ) ; adj1->segptr = segptr ; adj2->segptr = segptr ; adj1->next = lowptr->adjptr->next ; adj2->next = highptr->adjptr->next ; lowptr->adjptr->next = adj1 ; highptr->adjptr->next = adj2 ; segptr->next = netsegHeadG[lowptr->net]->next ; netsegHeadG[lowptr->net]->next = segptr ; return( segptr ) ; } dbg_cost() { FILE *fp ; INT row ; DOUBLE cost, ratio ; fp = TWOPEN("vcost.dat", "w", ABORT ) ; fprintf(fp, " rowHeightG = %d\n", rowHeightG ) ; fprintf(fp, " row cost actual estimate ratio\n" ) ; for( row = 1 ; row <= numRowsG ; row++ ) { cost = (DOUBLE)(rowfeed_penaltyG[row]) / (DOUBLE)(rowHeightG) ; ratio = (DOUBLE)(FeedInRowG[row]) / fd_estimateS[row] ; fprintf(fp, " %3d %5.2f %6d %8.2f %8.2f\n", row, cost, FeedInRowG[row], fd_estimateS[row], ratio ) ; } TWCLOSE(fp) ; } dbx_fdpen() { FILE *fp ; FEED_DATA *feedptr ; INT row , i , s ; fp = TWOPEN("pen.dat" , "w", ABORT ) ; fprintf(fp," row min_feedSS fd_estimateS act_feed needed\n" ) ; for( row = 1 ; row <= numRowsG ; row++ ) { feedptr = feedpptrG[row] ; s = 0 ; for( i = 1 ; i <= chan_node_noG ; i++ ) { s += feedptr[i]->needed ; } fprintf(fp," %3d %8d %8d %8d %6d\n", row, min_feedS[row], (INT)fd_estimateS[row] , FeedInRowG[row] , s ) ; } TWCLOSE(fp) ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/feeds.h000066400000000000000000000014141305746555600207720ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) feeds.h (Yale) version 4.2 9/7/90" FILE: feeds.h DESCRIPTION:TimberwolfSC insert file for feedthrus. CONTENTS: DATE: Mar 27, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef FEEDS_H #define FEEDS_H #ifdef FEEDS_VARS #define EXTERN #else #define EXTERN extern #endif typedef struct feed_assgn_box { PINBOXPTR netptr ; PINBOXPTR refer ; SEGBOXPTR segptr ; } *FEED_SEG_PTR , FEED_SEG ; EXTERN INT *feeds_in_rowG ; EXTERN INT *FeedInRowG ; EXTERN INT fdWidthG ; EXTERN INT *fdcel_addedG ; EXTERN INT **fdcel_needG ; EXTERN INT *total_feed_in_the_rowG ; #undef EXTERN #endif /* FEEDS_H */ graywolf-0.1.4+20170307gite1bf319/src/twsc/findcost.c000066400000000000000000000667421305746555600215270ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: findcost.c DESCRIPTION:calculate total cost of placement. CONTENTS: findcost() create_cell( ) find_net_sizes() DATE: Mar 27, 1989 REVISIONS: Apr 1, 1990 - added missing ignore test for wire penalty. Moved to the correct place. Thu Dec 20 00:09:18 EST 1990 - removed += operator. Tue Jan 29 23:38:32 EST 1991 - added WARNING of large pins to output file and stderr. Mon Feb 11 23:53:22 EST 1991 - commented out unnecessary call to findunlap. Wed Jul 3 13:49:49 CDT 1991 - now print out pins of any size as a debug function. Wed Aug 28 15:03:52 EDT 1991 - now place the pads initially and added IGNORE info for large pin warning. Thu Sep 19 14:15:51 EDT 1991 - added equal width cell capability. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) findcost.c (Yale) version 4.18 4/2/92" ; #endif #endif #define EXTRA_BIN 0.50 #define MAXNUMPINS 100 /* WPS */ /* #define MITLL */ #include "standard.h" #include "groute.h" #include "main.h" #include "config.h" #include "readpar.h" #include "parser.h" #include #include /* global variables */ INT minxspanG ; extern INT extra_cellsG ; extern INT spacer_widthG ; extern INT approximately_fixed_factorG ; extern BOOL rigidly_fixed_cellsG ; extern INT *feeds_in_rowG ; /* static variables */ static INT maxpinS = 0 ; static INT iwireS ; static INT iwirexS ; static INT iwireyS ; static INT print_pinS = 0 ; static spread_equal_cells(); static spread_cells(); findcost() { INT block , bin ; FILE *fp ; TIBOXPTR tile , tileptr1 ; CBOXPTR cellptr1 , ptr ; DBOXPTR dimptr ; PINBOXPTR netptr , termptr ; BINPTR bptr ; char filename[256] ; INT left , right , corient , val ; INT LoBin , HiBin ; INT cell , net , blk ; INT startx , endx ; INT x , y , t , cost=0 ; INT temp , n , k , cbin ; INT sum, npins ; INT net_pin_num[ MAXNUMPINS + 1 ] , *adjust_left ; DOUBLE deviation ; INT pathcount , shortest_cell , count, length ; INT layer ; PATHPTR path ; GLISTPTR net_of_path ; extern char *find_layer() ; char *pinname ; blkleftG = INT_MAX ; blkriteG = INT_MIN ; adjust_left = (INT *)Ysafe_malloc( ( numRowsG + 1 ) * sizeof(INT) ) ; for( block = 1 ; block <= numRowsG ; block++ ) { /* ------------- finding the absolute left (blkleftG) and ----------- ------------- the absolute right (blkriteG) positions ----------- */ if( barrayG[ block ]->bxcenter + barrayG[ block ]->bleft < blkleftG ) { blkleftG = barrayG[ block ]->bxcenter + barrayG[ block ]->bleft ; } if( barrayG[ block ]->bxcenter + barrayG[ block ]->bright > blkriteG ) { blkriteG = barrayG[ block ]->bxcenter + barrayG[ block ]->bright ; } adjust_left[ block ] = INT_MAX ; } binOffstG = blkleftG ; max_blklengthG = blkriteG - blkleftG ; deviation = 0 ; temp = 0 ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { temp += carrayG[ cell ]->clength ; } mean_widthG = temp / (numcellsG - extra_cellsG) ; fprintf(fpoG,"Original Average Cell Width:%f\n", mean_widthG ) ; /* modification by Carl 10/5/89 */ /* an attempt to rectify a large cell problem */ shortest_cell = INT_MAX ; count = 0 ; temp = 0 ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( carrayG[cell]->cclass < 0 ) { continue ; } count++ ; if( carrayG[cell]->clength <= 2.0 * mean_widthG ) { temp += carrayG[ cell ]->clength ; } if( carrayG[cell]->clength < shortest_cell ) { shortest_cell = carrayG[cell]->clength ; } } if( gate_arrayG && rigidly_fixed_cellsG ) { mean_widthG = shortest_cell ; } else { if( count > 0 ) { mean_widthG = temp / count ; } else { /* this is only used if all cells are fixed */ count = 0 ; temp = 0 ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { count++ ; temp += carrayG[ cell ]->clength ; } mean_widthG = temp / count ; } } fprintf(fpoG,"Adjusted Average Cell Width:%f\n", mean_widthG ) ; t = 0 ; for( cell = numcellsG + 1 ; cell <= lastpadG ; cell++ ) { t += carrayG[cell]->numterms ; } /* New by Carl 9/11/89 to get the proper pin sep avg's */ temp = 0 ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { temp += carrayG[cell]->clength ; } /* **** */ average_pin_sepG = temp / ( maxtermG - t ) ; if( implicit_feed_countG ) { average_feed_sepG = temp / implicit_feed_countG ; if( average_feed_sepG > 4 * average_pin_sepG ) { average_feed_sepG = 4 * average_pin_sepG ; } } else { average_feed_sepG = 4 * average_pin_sepG ; } #ifdef MITLL average_feed_sep *= 2 ; #endif for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { deviation += ( carrayG[ cell ]->clength - mean_widthG ) * ( carrayG[ cell ]->clength - mean_widthG ) ; } deviation = sqrt( deviation / (numcellsG - extra_cellsG) ) ; binWidthG = ( INT ) ( mean_widthG ) ; if(!(Equal_Width_CellsG)){ while (1) { numBinsG = ( blkriteG - binOffstG ) / binWidthG ; if( ( blkriteG - binOffstG ) > ( numBinsG * binWidthG ) ) { numBinsG++ ; } if( (DOUBLE) (numBinsG * numRowsG - (numcellsG - extra_cellsG) ) / (DOUBLE)(numcellsG - extra_cellsG) > EXTRA_BIN) break; binWidthG --; } } else { while ( (numBinsG * numRowsG) < (numcellsG - extra_cellsG) ){ numBinsG++ ; } } fprintf( fpoG , "numBinsG automatically set to:%d\n", numBinsG); fprintf( fpoG , "binWidthG = %d\n",binWidthG ) ; fprintf( fpoG , "average_cell_width is:%g\n",mean_widthG ) ; fprintf( fpoG , "standard deviation of cell length is:%g\n", deviation ) ; if( gate_arrayG ) { cells_per_clusterG = 1 ; num_clustersG = extra_cellsG / cells_per_clusterG ; cluster_widthG = cells_per_clusterG * spacer_widthG ; fprintf(fpoG,"\nAdded %d spacer clusters to the gate array\n", num_clustersG); fprintf(fpoG,"cluster width: %d\n", cluster_widthG ) ; } else { num_clustersG = 0 ; } minxspanG = (INT)(mean_widthG + 3.0 * deviation) ; #ifdef OLD_WAY if( gate_arrayG ) { minxspanG = (INT)(mean_widthG + 4.0 * deviation) ; /* factor = 0.0 ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( carrayG[cell]->cclass < 0 ) { factor += (DOUBLE) carrayG[cell]->clength ; } } factor += (DOUBLE)(num_clusters * cluster_width) ; if( total_row_length > (INT) factor ) { factor = (DOUBLE) total_row_length / ((DOUBLE) total_row_length - factor) ; factor = (DOUBLE) minxspanG * factor ; fprintf(fpoG,"\nminxspanG INCREASED from %d to %d\n", minxspanG,(INT)factor); minxspanG = (INT) factor ; } else { fprintf(fpoG,"\nSTRANGE COMPUTATION OF MINXSPAN IN FINDCOST\n"); minxspanG *= 3 ; } */ } #endif /* OLD_WAY */ /*********************************************************** */ if( connection_machineG != 3 ) { sprintf( filename , "%s.res" , cktNameG ) ; fp = TWOPEN( filename , "r", NOABORT) ; } else { sprintf( filename , "%s.cmi" , cktNameG ) ; fp = TWOPEN ( filename , "r", ABORT ) ; } if( !(fp) ) { /* * Could not open the file cktName.res */ if( resume_runG == YES ) { fprintf(fpoG,"Could not use resume file: %s ", filename ) ; fprintf(fpoG,"since it could not be found\n"); } else { fprintf(fpoG,"TimberWolfSC starting from the beginning\n"); } } else if( resume_runG == NO ) { fprintf(fpoG,"Use of resume file: %s was not requested\n", filename); } else { if( connection_machineG != 3 ) { fprintf( fpoG, "Resuming TimberWolfSC from previous saved "); fprintf( fpoG, "placement in %s\n", filename ); TW_oldin( fp ) ; /* findunlap(0); */ TWCLOSE( fp ) ; } else { fprintf( fpoG, "Starting TimberWolfSC with connection "); fprintf( fpoG, "machine placement in %s\n", filename ); incm( fp ) ; TWCLOSE( fp ) ; } } sortpin() ; for( cell = 1 ; cell <= lastpadG ; cell++ ) { ptr = carrayG[ cell ] ; corient = ptr->corient ; block = ptr->cblock ; tile = ptr->tileptr ; if( cell <= numcellsG - extra_cellsG ) { ptr->cycenter = barrayG[block]->bycenter ; if( adjust_left[block] > ptr->cxcenter + tile->left ) { adjust_left[block] = ptr->cxcenter + tile->left ; } for( termptr = ptr->pins;termptr;termptr =termptr->nextpin ) { termptr->xpos = termptr->txpos[corient/2] + ptr->cxcenter; termptr->ypos = termptr->typos[corient%2] + ptr->cycenter; } } else if( cell > numcellsG ) { for( termptr = ptr->pins;termptr;termptr =termptr->nextpin ) { termptr->xpos = termptr->txpos[1] + ptr->cxcenter; termptr->ypos = termptr->typos[1] + ptr->cycenter; } } } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ /* @@@ calculate the initial wire cost of user's placement @@@ */ iwirexS = 0 ; iwireyS = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[ net ] ; if( !(netptr = dimptr->pins)) { continue ; } dimptr->xmin = dimptr->xmax = netptr->xpos ; dimptr->ymin = dimptr->ymax = netptr->ypos ; for( netptr = netptr->next ; netptr ; netptr = netptr->next ) { x = netptr->xpos ; y = netptr->ypos ; if( x < dimptr->xmin ) { dimptr->xmin = x ; } else if( x > dimptr->xmax ) { dimptr->xmax = x ; } if( y < dimptr->ymin ) { dimptr->ymin = y ; } else if( y > dimptr->ymax ) { dimptr->ymax = y ; } } cost += dimptr->halfPx = dimptr->newhalfPx = dimptr->xmax - dimptr->xmin ; dimptr->halfPy = dimptr->newhalfPy = dimptr->ymax - dimptr->ymin ; cost = cost + (INT)( vertical_wire_weightG * (DOUBLE) dimptr->halfPy ) ; iwirexS += dimptr->xmax - dimptr->xmin ; iwireyS += dimptr->ymax - dimptr->ymin ; } fprintf( fpoG, "\n\n\nTHIS IS THE ROUTE COST OF THE "); fprintf( fpoG, "ORIGINAL PLACEMENT: %d\n" , cost ) ; /* @@@@@@@@@@@@@@@@@@@@@@ calculation end @@@@@@@@@@@@@@@@@@@@ */ /* $$$$$$$$$$$ move the cells in each block such that $$$$$$$ */ /* $$$$$$$$$$$ they line up with the left edge of block $$$$$$$ */ if( resume_runG == NO ) { for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { ptr = carrayG[cell] ; corient = ptr->corient ; block = ptr->cblock ; ptr->cxcenter -= adjust_left[block] - barrayG[block]->bxcenter - barrayG[block]->bleft ; for( termptr = ptr->pins ;termptr;termptr = termptr->nextpin ) { termptr->xpos = termptr->txpos[corient/2] + ptr->cxcenter; termptr->ypos = termptr->typos[corient%2] + ptr->cycenter; } } } /* $$$$$$$$$$$$$$$$$$$$$$ adjustment end $$$$$$$$$$$$$$$$$$$$$$ */ for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( carrayG[cell]->fence != NULL ) { carrayG[cell]->fence->min_xpos = carrayG[cell]->cxcenter - approximately_fixed_factorG * minxspanG ; carrayG[cell]->fence->max_xpos = carrayG[cell]->cxcenter + approximately_fixed_factorG * minxspanG ; } } /*********************************************************** */ cost = 0 ; iwirexS = 0 ; iwireyS = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[ net ] ; if( netptr = dimptr->pins ) { while( carrayG[netptr->cell]->ECO_flag ) { fprintf(fpoG,"ECO pin skipped for net <%s>\n", netarrayG[netptr->net]->name ) ; netptr = netptr->next ; if( netptr == NULL ) { break ; } } if( netptr == NULL ) { continue ; } dimptr->xmin = dimptr->xmax = netptr->xpos ; dimptr->ymin = dimptr->ymax = netptr->ypos ; dimptr->Lnum = dimptr->Rnum = 1 ; dimptr->Bnum = dimptr->Tnum = 1 ; netptr = netptr->next ; } n = 1 ; for( ; netptr ; netptr = netptr->next ) { while( carrayG[netptr->cell]->ECO_flag ) { fprintf(fpoG,"ECO pin skipped for net <%s>\n", netarrayG[netptr->net]->name ) ; netptr = netptr->next ; if( netptr == NULL ) { break ; } } if( netptr == NULL ) { break ; } x = netptr->xpos ; y = netptr->ypos ; if( x < dimptr->xmin ) { dimptr->xmin = x ; dimptr->Lnum = 1 ; } else if( x == dimptr->xmin ) { dimptr->Lnum++ ; if( x == dimptr->xmax ) { dimptr->Rnum++ ; } } else if( x > dimptr->xmax ) { dimptr->xmax = x ; dimptr->Rnum = 1 ; } else if( x == dimptr->xmax ) { dimptr->Rnum++ ; } if( y < dimptr->ymin ) { dimptr->ymin = y ; dimptr->Bnum = 1 ; } else if( y == dimptr->ymin ) { dimptr->Bnum++ ; if( y == dimptr->ymax ) { dimptr->Tnum++ ; } } else if( y > dimptr->ymax ) { dimptr->ymax = y ; dimptr->Tnum = 1 ; } else if( y == dimptr->ymax ) { dimptr->Tnum++ ; } n++ ; } dimptr->numpins = n ; if( dimptr->ignore == 1 ){ continue ; } cost += dimptr->halfPx = dimptr->newhalfPx = dimptr->xmax - dimptr->xmin ; dimptr->halfPy = dimptr->newhalfPy = dimptr->ymax - dimptr->ymin ; cost = cost + (INT)( vertical_wire_weightG * (DOUBLE) dimptr->halfPy ) ; D( "twsc/findcost", fprintf( fpoG, "net:%5d cum cost:%10d\n", net, cost ) ; fflush( fpoG ) ; ) ; iwirexS += dimptr->xmax - dimptr->xmin ; iwireyS += dimptr->ymax - dimptr->ymin ; } iwireS = cost ; for( n = 1 ; n <= MAXNUMPINS ; n++ ) { net_pin_num[ n ] = 0 ; } fprintf( fpoG, "\n" ) ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[ net ] ; maxpinS = MAX( maxpinS, dimptr->numpins ) ; if( dimptr->numpins >= MAXNUMPINS ) { net_pin_num[ MAXNUMPINS ]++ ; if( dimptr->ignore == 1 ) { sprintf(YmsgG, "IGNORED Net <%s> has %d pins\n", dimptr->name, dimptr->numpins ) ; } else { sprintf(YmsgG, "Net <%s> has %d pins\n", dimptr->name, dimptr->numpins ) ; } M( WARNMSG, "findcost", YmsgG ) ; fprintf( fpoG, "WARNING[findcost]:%s", YmsgG ) ; } else { net_pin_num[ dimptr->numpins ]++ ; } if( print_pinS ){ if( dimptr->numpins == print_pinS ){ fprintf( fpoG, "A net with %d pin[s]:net%d - %s\n" , print_pinS, net, netarrayG[net]->name ) ; for( termptr=dimptr->pins;termptr;termptr=termptr->next){ cell = termptr->cell ; pinname = find_layer( termptr->pinname, &layer ) ; fprintf( fpoG, "\tpinname:%s cellname:%s cellnum:%d\n", pinname, carrayG[cell]->cname, cell ) ; } } } } /* for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { n = 0 ; for( termptr = carrayG[cell]->pins;termptr;termptr=termptr->nextpin ) { n++ ; } if( n < 1 ) { fprintf(fpoG,"This cell has no pins: %s\n", carrayG[cell]->cname); } } */ sum = npins = 0 ; for( n = 1 ; n < MAXNUMPINS ; n++ ) { if( net_pin_num[ n ] ){ fprintf( fpoG, "The number of nets with %d pins is %d\n", n , net_pin_num[ n ] ) ; } sum += n * net_pin_num[ n ] ; npins += net_pin_num[ n ] ; } fprintf( fpoG, "The number of nets with %d pins or more is %d\n", MAXNUMPINS, net_pin_num[ MAXNUMPINS ] ) ; fprintf( fpoG, "Average number of pins per net = %f\n", (DOUBLE) sum / (DOUBLE) npins ) ; fprintf( fpoG, "The maximum number of pins on a single net is:%d\n", maxpinS ) ; binpenalG = 0 ; rowpenalG = 0 ; penaltyG = 0 ; /* set up the initial bin-penalty */ binptrG = ( BINPTR ** ) Ysafe_malloc( (numRowsG + 1 ) * sizeof( BINPTR * ) ) ; for( block = 1 ; block <= numRowsG ; block++ ) { binptrG[block] = (BINPTR * ) Ysafe_malloc( (numBinsG + 1) * sizeof( BINPTR ) ) ; left = barrayG[ block ]->bleft + barrayG[ block ]->bxcenter ; right = barrayG[ block ]->bleft + barrayG[ block ]->bxcenter + barrayG[ block ]->desire ; /* ---------------------------------------------------------------- SetBin(x) = ((numBinsG = ((x) - binOffstG) / binWidthG)) ---------------------------------------------------------------- */ LoBin = SetBin( left ) ; HiBin = SetBin( right ) ; for( bin = 0 ; bin <= numBinsG ; bin++ ) { binptrG[block][bin] = (BINBOX *) Ysafe_malloc( sizeof(BINBOX) ) ; binptrG[block][bin]->cell = (INT *)Ysafe_malloc( 10 * sizeof(INT) ); /* ------------------------------------------------------------------ This structure is a little tricky to understand. The structure can be thought of as rows of bins, one for each block. Each row of bins is a structure which has five members left, right, *cell, penalty, and nupenalty ... ------------------------------------------------------------------ */ bptr = binptrG[block][bin] ; bptr->cell[0] = 0 ; if( Equal_Width_CellsG ){ bptr->right = binOffstG + (bin+1) * binWidthG ; } else { bptr->right = binOffstG + bin * binWidthG ; } bptr->left = bptr->right - binWidthG ; if( !(Equal_Width_CellsG )){ if( bin == LoBin ) { bptr->penalty = left - bptr->right ; } else if( bin == HiBin ) { bptr->penalty = bptr->left - right ; } else if( bin > HiBin || bin < LoBin ) { bptr->penalty = 0 ; } else { bptr->penalty = - binWidthG ; } } else { bptr->penalty = 0 ; } } } if( Equal_Width_CellsG ){ spread_equal_cells() ; } else { spread_cells() ; } /* if( gate_arrayG ) { install_clusters() ; } */ if( Equal_Width_CellsG ){ rowpenalG = 0 ; binpenalG = 0 ; } else { for( block = 1 ; block <= numRowsG ; block++ ) { for( bin = 0 ; bin <= numBinsG ; bin++ ) { val = binptrG[block][bin]->penalty ; binpenalG += ABS( val ) ; } } for( blk = 1 ; blk <= numRowsG ; blk++ ) { rowpenalG += ABS(barrayG[blk]->oldsize - barrayG[blk]->desire) ; } } /* end else Equal_Width_CellsG */ penaltyG = (INT)( binpenConG * (DOUBLE) binpenalG + roLenConG * (DOUBLE) rowpenalG ) ; /* ************** place the pads ****************** */ placepads() ; cost = recompute_wirecost() ; /* ************* now calculate the timing penalty ************** */ timingcostG = 0 ; for( pathcount = 1 ; pathcount <= numpathsG ; pathcount++ ) { path = patharrayG[pathcount] ; length = 0 ; ASSERTNCONT( path, "findcost", "pointer to path is NULL" ) ; /* for all nets k of a path i */ /* ----------------------------------------------------------------- For all nets k of a path i: We use the minimum strength driver for each net to calculate the lower bound on the length and the maximum strength driver for the upper bound on the length. The user must take false paths into account when specifying the driver strengths. ------------------------------------------------------------------ */ for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ length = length + (INT) (horizontal_path_weightG * (DOUBLE) dimptr->halfPx); length = length + (INT) (vertical_path_weightG * (DOUBLE) dimptr->halfPy ) ; } /* save result */ path->path_len = path->new_path_len = length ; /* calculate penalty */ /* no penalty if within target window */ /* lowerbound <= length <= upperbound */ if( length > path->upper_bound ){ timingcostG += length - path->upper_bound ; } else if( length < path->lower_bound ){ timingcostG += path->lower_bound - length ; } } Ysafe_free( adjust_left ); find_net_sizes() ; /* initialize memory for dimbox by using maxpins on a single net */ init_dimbox() ; if( connection_machineG == 2 ) { create_cell() ; } insert_row(0) ; /* allocate space for counting feed thrus in the rows */ feeds_in_rowG = (INT *) Ysafe_calloc( 1+numRowsG,sizeof(INT) ); return( cost ) ; } /* end findcost */ static spread_equal_cells() { FILE *tp ; CBOXPTR cellptr1 ; TIBOXPTR tileptr1 ; INT bin, cell ; INT startx , endx ; INT kk , k , cbin ; INT LoBin , HiBin ; INT block, x_cxcenter ; BOOL BIN_FOUND ; D( "equal_width_cells", tp = TWOPEN ("bin_placement", "w", ABORT); ) ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { cellptr1 = carrayG[ cell ] ; tileptr1 = cellptr1->tileptr ; block = cellptr1->cblock ; startx = cellptr1->cxcenter + tileptr1->left ; endx = cellptr1->cxcenter + tileptr1->right ; x_cxcenter = cellptr1->cxcenter ; barrayG[block]->oldsize += endx - startx ; cbin = SetBin( cellptr1->cxcenter ) ; /*-- get the cell's bin --*/ LoBin = SetBin( startx ) ; HiBin = SetBin( endx ) ; /* Bins to check are: 0 and LoBin thru HiBin */ /* first check the latter range */ /*-- k = number of cells in a bin --*/ k = (binptrG[block][cbin]->cell[0]) ; if (k == 0) { /*---- Only for the empty bin ----*/ /*---- cell[k] contains the cell number in "cbin" ----*/ ++(binptrG[block][cbin]->cell[0]) ; binptrG[block][cbin]->cell[++k] = cell ; cellptr1->cxcenter = (INT) ((binptrG[block][cbin]->right + binptrG[block][cbin]->left) / (float) 2) ; /*-- hash the cell to the bin --*/ D( "equal_width_cells", fprintf(tp, "\nCell#=%3d -- Block#=%d adjusted into Bin#=%2d x_cxenter=%4d cxcenter=%4d", cell, block, cbin, x_cxcenter, cellptr1->cxcenter); ) ; } else { /*-- throw the cell into an empty bin --*/ BIN_FOUND = FALSE ; for (block = 1 ; block <= numRowsG ; block++) { for (bin = 0 ; bin <= numBinsG ; bin++) { kk = (binptrG[block][bin]->cell[0]) ; if (kk == 0) { ++(binptrG[block][bin]->cell[0]) ; binptrG[block][bin]->cell[++kk] = cell ; cellptr1->cxcenter = (INT) ((binptrG[block][cbin]->right + binptrG[block][bin]->left) / 2) ; /*-- hash the cell to the bin --*/ D( "equal_width_cells", fprintf(tp, "\nCell#=%3d -- Block#=%d placed into Bin#=%2d x_cxenter=%4d cxcenter=%4d", cell, block, bin, x_cxcenter, cellptr1->cxcenter); ) ; BIN_FOUND = TRUE ; break ; } if(BIN_FOUND){ break ; } } } }/*-- end else --*/ } /*--------------------------------------------------------*/ D( "equal_width_cells", fprintf(tp,"\n\n") ; TWCLOSE(tp); ) ; } /* end spread_equal_cells */ static spread_cells() { INT bin, cell ; INT startx , endx ; INT k , cbin ; INT LoBin , HiBin ; INT block ; CBOXPTR cellptr1 ; BINPTR bptr ; TIBOXPTR tileptr1 ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { cellptr1 = carrayG[ cell ] ; tileptr1 = cellptr1->tileptr ; block = cellptr1->cblock ; startx = cellptr1->cxcenter + tileptr1->left ; endx = cellptr1->cxcenter + tileptr1->right ; barrayG[block]->oldsize += endx - startx ; cbin = SetBin( cellptr1->cxcenter ) ; LoBin = SetBin( startx ) ; HiBin = SetBin( endx ) ; /* Bins to check are: 0 and LoBin thru HiBin */ /* first check the latter range */ k = ++(binptrG[block][cbin]->cell[0]) ; if( k % 10 == 0 ) { binptrG[block][cbin]->cell = (INT *) Ysafe_realloc( binptrG[block][cbin]->cell, (k + 10) * sizeof( INT ) ) ; } binptrG[block][cbin]->cell[k] = cell ; if( LoBin == HiBin ) { binptrG[block][LoBin]->penalty += ( endx - startx ) ; } else { bptr = binptrG[block][LoBin] ; bptr->penalty += ( bptr->right - startx ) ; bptr = binptrG[block][HiBin] ; bptr->penalty += ( endx - bptr->left ) ; if( LoBin + 1 < HiBin ) { for( bin = LoBin + 1 ; bin <= HiBin - 1 ; bin++ ) { binptrG[block][bin]->penalty += binWidthG ; } } } } } /* end spread_cells() */ create_cell( ) { FILE *fpr ; char nfilename[128] ; INT pinsep , pin_pos ; INT count , n , j ; INT distance , cellwidth ; INT cell , block ; TIBOXPTR tile ; CBOXPTR ptr ; PINBOXPTR pin ; sprintf( nfilename , "n%s.cel" , cktNameG ) ; fpr = TWOPEN ( nfilename , "w", ABORT ) ; block = 1 ; count = 0 ; j = 0 ; cellwidth = (INT)( mean_widthG ) ; if( cellwidth != cellwidth / 2 * 2 ) { cellwidth++ ; } for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { ptr = carrayG[ cell ] ; tile = ptr->tileptr ; fprintf( fpr, "\ncell %d %s\n", cell , ptr->cname ) ; distance = j++ * cellwidth ; fprintf( fpr , "initially nonfixed %d from left of block %d\n", distance , block ) ; fprintf( fpr , "left %d right %d bottom %d top %d\n" , -cellwidth / 2, cellwidth / 2 , tile->bottom , tile->top ) ; n = 0 ; for( pin = ptr->pins ; pin ; pin = pin->nextpin ){ n++ ; } pinsep = cellwidth / (2*n+1) ; n = 0 ; for( pin = ptr->pins ; pin ; pin = pin->nextpin ){ pin_pos = ( ++n ) * pinsep - cellwidth / 2 ; fprintf( fpr, "pin name %d signal %s %d %d\n", 2*pin->terminal, netarrayG[pin->net]->name, pin_pos , tile->top ) ; fprintf( fpr , "equiv name %d %d %d\n", 2*pin->terminal + 1 ,pin_pos , -tile->top ) ; pin_pos = ( ++n ) * pinsep - cellwidth / 2 ; fprintf( fpr, "pin name %d signal TW_PASS_THRU %d %d\n", 2 * ( maxtermG + ++count ) , pin_pos , tile->top ); fprintf( fpr, "equiv name %d %d %d\n", 2 * ( maxtermG + count ) + 1 , pin_pos , -tile->top); } if( distance >= barrayG[block]->blength && block != numRowsG ) { block++ ; j = 0 ; } } TWCLOSE( fpr ) ; printf( "%s has been established\n", nfilename ) ; exit( 0 ) ; } find_net_sizes() { PINBOXPTR netptr ; DBOXPTR dimptr ; INT i , net , *net_size , limit , *num_nets_of_size , num_nets ; INT j , total , cell ; limit = 6 ; num_nets = 0 ; net_size = (INT *) Ysafe_malloc( (limit + 2) * sizeof(INT) ) ; num_nets_of_size = (INT *) Ysafe_malloc( (limit + 1) * sizeof(INT) ) ; for( i = 0 ; i <= limit ; i++ ) { num_nets_of_size[i] = 0 ; } for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[net] ; for( i = 1 ; i <= limit + 1 ; i++ ) { net_size[i] = 0 ; } for( netptr = dimptr->pins ; netptr ; netptr = netptr->next ){ cell = netptr->cell ; if( cell > numcellsG ) { continue ; } for( i = 1 ; i <= limit ; i++ ) { if( cell == net_size[i] || net_size[i] == 0 ) { break ; } } if( i > limit ) { break ; } else { net_size[i] = cell ; } } for( i = 1 ; i <= limit ; i++ ) { if( net_size[i+1] == 0 ) { break ; } } if( i >= 2 ) { num_nets++ ; num_nets_of_size[i]++ ; } } fprintf(fpoG,"\n"); for( i = 2 ; i <= limit ; i++ ) { total = 0 ; for( j = i ; j <= limit ; j++ ) { total += num_nets_of_size[j] ; } fprintf(fpoG, "Percentage of Nets Connecting to at least %d cells:%4.2f\n", i , (DOUBLE) total / (DOUBLE) num_nets ) ; } fprintf(fpoG,"\n"); fflush(fpoG) ; Ysafe_free( net_size ) ; Ysafe_free( num_nets_of_size ) ; return ; } get_max_pin() { return( maxpinS ) ; } /* end get_max_pin */ set_print_pin( pins ) INT pins ; { print_pinS = pins ; } /* end print_one_pin_nets */ graywolf-0.1.4+20170307gite1bf319/src/twsc/findcostf.c000066400000000000000000000370631305746555600216670ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: findcostf.c DESCRIPTION:find total cost with feeds. CONTENTS: findcostf() installf() install_clusters() place_clusters() DATE: Mar 27, 1989 REVISIONS: Apr 1, 1990 - added missing ignore test for wire penalty. Thu Dec 20 00:23:46 EST 1990 - removed += operator. Thu Jan 31 15:56:05 EST 1991 - added recompute_timecost for reconfig problems. Wed Sep 11 11:18:19 CDT 1991 - modified for new global routing algorith. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) findcostf.c (Yale) version 4.18 4/2/92" ; #endif #endif #include "standard.h" #include "groute.h" #include "config.h" #include "parser.h" #include "feeds.h" #include "main.h" #include #define PICK_INT(l,u) (((l)<(u)) ? ((RAND % ((u)-(l)+1))+(l)) : (l)) /* global variables */ extern INT **bin_configG ; extern BOOL gate_arrayG ; /* static variables */ static INT old_numBinS ; static INT cluster_norm_offsetS = 0 ; static INT **cluster_configS ; /* forward declarations */ static void installf(); INT recompute_wirecost() ; INT recompute_timecost() ; findcostf() { TIBOXPTR tileptr1 ; CBOXPTR cellptr1 ; BINPTR bptr ; INT left , right ; INT bin , LoBin , HiBin ; INT block , cell , blk ; INT startx , endx ; INT cost ; INT k , cbin , row ; blkleftG = INT_MAX ; blkriteG = INT_MIN ; for( block = 1 ; block <= numRowsG ; block++ ) { if( barrayG[ block ]->bxcenter + barrayG[ block ]->bleft < blkleftG ) { blkleftG = barrayG[ block ]->bxcenter + barrayG[ block ]->bleft ; } if( barrayG[ block ]->bxcenter + barrayG[ block ]->bright > blkriteG ) { blkriteG = barrayG[ block ]->bxcenter + barrayG[ block ]->bright ; } } binOffstG = blkleftG ; max_blklengthG = blkriteG - blkleftG ; old_numBinS = numBinsG ; numBinsG = (INT)( ( blkriteG - binOffstG ) / binWidthG ) ; if( ( blkriteG - binOffstG ) > ( numBinsG * binWidthG ) ) { numBinsG++ ; } if( numBinsG > old_numBinS ) { for( row = 1 ; row <= numRowsG ; row++ ) { bin_configG[row] = (INT *) Ysafe_realloc( bin_configG[row] , (1 + numBinsG) * sizeof(INT) ) ; for( bin = old_numBinS + 1 ; bin <= numBinsG ; bin++ ) { bin_configG[row][bin] = 0 ; } } } cost = recompute_wirecost() ; binpenalG = 0 ; rowpenalG = 0 ; penaltyG = 0 ; for( block = 1 ; block <= numRowsG ; block++ ) { for( bin = 0 ; bin <= old_numBinS ; bin++ ) { Ysafe_free( binptrG[block][bin]->cell ) ; Ysafe_free( binptrG[block][bin] ) ; } Ysafe_free( binptrG[block] ) ; } for( block = 1 ; block <= numRowsG ; block++ ) { binptrG[block] = (BINPTR * ) Ysafe_malloc( (numBinsG + 1) * sizeof( BINPTR ) ) ; left = barrayG[ block ]->bleft + barrayG[ block ]->bxcenter ; right = barrayG[ block ]->bleft + barrayG[ block ]->bxcenter + barrayG[ block ]->desire ; /* set barray->oldsize to zero for upcoming calculation */ barrayG[ block ]->oldsize = 0 ; LoBin = SetBin( left ) ; HiBin = SetBin( right ) ; for( bin = 0 ; bin <= numBinsG ; bin++ ) { binptrG[block][bin] = (BINBOX *) Ysafe_malloc( sizeof(BINBOX) ) ; binptrG[block][bin]->cell = (INT *)Ysafe_malloc( 10 * sizeof(INT) ); bptr = binptrG[block][bin] ; bptr->cell[0] = 0 ; bptr->right = binOffstG + bin * binWidthG ; bptr->left = bptr->right - binWidthG ; if( bin == LoBin ) { bptr->penalty = left - bptr->right ; } else if( bin == HiBin ) { bptr->penalty = bptr->left - right ; } else if( bin > HiBin || bin < LoBin ) { bptr->penalty = 0 ; } else { bptr->penalty = - binWidthG ; } } } installf() ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { cellptr1 = carrayG[ cell ] ; tileptr1 = cellptr1->tileptr ; block = cellptr1->cblock ; startx = cellptr1->cxcenter + tileptr1->left ; endx = cellptr1->cxcenter + tileptr1->right ; barrayG[block]->oldsize += endx - startx ; cbin = SetBin( cellptr1->cxcenter ) ; LoBin = SetBin( startx ) ; HiBin = SetBin( endx ) ; k = ++(binptrG[block][cbin]->cell[0]) ; if( k % 10 == 0 ) { binptrG[block][cbin]->cell = (INT *) Ysafe_realloc( binptrG[block][cbin]->cell, (k + 10) * sizeof( INT ) ) ; } binptrG[block][cbin]->cell[k] = cell ; if( LoBin == HiBin ) { binptrG[block][LoBin]->penalty += ( endx - startx ) ; } else { bptr = binptrG[block][LoBin] ; bptr->penalty += ( bptr->right - startx ) ; bptr = binptrG[block][HiBin] ; bptr->penalty += ( endx - bptr->left ) ; if( LoBin + 1 < HiBin ) { for( bin = LoBin + 1 ; bin <= HiBin - 1 ; bin++ ) { binptrG[block][bin]->penalty += binWidthG ; } } } } for( block = 1 ; block <= numRowsG ; block++ ) { for( bin = 0 ; bin <= numBinsG ; bin++ ) { binpenalG += ABS( binptrG[block][bin]->penalty ) ; } } for( blk = 1 ; blk <= numRowsG ; blk++ ) { rowpenalG += ABS(barrayG[blk]->oldsize - barrayG[blk]->desire) ; } penaltyG = (INT)( binpenConG * (DOUBLE) binpenalG + roLenConG * (DOUBLE) rowpenalG ) ; timingcostG = recompute_timecost() ; return( cost ) ; } static void installf() { int row , n , i , bin , diff , extra , stop , tmp ; int c_limit , num_trys , cell_num ; INT *c_ptr ; for( row = 1 ; row <= numRowsG ; row++ ) { tmp = feeds_in_rowG[row] * fdWidthG ; if( tmp > barrayG[row]->orig_desire ) { barrayG[row]->oldsize = barrayG[row]->orig_desire ; } else { barrayG[row]->oldsize = tmp ; } } for( row = 1 ; row <= numRowsG ; row++ ) { n = feeds_in_rowG[row] ; if( n < 1 ) { for( bin = 0 ; bin <= numBinsG ; bin++ ) { bin_configG[row][bin] = 0 ; } for( ; bin <= old_numBinS ; bin++ ) { bin_configG[row][bin] = 0 ; } continue ; } extra = 0 ; if( old_numBinS > numBinsG ) { for( bin = numBinsG + 1 ; bin <= old_numBinS ; bin++ ) { if( bin_configG[row][bin] == 1 ) { extra++ ; bin_configG[row][bin] = 0 ; } } } if( n < bin_configG[row][0] - extra ) { diff = bin_configG[row][0] - extra - n ; for( i = 0 ; i < diff ; ) { bin = PICK_INT( 1 , numBinsG ) ; if( bin_configG[row][bin] == 0 ) { continue ; } i++ ; bin_configG[row][bin] = 0 ; } bin_configG[row][0] = n ; } else if( n > bin_configG[row][0] - extra ) { diff = n - (bin_configG[row][0] - extra) ; for( i = 0, num_trys = 0 ; i < diff ; ) { if( ++num_trys > 30 * diff ) { break ; } bin = PICK_INT( 1 , numBinsG ) ; if( bin_configG[row][bin] == 1 ) { continue ; } c_ptr = binptrG[row][bin]->cell ; c_limit = c_ptr[0] ; stop = 0 ; for( cell_num = 1 ; cell_num <= c_limit ; cell_num++ ) { if( carrayG[ c_ptr[cell_num] ]->cclass < 0 ) { stop = 1 ; break ; } } if( stop ) { continue ; } i++ ; bin_configG[row][bin] = 1 ; } bin_configG[row][0] = n - (diff - i) ; } else { bin_configG[row][0] = n ; } for( bin = 1 ; bin <= numBinsG ; bin++ ) { if( bin_configG[row][bin] == 1 ) { binptrG[row][bin]->penalty += binWidthG ; } } } return; } install_clusters() { INT row , n , i , bin , i_error , delta_bin , length_in_row , cell ; INT total ; INT total_actual_clusters ; DOUBLE error , n_DOUBLE , cluster_norm ; fprintf(fpoG,"total number of clusters which should be added in: %d\n", num_clustersG ) ; total_actual_clusters = 0 ; cluster_configS = (INT **) Ysafe_malloc((1 + numRowsG) * sizeof(INT *)) ; for( row = 1 ; row <= numRowsG ; row++ ) { cluster_configS[row] = (INT *) Ysafe_malloc((1+numBinsG)*sizeof(INT)); for( bin = 0 ; bin <= numBinsG ; bin++ ) { cluster_configS[row][bin] = 0 ; } } cluster_norm = (DOUBLE) num_clustersG / (DOUBLE) numRowsG + cluster_norm_offsetS ; if( num_clustersG == 0 ) { return ; } error = 0.0 ; total = 0 ; for( row = 1 ; total < num_clustersG && row <= numRowsG ; row++ ) { length_in_row = 0 ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( carrayG[cell]->cblock == row ) { if( carrayG[cell]->cclass < 0 ) { length_in_row += carrayG[cell]->clength ; } } } n_DOUBLE = cluster_norm + error ; n = (INT) n_DOUBLE ; if( n_DOUBLE - (DOUBLE) n >= 0.5 ) { n++ ; } error = n_DOUBLE - (DOUBLE) n ; while( total + n > num_clustersG ) { n-- ; } if( length_in_row + n * cluster_widthG > barrayG[row]->desire ) { if( row == numRowsG ) { /* can't fit all the required clusters; increase cluster_norm */ ++cluster_norm_offsetS ; for( row = 1 ; row <= numRowsG ; row++ ) { Ysafe_free( cluster_configS[row] ) ; } Ysafe_free( cluster_configS ) ; install_clusters() ; return ; } n = (barrayG[row]->desire - length_in_row) / cluster_widthG ; if( n < 0 ) { n = 0 ; } error += (DOUBLE)( (INT) n_DOUBLE - n ) ; } if( n == 0 ) { continue ; } total += n ; i_error = 0 ; bin = 0 ; for( i = 0 ; i < n ; i++ ) { delta_bin = (numBinsG + i_error) / n ; bin += delta_bin ; i_error += numBinsG - delta_bin * n ; if( bin < 1 ) bin = 1 ; if( bin > numBinsG ) bin = numBinsG ; cluster_configS[row][bin]++ ; } fprintf(fpoG,"Number of clusters added to row:%d was:%d\n", row,i); total_actual_clusters += i ; for( bin = 1 ; bin <= numBinsG ; bin++ ) { if( cluster_configS[row][bin] >= 1 ) { barrayG[row]->oldsize += cluster_configS[row][bin] * cluster_widthG ; } } } fprintf(fpoG,"actual total number of clusters which were added in: %d\n", total_actual_clusters ) ; return; } /* end install_clusters */ place_clusters() { INT bin , cell , row , c , count ; cell = numcellsG - extra_cellsG ; for( row = 1 ; row <= numRowsG ; row++ ) { for( bin = 1 ; bin <= numBinsG ; bin++ ) { if( cluster_configS[row][bin] == 0 ) { continue ; } count = cluster_configS[row][bin] ; for( c = 1 ; c <= count ; c++ ) { carrayG[++cell]->cblock = row ; carrayG[cell]->cycenter = barrayG[row]->bycenter ; carrayG[cell]->cxcenter = (((DOUBLE) bin / (DOUBLE) numBinsG) * (barrayG[row]->bright - barrayG[row]->bleft)) + barrayG[row]->bleft + barrayG[row]->bxcenter ; } } } return ; } /* **************************************************************** */ INT recompute_wirecost() { INT n ; INT x, y ; INT net ; INT cell ; INT cost ; INT corient ; INT block ; CBOXPTR ptr ; DBOXPTR dimptr ; PINBOXPTR netptr , termptr ; for( cell = 1 ; cell <= lastpadG ; cell++ ) { ptr = carrayG[ cell ] ; corient = ptr->corient ; block = ptr->cblock ; if( cell <= numcellsG - extra_cellsG ) { ptr->cycenter = barrayG[block]->bycenter ; for( termptr = ptr->pins ; termptr ; termptr=termptr->nextpin ) { termptr->xpos = termptr->txpos[corient/2] + ptr->cxcenter; termptr->ypos = termptr->typos[corient%2] + ptr->cycenter; } } else if( cell > numcellsG ) { for( termptr = ptr->pins ; termptr ; termptr=termptr->nextpin ) { termptr->xpos = termptr->txpos[1] + ptr->cxcenter; termptr->ypos = termptr->typos[1] + ptr->cycenter; } } } cost = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[ net ] ; if( dimptr->ignore == 1 ){ continue ; } if( netptr = dimptr->pins ) { dimptr->xmin = dimptr->xmax = netptr->xpos ; dimptr->ymin = dimptr->ymax = netptr->ypos ; dimptr->Lnum = dimptr->Rnum = 1 ; dimptr->Bnum = dimptr->Tnum = 1 ; netptr = netptr->next ; } n = 1 ; for( ; netptr ; netptr = netptr->next ) { x = netptr->xpos ; y = netptr->ypos ; if( x < dimptr->xmin ) { dimptr->xmin = x ; dimptr->Lnum = 1 ; } else if( x == dimptr->xmin ) { dimptr->Lnum++ ; if( x == dimptr->xmax ) { dimptr->Rnum++ ; } } else if( x > dimptr->xmax ) { dimptr->xmax = x ; dimptr->Rnum = 1 ; } else if( x == dimptr->xmax ) { dimptr->Rnum++ ; } if( y < dimptr->ymin ) { dimptr->ymin = y ; dimptr->Bnum = 1 ; } else if( y == dimptr->ymin ) { dimptr->Bnum++ ; if( y == dimptr->ymax ) { dimptr->Tnum++ ; } } else if( y > dimptr->ymax ) { dimptr->ymax = y ; dimptr->Tnum = 1 ; } else if( y == dimptr->ymax ) { dimptr->Tnum++ ; } n++ ; } dimptr->numpins = n ; cost += dimptr->halfPx = dimptr->newhalfPx = dimptr->xmax - dimptr->xmin ; dimptr->halfPy = dimptr->newhalfPy = dimptr->ymax - dimptr->ymin ; cost = cost + (INT)( vertical_wire_weightG * (DOUBLE) dimptr->halfPy ) ; } /* end for loop */ return( cost ) ; } /* end recompute_wirecost */ INT recompute_timecost() { INT pathcount ; INT net ; INT timingpenal ; INT length ; PATHPTR path ; DBOXPTR dimptr ; GLISTPTR net_of_path ; /* ************* now calculate the timing penalty ************** */ timingpenal = 0 ; for( pathcount = 1 ; pathcount <= numpathsG ; pathcount++ ) { path = patharrayG[pathcount] ; length = 0 ; ASSERTNCONT( path, "findcost", "pointer to path is NULL" ) ; /* for all nets k of a path i */ /* ----------------------------------------------------------------- For all nets k of a path i: We use the minimum strength driver for each net to calculate the lower bound on the length and the maximum strength driver for the upper bound on the length. The user must take false paths into account when specifying the driver strengths. ------------------------------------------------------------------ */ for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ length = length + (INT) (horizontal_path_weightG * (DOUBLE) dimptr->halfPx) ; length = length + (INT) (vertical_path_weightG * (DOUBLE) dimptr->halfPy) ; } /* save result */ path->path_len = path->new_path_len = length ; /* calculate penalty */ /* no penalty if within target window */ /* lowerbound <= length <= upperbound */ if( length > path->upper_bound ){ timingpenal += length - path->upper_bound ; } else if( length < path->lower_bound ){ timingpenal += path->lower_bound - length ; } } return( timingpenal ) ; } /* end recompute_timecost */ graywolf-0.1.4+20170307gite1bf319/src/twsc/findrcost.c000066400000000000000000000271161305746555600217010ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: findrcost.c DESCRIPTION:find routing cost. CONTENTS: findrcost() initial_tracks( segptr ) SEGBOXPTR segptr ; set_cedgebin() reset_track() facing_cellheight( pin , row , pinloc , status ) INT pin, row , pinloc , status ; DATE: Mar 27, 1989 REVISIONS: Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) findrcost.c (Yale) version 4.6 12/15/90" ; #endif #endif #include "standard.h" #include "groute.h" static INT **cedgebinS ; static INT cedge_binwidthS ; static INT num_edgebinS ; findrcost() { SEGBOXPTR segptr ; CHANGRDPTR gdptr ; DENSITYPTR *hdptr , headptr , dptr ; INT chan ; INT trackG , max_trk , k ; INT net ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ initial_tracks( segptr ) ; } for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ process_cross( segptr , 0 ) ; } } DboxHeadG = ( DENSITYPTR ** )Ysafe_calloc( numChansG + 1, sizeof( DENSITYPTR * ) ) ; maxTrackG = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof( INT ) ) ; nmaxTrackG = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof( INT ) ) ; max_tdensityG = 0 ; tracksG = 0 ; if( uneven_cell_heightG ) { set_cedgebin( ) ; reset_track( ) ; } for( chan = 1 ; chan <= numChansG ; chan++ ) { max_trk = 0 ; for( gdptr = BeginG[ chan ] ; gdptr != GRDNULL ; gdptr = gdptr->nextgrd ) { if( gdptr->tracks > max_trk ) { max_trk = gdptr->tracks ; } } maxTrackG[ chan ] = max_trk ; if( max_trk > max_tdensityG ) { max_tdensityG = max_trk ; } tracksG += max_trk ; } printf(" the starting value of tracks = %4d\n" , tracksG ) ; k = max_tdensityG + 100 ; for( chan = 1 ; chan <= numChansG ; chan++ ) { DboxHeadG[ chan ] = hdptr = ( DENSITYPTR *)Ysafe_calloc( k + 1, sizeof( DENSITYPTR) ) ; for( trackG = 0 ; trackG <= k ; trackG++ ) { hdptr[trackG] = ( DENSITYPTR )Ysafe_calloc( 1, sizeof(DENSITYBOX)); } for( gdptr = BeginG[ chan ] ; gdptr ; gdptr = gdptr->nextgrd ) { trackG = gdptr->tracks ; gdptr->dptr = dptr = ( DENSITYPTR )Ysafe_calloc( 1,sizeof(DENSITYBOX) ) ; headptr = hdptr[trackG] ; if( headptr->next ) { dptr->next = headptr->next ; dptr->next->back = dptr ; headptr->next = dptr ; dptr->back = headptr; } else { headptr->next = dptr ; dptr->back = headptr ; } dptr->grdptr = gdptr ; } } } initial_tracks( segptr ) SEGBOXPTR segptr ; { INT x1 , x2 , pin1 , pin2 ; PINBOXPTR netptr1 , netptr2 ; CHANGRDPTR ptr1 , ptr2 , ptr ; x1 = segptr->pin1ptr->xpos ; x2 = segptr->pin2ptr->xpos ; if( x1 == x2 ) { return ; } netptr1 = segptr->pin1ptr ; netptr2 = segptr->pin2ptr ; pin1 = netptr1->terminal ; pin2 = netptr2->terminal ; if( netptr1->row < netptr2->row ) { ptr1 = TgridG[pin1]->up ; ptr2 = TgridG[pin2]->down ; } else if( netptr1->row > netptr2->row ) { ptr1 = TgridG[pin1]->down ; ptr2 = TgridG[pin2]->up ; } else if( segptr->switchvalue == swUP ) { ptr1 = TgridG[pin1]->up ; ptr2 = TgridG[pin2]->up ; } else if( segptr->switchvalue == swDOWN ) { ptr1 = TgridG[pin1]->down ; ptr2 = TgridG[pin2]->down ; } else if( netptr1->pinloc >= NEITHER && netptr2->pinloc >= NEITHER ) { ptr1 = TgridG[pin1]->up ; ptr2 = TgridG[pin2]->up ; } else { ptr1 = TgridG[pin1]->down ; ptr2 = TgridG[pin2]->down ; } while( ptr1->prevgrd ) { if( ptr1->prevgrd->netptr->xpos == x1 ) { ptr1 = ptr1->prevgrd ; } else { break ; } } while( ptr2->nextgrd ) { if( ptr2->nextgrd->netptr->xpos == x2 ) { ptr2 = ptr2->nextgrd ; } else { break ; } } ptr2 = ptr2->nextgrd ; for( ptr = ptr1 ; ptr != ptr2 ; ptr = ptr->nextgrd ) { if( ptr->cross == 0 ) { ptr->tracks++ ; ptr->cross = 1 ; } } } /* the set_cedgebin() , reset_track , facing_cellheight() function would be used only when the cells are in uneven height */ set_cedgebin() { CBOXPTR cellptr ; INT channel , row , bin , bin_rite_edge , crite ; INT most_left , most_rite , rite , i ; cedgebinS = (INT **)Ysafe_malloc( ( numChansG + 1 ) * sizeof(INT *) ) ; cedge_binwidthS = (INT)( 2.0 * mean_widthG ) ; cellptr = carrayG[ pairArrayG[1][ pairArrayG[1][0] ] ] ; most_rite = cellptr->cxcenter + cellptr->tileptr->right ; for( row = 2 ; row <= numRowsG ; row++ ) { cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; rite = cellptr->cxcenter + cellptr->tileptr->right ; if( rite > most_rite ) { most_rite = rite ; } } num_edgebinS = ( most_rite - blkleftG ) / cedge_binwidthS + 1 ; for( channel = 1 ; channel <= numChansG ; channel++ ) { cedgebinS[ channel ] = (INT *)Ysafe_malloc( ( num_edgebinS + 1 ) * sizeof( INT ) ) ; } for( row = 1 ; row <= numRowsG ; row++ ) { cellptr = carrayG[ pairArrayG[row][1] ] ; most_left = cellptr->cxcenter + cellptr->tileptr->left ; bin_rite_edge = most_left + cedge_binwidthS ; cedgebinS[row][1] = 1 ; bin = 1 ; for( i = 1 ; i <= pairArrayG[row][0] ; i++ ) { cellptr = carrayG[ pairArrayG[row][i] ] ; crite = cellptr->cxcenter + cellptr->tileptr->right ; if( bin_rite_edge < crite ) { while( bin_rite_edge <= crite ) { cedgebinS[row][++bin] = i ; bin_rite_edge += cedge_binwidthS ; } } } for( ++bin ; bin <= num_edgebinS ; bin++ ) { cedgebinS[row][bin] = 0 ; } } } reset_track() { CBOXPTR cellptr ; TIBOXPTR tileptr ; PINBOXPTR termptr ; INT cell , pin , pinloc , row , top , bottom ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = carrayG[cell] ; tileptr = cellptr->tileptr ; row = cellptr->cblock ; top = tileptr->top ; bottom = -tileptr->bottom ; for( termptr = cellptr->pins ;termptr; termptr = termptr->nextpin ) { pin = termptr->terminal ; pinloc = tearrayG[pin]->pinloc ; if( pinloc == TOPCELL ) { TgridG[ pin ]->up->tracks += ( top + facing_cellheight( pin , row , 1 , NEW ) ) / track_pitchG ; } else if( pinloc == BOTCELL ) { TgridG[ pin ]->up->tracks += ( bottom + facing_cellheight( pin , row , -1 , NEW ) ) / track_pitchG; } else { /* pinloc == 0 */ TgridG[ pin ]->up->tracks += ( top + facing_cellheight( pin , row , 1 , NEW ) ) / track_pitchG ; TgridG[ pin ]->down->tracks += ( bottom + facing_cellheight( pin , row , -1 , NEW ) ) / track_pitchG; } } } for( ; cell <= lastpadG ; cell++ ) { cellptr = carrayG[cell] ; for( termptr = cellptr->pins ;termptr; termptr = termptr->nextpin ) { pin = termptr->terminal ; row = tearrayG[ pin ]->row ; TgridG[ pin ]->up->tracks += facing_cellheight( pin , row , 0 , NEW ) / track_pitchG ; } } } facing_cellheight( pin , row , pinloc , status ) INT pin, row , pinloc , status ; { CBOXPTR cellptr ; INT bin , i , *Aray , most_left , most_rite ; INT nrow , pin_x , crite ; if( 1 <= row && row <= numRowsG ) { nrow = row + pinloc - PINLOC_OFFSET ; if( nrow == 0 || nrow == numChansG || pinloc == NEITHER ) { return(0) ; } } else if( row == 0 ) { nrow = 1 ; } else { nrow = numRowsG ; } Aray = pairArrayG[nrow] ; if( status == OLD ) { pin_x = tearrayG[pin]->newx ; } else { pin_x = tearrayG[pin]->xpos ; } cellptr = carrayG[ Aray[1] ] ; most_left = cellptr->cxcenter + cellptr->tileptr->left ; cellptr = carrayG[ Aray[Aray[0]] ] ; most_rite = cellptr->cxcenter + cellptr->tileptr->right ; if( pin_x < most_left || pin_x > most_rite ) { return( 0 ) ; } bin = ( pin_x - most_left ) / cedge_binwidthS + 1 ; if( ( i = cedgebinS[nrow][bin] ) == 0 ) { return( 0 ) ; } cellptr = carrayG[ Aray[i] ] ; if( ( ( cellptr->tileptr->left + cellptr->cxcenter ) == pin_x ) && ( bin >= 2 ) ) { if( carrayG[ Aray[i-1] ]->cheight > cellptr->cheight ) { cellptr = carrayG[ Aray[--i] ] ; } } else { crite = cellptr->tileptr->right + cellptr->cxcenter ; while( crite < pin_x && i < Aray[0] ) { cellptr = carrayG[ Aray[++i] ] ; crite += cellptr->clength ; } if( crite == pin_x && i != Aray[0] ) { if( carrayG[ Aray[i+1] ]->cheight > cellptr->cheight ) { cellptr = carrayG[ Aray[i+1] ] ; } } } if( 1 <= row && row <= numRowsG ) { if( pinloc == TOPCELL ) { return( -cellptr->tileptr->bottom ) ; } else { return( cellptr->tileptr->top ) ; } } else if( row == 0 ) { return( -cellptr->tileptr->bottom ) ; } else { return( cellptr->tileptr->top ) ; } } fcellheight( pin , fcell , status ) INT pin , *fcell , status ; { CBOXPTR cellptr ; INT bin , i , *Aray , most_left , most_rite ; INT nrow , pin_x , crite , row , pinloc ; row = tearrayG[pin]->row ; pinloc = tearrayG[pin]->pinloc ; if( 1 <= row && row <= numRowsG ) { nrow = row + pinloc - PINLOC_OFFSET ; if( nrow == 0 || nrow == numChansG || pinloc == NEITHER ) { *fcell = 0 ; return(0) ; } } else if( row == 0 ) { nrow = 1 ; } else { nrow = numRowsG ; } Aray = pairArrayG[nrow] ; if( status == OLD ) { pin_x = tearrayG[pin]->newx ; } else { pin_x = tearrayG[pin]->xpos ; } cellptr = carrayG[ Aray[1] ] ; most_left = cellptr->cxcenter + cellptr->tileptr->left ; cellptr = carrayG[ Aray[Aray[0]] ] ; most_rite = cellptr->cxcenter + cellptr->tileptr->right ; if( pin_x < most_left || pin_x > most_rite ) { *fcell = 0 ; return( 0 ) ; } bin = ( pin_x - most_left ) / cedge_binwidthS + 1 ; if( ( i = cedgebinS[nrow][bin] ) == 0 ) { *fcell = 0 ; return( 0 ) ; } *fcell = Aray[i] ; cellptr = carrayG[ *fcell ] ; crite = cellptr->tileptr->right + cellptr->cxcenter ; while( crite < pin_x && i < Aray[0] ) { *fcell = Aray[++i] ; cellptr = carrayG[ *fcell ] ; crite += cellptr->clength ; } if( crite == pin_x && i != Aray[0] ) { if( carrayG[ Aray[i+1] ]->cheight > cellptr->cheight ) { *fcell = Aray[i+1] ; cellptr = carrayG[ *fcell ] ; } } if( 1 <= row && row <= numRowsG ) { if( pinloc == TOPCELL ) { return( -cellptr->tileptr->bottom ) ; } else { return( cellptr->tileptr->top ) ; } } else if( row == 0 ) { return( -cellptr->tileptr->bottom ) ; } else { return( cellptr->tileptr->top ) ; } } graywolf-0.1.4+20170307gite1bf319/src/twsc/findunlap.c000066400000000000000000001013721305746555600216630ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: findunlap.c DESCRIPTION:remove overlap from cells. CONTENTS: findunlap(flag) INT flag ; even_the_rows(flag) INT flag ; even_the_rows_2( iteration ) INT iteration ; check_row_length() find_longest_row() ; find_shortest_row() ; find_last_6_moveable_cells( cell1, cell2, cell3, cell4, cell5, cell6 ) INT *cell1, *cell2, *cell3, *cell4, *cell5, *cell6 ; row_cost( long_row , short_row , width ) INT long_row , short_row , width ; DATE: Mar 27, 1989 REVISIONS: Thu Dec 20 00:23:46 EST 1990 - removed += operator. Wed Sep 11 11:19:25 CDT 1991 - modified for new global router. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) findunlap.c (Yale) version 4.14 4/2/92" ; #endif #endif #include "standard.h" #include "main.h" #include "groute.h" #include "feeds.h" #include #define PICK_INT(l,u) (((l)<(u)) ? ((RAND % ((u)-(l)+1))+(l)) : (l)) /* globals */ INT largest_delta_row_lenG ; extern INT **pairArrayG ; extern INT exact_feedsG ; extern INT extra_cellsG ; extern INT actual_feed_thru_cells_addedG ; extern BOOL gate_arrayG ; extern BOOL no_row_lengthsG ; extern DOUBLE mean_widthG ; extern INT *feeds_in_rowG ; static INT *row_lengthS ; static BOOL first_passS = TRUE ; findunlap(flag) INT flag ; { CBOXPTR cellptr , ptr ; TIBOXPTR tileptr ; DBOXPTR dimptr ; PINBOXPTR termptr , netptr ; INT cost , corient , last_cell , total_penalty ; INT block , cell , bin ; INT i , n , xwire, ywire ; INT bigblkx ; INT net , x , y , *blklen , k ; INT pathcount ; INT delta_row_len ; INT length , tmp ; PATHPTR path ; GLISTPTR net_of_path ; blklen = (INT *) Ysafe_malloc( (numRowsG + 1) * sizeof( INT ) ) ; for( i = 0 ; i <= numRowsG ; i++ ) { blklen[i] = 0 ; } if( pairArrayG != NULL ) { for( block = 1 ; block <= numRowsG ; block++ ) { Ysafe_free( pairArrayG[block] ) ; } Ysafe_free( pairArrayG ) ; pairArrayG = NULL ; } if( flag == 2 ) { unlap(2) ; } else if( flag == 0 ) { unlap(0) ; } else { unlap(1) ; } if( binptrG != NULL ) { for( block = 1 ; block <= numRowsG ; block++ ) { for( bin = 0 ; bin <= numBinsG ; bin++ ) { Ysafe_free( binptrG[ block ][ bin ]->cell ) ; Ysafe_free( binptrG[ block ][ bin ] ) ; } Ysafe_free( binptrG[ block ] ) ; } Ysafe_free( binptrG ) ; binptrG = NULL ; } for( cell = 1 ; cell <= numcellsG ; cell++ ) { ptr = carrayG[ cell ] ; corient = ptr->corient ; for( termptr = ptr->pins ; termptr; termptr = termptr->nextpin ){ x = termptr->txpos[ corient/2 ] + ptr->cxcenter; if( flag == 2 && x != termptr->xpos ) { if( cell <= numcellsG - extra_cellsG ) { printf("actual cell %d x error\n", cell ); } else { printf("extra cell %d y error\n", cell ); } } termptr->xpos = termptr->txpos[ corient/2 ] + ptr->cxcenter; y = termptr->typos[ corient%2 ] + ptr->cycenter; if( flag == 2 && y != termptr->ypos ) { if( cell <= numcellsG - extra_cellsG ) { printf("actual cell %d y error\n", cell ); } else { printf("extra cell %d y error\n", cell ); } } termptr->ypos = termptr->typos[ corient%2 ] + ptr->cycenter; termptr->newx = 0 ; termptr->newy = 0 ; termptr->row = ptr->cblock ; } } for( cell = numcellsG + 1 ; cell <= lastpadG ; cell++ ) { ptr = carrayG[ cell ] ; for( termptr = ptr->pins ; termptr; termptr = termptr->nextpin ){ x = termptr->txpos[1] + ptr->cxcenter; if( flag == 2 && x != termptr->xpos ) { printf("pad x error\n"); } termptr->xpos = termptr->txpos[1] + ptr->cxcenter; y = termptr->typos[1] + ptr->cycenter; if( flag == 2 && y != termptr->ypos ) { printf("pad y error\n"); } termptr->ypos = termptr->typos[1] + ptr->cycenter; termptr->newx = 0 ; termptr->newy = 0 ; } } k = numcellsG + numtermsG + actual_feed_thru_cells_addedG ; for( cell = lastpadG + 1 ; cell <= k ; cell++ ) { ptr = carrayG[ cell ] ; corient = ptr->corient ; for( termptr = ptr->pins ; termptr; termptr = termptr->nextpin ){ x = termptr->txpos[ corient/2 ] + ptr->cxcenter; if( flag == 2 && x != termptr->xpos ) { printf("feed %d x error\n", cell ); } termptr->xpos = termptr->txpos[ corient/2 ] + ptr->cxcenter; y = termptr->typos[ corient%2 ] + ptr->cycenter; if( flag == 2 && y != termptr->ypos ) { printf("feed %d y error\n", cell ); } termptr->ypos = termptr->typos[ corient%2 ] + ptr->cycenter; termptr->newx = 0 ; termptr->newy = 0 ; termptr->row = ptr->cblock ; } } cost = 0 ; xwire = 0 ; ywire = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[ net ] ; if(!(netptr = dimptr->pins)) { continue ; } dimptr->xmin = dimptr->xmax = netptr->xpos ; dimptr->ymin = dimptr->ymax = netptr->ypos ; dimptr->Lnum = dimptr->Rnum = 1 ; dimptr->Bnum = dimptr->Tnum = 1 ; netptr = netptr->next ; n = 1 ; for( ; netptr ; netptr = netptr->next ) { x = netptr->xpos ; y = netptr->ypos ; if( x < dimptr->xmin ) { dimptr->xmin = x ; dimptr->Lnum = 1 ; } else if( x == dimptr->xmin ) { dimptr->Lnum++ ; if( x == dimptr->xmax ) { dimptr->Rnum++ ; } } else if( x > dimptr->xmax ) { dimptr->xmax = x ; dimptr->Rnum = 1 ; } else if( x == dimptr->xmax ) { dimptr->Rnum++ ; } if( y < dimptr->ymin ) { dimptr->ymin = y ; dimptr->Bnum = 1 ; } else if( y == dimptr->ymin ) { dimptr->Bnum++ ; if( y == dimptr->ymax ) { dimptr->Tnum++ ; } } else if( y > dimptr->ymax ) { dimptr->ymax = y ; dimptr->Tnum = 1 ; } else if( y == dimptr->ymax ) { dimptr->Tnum++ ; } n++ ; } dimptr->numpins = n ; xwire += dimptr->xmax - dimptr->xmin ; ywire += dimptr->ymax - dimptr->ymin ; cost += dimptr->halfPx = dimptr->newhalfPx = dimptr->xmax - dimptr->xmin ; dimptr->halfPy = dimptr->newhalfPy = dimptr->ymax - dimptr->ymin ; cost = cost + (INT)( vertical_wire_weightG * (DOUBLE) dimptr->halfPy ) ; } funccostG = cost ; /* ************* now calculate the timing penalty ************** */ timingcostG = 0 ; for( pathcount = 1 ; pathcount <= numpathsG ; pathcount++ ) { path = patharrayG[pathcount] ; length = 0 ; ASSERTNCONT( path, "findcost", "pointer to path is NULL" ) ; /* for all nets k of a path i */ /* ----------------------------------------------------------------- For all nets k of a path i: We use the minimum strength driver for each net to calculate the lower bound on the length and the maximum strength driver for the upper bound on the length. The user must take false paths into account when specifying the driver strengths. ------------------------------------------------------------------ */ for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ length = length + (INT) (horizontal_path_weightG * (DOUBLE) dimptr->halfPx) ; length = length + (INT) (vertical_path_weightG * (DOUBLE) dimptr->halfPy) ; } /* save result */ path->path_len = path->new_path_len = length ; /* calculate penalty */ /* no penalty if within target window */ /* lowerbound <= length <= upperbound */ if( length > path->upper_bound ){ timingcostG += length - path->upper_bound ; } else if( length < path->lower_bound ){ timingcostG += path->lower_bound - length ; } } fprintf(fpoG,"Total Wire Length - X-Component:%d\n", xwire ) ; fprintf(fpoG,"Total Wire Length - Y-Component:%d\n", ywire ) ; fprintf(fpoG,"Time Penalty:%d\n", timingcostG ) ; fflush(fpoG); for( block = 1 ; block <= numRowsG ; block++ ) { last_cell = pairArrayG[block][0] ; for( i = 1 ; i <= last_cell ; i++ ) { cellptr = carrayG[ pairArrayG[block][i] ] ; tileptr = cellptr->tileptr ; blklen[block] += tileptr->right - tileptr->left ; } } if( exact_feedsG ) { for( i = 1 ; i <= numRowsG ; i++ ) { blklen[i] += fdcel_addedG[i] * fdWidthG ; } exact_feedsG = 0 ; } bigblkx = 0 ; largest_delta_row_lenG = -1000000 ; if( !no_row_lengthsG ) { if( first_passS ) { for( i = 1 ; i <= numRowsG ; i++ ) { tmp = feeds_in_rowG[i] * fdWidthG ; if( tmp > barrayG[i]->orig_desire ) { blklen[i] += barrayG[i]->orig_desire ; } else { blklen[i] += tmp ; } total_penalty = 0 ; } } fprintf(fpoG,"BLOCK TOTAL CELL LENGTHS OVER/UNDER TARGET DESIRE\n"); for( i = 1 ; i <= numRowsG ; i++ ) { if( blklen[i] > blklen[ bigblkx ] ) { bigblkx = i ; } delta_row_len = blklen[i] - barrayG[i]->desire ; if( delta_row_len > largest_delta_row_lenG ) { largest_delta_row_lenG = delta_row_len ; } if( first_passS ) { total_penalty += ABS( delta_row_len ) ; } fprintf( fpoG, "%5d %18d %17d %9d\n", i, blklen[i] , delta_row_len , barrayG[i]->desire ); } fprintf( fpoG, "\nLONGEST Block is:%d Its length is:%d\n", bigblkx , blklen[ bigblkx ] ) ; if( first_passS ) { fprintf( fpoG,"total penalty is %d\n", total_penalty ) ; } first_passS = FALSE ; } Ysafe_free( blklen ) ; return ; } even_the_rows(flag,even_the_rows_max) INT flag ; BOOL even_the_rows_max ; { INT cell1 , cell2 , cell3 , cell4 , cell5 , cell6 ; INT long_row , short_row , row , bound , j , i , desire ; INT select , cost , num_trys, index, shift ; unsigned bit_class ; row_lengthS = (INT *) Ysafe_calloc( (1+numRowsG), sizeof(INT) ) ; for( row = 1 ; row <= numRowsG ; row++ ) { bound = 0 ; j = pairArrayG[row][0] ; for( i = 1 ; i <= j ; i++ ) { bound += carrayG[ pairArrayG[row][i] ]->clength ; } if( flag ) { bound += fdcel_addedG[row] * fdWidthG ; } desire = barrayG[row]->desire ; row_lengthS[row] = bound - desire ; } num_trys = 0 ; while( 1 ) { if( even_the_rows_max ){ determine_unequal_rows( &short_row, &long_row ) ; } else { determine_unequal_rows( &short_row, &long_row ) ; short_row = find_shortest_row( long_row ) ; } if( pairArrayG[long_row][0] == 1 ) { continue ; } /* long_row = find_longest_row() ; */ /* if( long_row == 0 ) { break ; } */ find_last_6_moveable_cells( long_row, &cell1 , &cell2 , &cell3 , &cell4 , &cell5 , &cell6 ) ; select = 0 ; if( cell1 > 0 ) { cost = row_cost(long_row, short_row, carrayG[cell1]->clength); if( cost < 0 ) { select = cell1 ; if( carrayG[cell1]->cclass > 0 ) { bit_class = 1 ; index = (barrayG[short_row]->bclass - 1) / 32 ; shift = barrayG[short_row]->bclass - 32 * index ; bit_class <<= (shift - 1) ; if( bit_class & carrayG[cell1]->cbclass[index] ) { /* a move to this row is allowed */ } else { select = 0 ; } } } } if( select == 0 && cell2 > 0 ) { cost = row_cost(long_row , short_row , carrayG[cell2]->clength) ; if( cost < 0 ) { select = cell2 ; if( carrayG[cell2]->cclass > 0 ) { bit_class = 1 ; index = (barrayG[short_row]->bclass - 1) / 32 ; shift = barrayG[short_row]->bclass - 32 * index ; bit_class <<= (shift - 1) ; if( bit_class & carrayG[cell2]->cbclass[index] ) { /* a move to this row is allowed */ } else { select = 0 ; } } } } if( select == 0 && cell3 > 0 ) { cost = row_cost(long_row , short_row , carrayG[cell3]->clength) ; if( cost < 0 ) { select = cell3 ; if( carrayG[cell3]->cclass > 0 ) { bit_class = 1 ; index = (barrayG[short_row]->bclass - 1) / 32 ; shift = barrayG[short_row]->bclass - 32 * index ; bit_class <<= (shift - 1) ; if( bit_class & carrayG[cell3]->cbclass[index] ) { /* a move to this row is allowed */ } else { select = 0 ; } } } } if( select == 0 && cell4 > 0 ) { cost = row_cost(long_row , short_row , carrayG[cell4]->clength) ; if( cost < 0 ) { select = cell4 ; if( carrayG[cell4]->cclass > 0 ) { bit_class = 1 ; index = (barrayG[short_row]->bclass - 1) / 32 ; shift = barrayG[short_row]->bclass - 32 * index ; bit_class <<= (shift - 1) ; if( bit_class & carrayG[cell4]->cbclass[index] ) { /* a move to this row is allowed */ } else { select = 0 ; } } } } if( select == 0 && cell5 > 0 ) { cost = row_cost(long_row , short_row , carrayG[cell5]->clength) ; if( cost < 0 ) { select = cell5 ; if( carrayG[cell5]->cclass > 0 ) { bit_class = 1 ; index = (barrayG[short_row]->bclass - 1) / 32 ; shift = barrayG[short_row]->bclass - 32 * index ; bit_class <<= (shift - 1) ; if( bit_class & carrayG[cell5]->cbclass[index] ) { /* a move to this row is allowed */ } else { select = 0 ; } } } } if( select == 0 && cell6 > 0 ) { cost = row_cost(long_row , short_row , carrayG[cell6]->clength) ; if( cost < 0 ) { select = cell6 ; if( carrayG[cell6]->cclass > 0 ) { bit_class = 1 ; index = (barrayG[short_row]->bclass - 1) / 32 ; shift = barrayG[short_row]->bclass - 32 * index ; bit_class <<= (shift - 1) ; if( bit_class & carrayG[cell6]->cbclass[index] ) { /* a move to this row is allowed */ } else { select = 0 ; } } } } if( select == 0 ) { if( ++num_trys > 2 * numRowsG ) { break ; } continue ; } num_trys = 0 ; /* fprintf(fpoG,"cell:%d moved from row:%d to row:%d\n", select, long_row , short_row ) ; fflush(fpoG) ; */ row_lengthS[ long_row ] -= carrayG[select]->clength ; row_lengthS[ short_row ] += carrayG[select]->clength ; pairArrayG[ short_row ][ ++pairArrayG[short_row][0] ] = select ; for( i = 1 ; i <= pairArrayG[long_row][0] ; i++ ) { if( pairArrayG[long_row][i] == select ) { for( i++ ; i <= pairArrayG[long_row][0] ; i++ ) { pairArrayG[long_row][i-1] = pairArrayG[long_row][i] ; } pairArrayG[long_row][0]-- ; break ; } } carrayG[select]->cblock = short_row ; carrayG[select]->cycenter = barrayG[short_row]->bycenter ; if( barrayG[short_row]->borient != barrayG[long_row]->borient ) { if( carrayG[select]->corient == 0 || carrayG[select]->corient == 2 ) { if( carrayG[select]->corient == 0 ) { carrayG[select]->corient = 1 ; } else { carrayG[select]->corient = 3 ; } } else { /* its 1 or 3 */ if( carrayG[select]->corient == 1 ) { carrayG[select]->corient = 0 ; } else { carrayG[select]->corient = 2 ; } } } } Ysafe_free( row_lengthS ) ; return ; } gate_arrayG_even_the_rows(flag) INT flag ; { CBOXPTR cellptr , cellptr1 , cellptr2 , cellptr3 , cellptr4 ; INT shortest , *set , i , row , tmp , w1 , w2 , w3 , w4 , error ; INT width1, width2, width3, width4, desire, mark, bound, new_bound ; INT gap , j , k , l , m, shift, index ; unsigned bit_class ; if( numRowsG <= 6 ) { return ; } set = (INT *) Ysafe_malloc( (1 + numcellsG) * sizeof( INT ) ) ; set[0] = 0 ; shortest = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { bound = 0 ; j = pairArrayG[row][0] ; for( i = 1 ; i <= j ; i++ ) { bound += carrayG[ pairArrayG[row][i] ]->clength ; } if( flag ) { bound += fdcel_addedG[row] * fdWidthG ; } desire = barrayG[row]->desire ; if( desire - bound > shortest ) { shortest = desire - bound ; } } for( row = 1 ; row <= numRowsG ; row++ ) { bound = 0 ; j = pairArrayG[row][0] ; for( i = 1 ; i <= j ; i++ ) { bound += carrayG[ pairArrayG[row][i] ]->clength ; } if( flag ) { bound += fdcel_addedG[row] * fdWidthG ; } desire = barrayG[row]->desire ; gap = desire - bound ; while( gap < shortest ) { i = pairArrayG[row][0] + 1 ; do { if( --i > 0 ) { cellptr1 = carrayG[ pairArrayG[row][i] ] ; } } while( i > 0 && cellptr1->cclass < 0 ) ; if( i == 0 ) { break ; } j = i ; do { if( --j > 0 ) { cellptr2 = carrayG[ pairArrayG[row][j] ] ; } } while( j > 0 && cellptr2->cclass < 0 ) ; if( j == 0 ) { break ; } k = j ; do { if( --k > 0 ) { cellptr3 = carrayG[ pairArrayG[row][k] ] ; } } while( k > 0 && cellptr3->cclass < 0 ) ; if( k == 0 ) { break ; } l = k ; do { if( --l > 0 ) { cellptr4 = carrayG[ pairArrayG[row][l] ] ; } } while( l > 0 && cellptr4->cclass < 0 ) ; if( l == 0 ) { break ; } w1 = cellptr1->clength ; w2 = cellptr2->clength ; w3 = cellptr3->clength ; w4 = cellptr4->clength ; if( w1 <= w2 && w1 <= w3 && w1 <= w4 ) { gap += w1 ; set[ ++set[0] ] = pairArrayG[row][i] ; for( m = i + 1 ; m <= pairArrayG[row][0] ; m++ ) { pairArrayG[row][m-1] = pairArrayG[row][m] ; } pairArrayG[row][0]-- ; } else if( w2 <= w1 && w2 <= w3 && w2 <= w4 ) { gap += w2 ; set[ ++set[0] ] = pairArrayG[row][j] ; for( m = j + 1 ; m <= pairArrayG[row][0] ; m++ ) { pairArrayG[row][m-1] = pairArrayG[row][m] ; } pairArrayG[row][0]-- ; } else if( w3 <= w1 && w3 <= w2 && w3 <= w4 ) { gap += w3 ; set[ ++set[0] ] = pairArrayG[row][k] ; for( m = k + 1 ; m <= pairArrayG[row][0] ; m++ ) { pairArrayG[row][m-1] = pairArrayG[row][m] ; } pairArrayG[row][0]-- ; } else { gap += w4 ; set[ ++set[0] ] = pairArrayG[row][l] ; for( m = l + 1 ; m <= pairArrayG[row][0] ; m++ ) { pairArrayG[row][m-1] = pairArrayG[row][m] ; } pairArrayG[row][0]-- ; } } } /* for( i = 1 ; i <= set[0] ; i++ ) { printf("cell: %d length: %d\n", set[i], carrayG[set[i]]->clength); } */ mark = 0 ; error = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { bound = 0 ; for( i = 1 ; i <= pairArrayG[row][0] ; i++ ) { bound += carrayG[ pairArrayG[row][i] ]->clength ; } if( flag ) { bound += fdcel_addedG[row] * fdWidthG ; } desire = barrayG[row]->desire ; /* printf("row: %d bound: %d desire: %d\n", row, bound, desire); */ while( 1 ) { if( mark+1 <= set[0] ) { width1 = carrayG[ set[mark+1] ]->clength ; } else { break ; } if( mark+2 <= set[0] ) { width2 = carrayG[ set[mark+2] ]->clength ; } else { width2 = 10000000 ; } if( mark+3 <= set[0] ) { width3 = carrayG[ set[mark+3] ]->clength ; } else { width3 = 10000000 ; } if( mark+4 <= set[0] ) { width4 = carrayG[ set[mark+4] ]->clength ; } else { width4 = 10000000 ; } w1 = ABS( bound + width1 + error - desire ) ; w2 = ABS( bound + width2 + error - desire ) ; w3 = ABS( bound + width3 + error - desire ) ; w4 = ABS( bound + width4 + error - desire ) ; if( w1 <= w2 && w1 <= w3 && w1 <= w4 ){ new_bound = bound + width1 ; } else if( w2 <= w1 && w2 <= w3 && w2 <= w4 ) { tmp = set[mark+1] ; set[mark+1] = set[mark+2] ; set[mark+2] = tmp ; new_bound = bound + width2 ; } else if( w3 <= w1 && w3 <= w2 && w3 <= w4 ) { tmp = set[mark+1] ; set[mark+1] = set[mark+3] ; set[mark+3] = tmp ; new_bound = bound + width3 ; } else { tmp = set[mark+1] ; set[mark+1] = set[mark+4] ; set[mark+4] = tmp ; new_bound = bound + width4 ; } if( ABS(new_bound + error - desire) <= ABS(bound + error - desire) ) { bit_class = 1 ; index = (barrayG[row]->bclass - 1) / 32 ; shift = barrayG[row]->bclass - 32 * index ; bit_class <<= (shift - 1) ; if( row == carrayG[set[mark+1]]->cblock || carrayG[set[mark+1]]->cclass == 0 || bit_class & carrayG[set[mark+1]]->cbclass[index]) { /* this cell can go into "row" */ bound = new_bound ; pairArrayG[row][ ++pairArrayG[row][0] ] = set[ ++mark ] ; cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; if( barrayG[row]->borient != barrayG[cellptr->cblock]->borient ) { if( cellptr->corient == 0 || cellptr->corient == 2 ) { if( cellptr->corient == 0 ) { cellptr->corient = 1 ; } else { cellptr->corient = 3 ; } } else { /* its 1 or 3 */ if( cellptr->corient == 1 ) { cellptr->corient = 0 ; } else { cellptr->corient = 2 ; } } } cellptr->cblock = row ; cellptr->cycenter = barrayG[row]->bycenter ; } else { mark++ ; } } else { error += bound - desire ; break ; } } } Ysafe_free( set ) ; return ; } row_cost( long_row , short_row , width ) INT long_row , short_row , width ; { INT cost ; cost = row_lengthS[short_row] + width - row_lengthS[long_row] ; return( cost ) ; } find_last_6_moveable_cells( row, cell1, cell2, cell3, cell4, cell5, cell6) INT row ; INT *cell1 , *cell2 , *cell3 , *cell4 , *cell5 , *cell6 ; { INT i ; CBOXPTR cellptr ; i = pairArrayG[row][0] + 1 ; do { if( --i > 0 ) { cellptr = carrayG[ pairArrayG[row][i] ] ; } } while( i > 0 && (cellptr->paths != NULL || cellptr->cclass < 0 )) ; if( i <= 0 ) { *cell1 = 0 ; *cell2 = 0 ; *cell3 = 0 ; *cell4 = 0 ; *cell5 = 0 ; *cell6 = 0 ; return ; } else { *cell1 = pairArrayG[row][i] ; } do { if( --i > 0 ) { cellptr = carrayG[ pairArrayG[row][i] ] ; } } while( i > 0 && (cellptr->paths != NULL || cellptr->cclass < 0 )) ; if( i <= 0 ) { *cell2 = 0 ; *cell3 = 0 ; *cell4 = 0 ; *cell5 = 0 ; *cell6 = 0 ; return ; } else { *cell2 = pairArrayG[row][i] ; } do { if( --i > 0 ) { cellptr = carrayG[ pairArrayG[row][i] ] ; } } while( i > 0 && (cellptr->paths != NULL || cellptr->cclass < 0 )) ; if( i <= 0 ) { *cell3 = 0 ; *cell4 = 0 ; *cell5 = 0 ; *cell6 = 0 ; return ; } else { *cell3 = pairArrayG[row][i] ; } do { if( --i > 0 ) { cellptr = carrayG[ pairArrayG[row][i] ] ; } } while( i > 0 && (cellptr->paths != NULL || cellptr->cclass < 0 )) ; if( i <= 0 ) { *cell4 = 0 ; *cell5 = 0 ; *cell6 = 0 ; return ; } else { *cell4 = pairArrayG[row][i] ; } do { if( --i > 0 ) { cellptr = carrayG[ pairArrayG[row][i] ] ; } } while( i > 0 && (cellptr->paths != NULL || cellptr->cclass < 0 )) ; if( i <= 0 ) { *cell5 = 0 ; *cell6 = 0 ; return ; } else { *cell5 = pairArrayG[row][i] ; } do { if( --i > 0 ) { cellptr = carrayG[ pairArrayG[row][i] ] ; } } while( i > 0 && (cellptr->paths != NULL || cellptr->cclass < 0 )) ; if( i <= 0 ) { *cell6 = 0 ; return ; } else { *cell6 = pairArrayG[row][i] ; } return ; } find_longest_row() { INT row ; INT num_trys ; num_trys = 0 ; do { row = PICK_INT( 1 , numRowsG ) ; } while( row_lengthS[row] <= 0 && ++num_trys <= 2*numRowsG ) ; return( row ) ; } /* find_shortest_row( long_row ) INT long_row ; { INT row ; if( long_row + 1 <= numRowsG && long_row - 1 >= 1 ) { if( row_lengthS[long_row + 1] <= row_lengthS[long_row - 1] ) { row = long_row + 1 ; } else { row = long_row - 1 ; } } else if( long_row + 1 <= numRowsG ) { row = long_row + 1 ; } else { row = long_row - 1 ; } return(row) ; } */ find_shortest_row( long_row ) INT long_row ; { INT row ; INT short_row_length ; INT slack , short_row , min_row , max_row ; if( long_row > 3 ) { min_row = long_row - 3 ; } else { min_row = 1 ; } if( long_row <= numRowsG - 3 ) { max_row = long_row + 3 ; } else { max_row = numRowsG ; } short_row_length = INT_MAX ; for( row = min_row ; row <= max_row ; row ++ ){ slack = row_lengthS[row] ; if( slack < short_row_length ){ short_row = row ; short_row_length = slack ; } } return(short_row) ; } determine_unequal_rows( short_row, long_row ) INT *short_row, *long_row ; { INT row ; INT short_row_length, long_row_length ; INT slack ; short_row_length = INT_MAX ; long_row_length = INT_MIN ; for( row = 1 ; row <= numRowsG ; row ++ ){ slack = row_lengthS[row] ; if( slack > long_row_length ){ *long_row = row ; long_row_length = slack ; } if( slack < short_row_length ){ *short_row = row ; short_row_length = slack ; } } } /* end determine_unequal_rows() */ even_the_rows_2( iteration ) INT iteration ; { CBOXPTR cellptr , cellptr1 , cellptr2 , cellptr3 , cellptr4 ; INT shortest , *set , i , row , tmp , w1 , w2 , w3 , w4 , error ; INT width1, width2, width3, width4, desire, mark, bound, new_bound ; INT gap , j , k , l , m, shift, index ; unsigned bit_class ; if( numRowsG <= 1 || numcellsG <= 6 ) { return ; } set = (INT *) Ysafe_malloc( (1 + numcellsG) * sizeof( INT ) ) ; set[0] = 0 ; shortest = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { bound = 0 ; j = pairArrayG[row][0] ; for( i = 1 ; i <= j ; i++ ) { bound += carrayG[ pairArrayG[row][i] ]->clength ; } desire = barrayG[row]->desire ; if( desire - bound > shortest ) { shortest = desire - bound ; } } shortest += iteration * (INT) mean_widthG ; for( row = 1 ; row <= numRowsG ; row++ ) { bound = 0 ; j = pairArrayG[row][0] ; for( i = 1 ; i <= j ; i++ ) { bound += carrayG[ pairArrayG[row][i] ]->clength ; } desire = barrayG[row]->desire ; gap = desire - bound ; while( gap < shortest ) { i = pairArrayG[row][0] + 1 ; do { if( --i > 0 ) { cellptr1 = carrayG[ pairArrayG[row][i] ] ; } } while( i > 0 && cellptr1->cclass < 0 ) ; if( i == 0 ) { break ; } j = i ; do { if( --j > 0 ) { cellptr2 = carrayG[ pairArrayG[row][j] ] ; } } while( j > 0 && cellptr2->cclass < 0 ) ; if( j == 0 ) { break ; } k = j ; do { if( --k > 0 ) { cellptr3 = carrayG[ pairArrayG[row][k] ] ; } } while( k > 0 && cellptr3->cclass < 0 ) ; if( k == 0 ) { break ; } l = k ; do { if( --l > 0 ) { cellptr4 = carrayG[ pairArrayG[row][l] ] ; } } while( l > 0 && cellptr4->cclass < 0 ) ; if( l == 0 ) { break ; } w1 = cellptr1->clength ; w2 = cellptr2->clength ; w3 = cellptr3->clength ; w4 = cellptr4->clength ; if( w1 <= w2 && w1 <= w3 && w1 <= w4 ) { gap += w1 ; set[ ++set[0] ] = pairArrayG[row][i] ; for( m = i + 1 ; m <= pairArrayG[row][0] ; m++ ) { pairArrayG[row][m-1] = pairArrayG[row][m] ; } pairArrayG[row][0]-- ; } else if( w2 <= w1 && w2 <= w3 && w2 <= w4 ) { gap += w2 ; set[ ++set[0] ] = pairArrayG[row][j] ; for( m = j + 1 ; m <= pairArrayG[row][0] ; m++ ) { pairArrayG[row][m-1] = pairArrayG[row][m] ; } pairArrayG[row][0]-- ; } else if( w3 <= w1 && w3 <= w2 && w3 <= w4 ) { gap += w3 ; set[ ++set[0] ] = pairArrayG[row][k] ; for( m = k + 1 ; m <= pairArrayG[row][0] ; m++ ) { pairArrayG[row][m-1] = pairArrayG[row][m] ; } pairArrayG[row][0]-- ; } else { gap += w4 ; set[ ++set[0] ] = pairArrayG[row][l] ; for( m = l + 1 ; m <= pairArrayG[row][0] ; m++ ) { pairArrayG[row][m-1] = pairArrayG[row][m] ; } pairArrayG[row][0]-- ; } } } /* for( row = 1 ; row <= numRowsG ; row++ ) { gap = 0 ; i = pairArrayG[row][0] + 1 ; while( gap < shortest ) { do { if( --i > 0 ) { cellptr1 = carrayG[ pairArrayG[row][i] ] ; } } while( i > 0 && strcmp("GATE_ARRAY_SPACER", cellptr1->cname) != 0 ) ; if( i == 0 ) { break ; } w1 = cellptr1->clength ; gap += w1 ; set[ ++set[0] ] = pairArrayG[row][i] ; for( m = i + 1 ; m <= pairArrayG[row][0] ; m++ ) { pairArrayG[row][m-1] = pairArrayG[row][m] ; } pairArrayG[row][0]-- ; } } */ mark = 0 ; error = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { bound = 0 ; for( i = 1 ; i <= pairArrayG[row][0] ; i++ ) { bound += carrayG[ pairArrayG[row][i] ]->clength ; } desire = barrayG[row]->desire ; while( 1 ) { if( mark+1 <= set[0] ) { width1 = carrayG[ set[mark+1] ]->clength ; } else { break ; } if( mark+2 <= set[0] ) { width2 = carrayG[ set[mark+2] ]->clength ; } else { width2 = 10000000 ; } if( mark+3 <= set[0] ) { width3 = carrayG[ set[mark+3] ]->clength ; } else { width3 = 10000000 ; } if( mark+4 <= set[0] ) { width4 = carrayG[ set[mark+4] ]->clength ; } else { width4 = 10000000 ; } w1 = ABS( bound + width1 + error - desire ) ; w2 = ABS( bound + width2 + error - desire ) ; w3 = ABS( bound + width3 + error - desire ) ; w4 = ABS( bound + width4 + error - desire ) ; if( w1 <= w2 && w1 <= w3 && w1 <= w4 ){ new_bound = bound + width1 ; } else if( w2 <= w1 && w2 <= w3 && w2 <= w4 ) { tmp = set[mark+1] ; set[mark+1] = set[mark+2] ; set[mark+2] = tmp ; new_bound = bound + width2 ; } else if( w3 <= w1 && w3 <= w2 && w3 <= w4 ) { tmp = set[mark+1] ; set[mark+1] = set[mark+3] ; set[mark+3] = tmp ; new_bound = bound + width3 ; } else { tmp = set[mark+1] ; set[mark+1] = set[mark+4] ; set[mark+4] = tmp ; new_bound = bound + width4 ; } if( ABS(new_bound + error - desire) <= ABS(bound + error - desire) ) { bit_class = 1 ; index = (barrayG[row]->bclass - 1) / 32 ; shift = barrayG[row]->bclass - 32 * index ; bit_class <<= (shift - 1) ; if( row == carrayG[set[mark+1]]->cblock || carrayG[set[mark+1]]->cclass == 0 || bit_class & carrayG[set[mark+1]]->cbclass[index]) { /* this cell can go into "row" */ bound = new_bound ; pairArrayG[row][ ++pairArrayG[row][0] ] = set[ ++mark ] ; cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; if( barrayG[row]->borient != barrayG[cellptr->cblock]->borient ) { if( cellptr->corient == 0 || cellptr->corient == 2 ) { if( cellptr->corient == 0 ) { cellptr->corient = 1 ; } else { cellptr->corient = 3 ; } } else { /* its 1 or 3 */ if( cellptr->corient == 1 ) { cellptr->corient = 0 ; } else { cellptr->corient = 2 ; } } } cellptr->cblock = row ; cellptr->cycenter = barrayG[row]->bycenter ; } else { mark++ ; } } else { error += bound - desire ; break ; } } } Ysafe_free( set ) ; return ; } check_row_length() { INT longest , row , shortest ; INT desire , bound , i , j , long_row ; if( numRowsG <= 1 || numcellsG <= 6 ) { return(0) ; } longest = -1 ; long_row = 1 ; shortest = 10000000 ; for( row = 1 ; row <= numRowsG ; row++ ) { bound = 0 ; j = pairArrayG[row][0] ; for( i = 1 ; i <= j ; i++ ) { bound += carrayG[ pairArrayG[row][i] ]->clength ; } desire = barrayG[row]->desire ; if( bound - desire > longest ) { longest = bound - desire ; long_row = row ; } if( bound - desire < shortest ) { shortest = bound - desire ; } } if( gate_arrayG ) { if( longest != shortest ) { return(1) ; } else { return(0) ; } } else { if( (DOUBLE) longest / (DOUBLE)(barrayG[long_row]->desire) > 0.01 && longest >= (INT) mean_widthG ) { return(1) ; } else { return(0) ; } } } findunlap2() { CBOXPTR cellptr ; TIBOXPTR tileptr ; INT last_cell ; INT block , i , bigblkx , *blklen , delta_row_len ; blklen = (INT *) Ysafe_malloc( (numRowsG + 1) * sizeof( INT ) ) ; for( i = 0 ; i <= numRowsG ; i++ ) { blklen[i] = 0 ; } for( block = 1 ; block <= numRowsG ; block++ ) { last_cell = pairArrayG[block][0] ; for( i = 1 ; i <= last_cell ; i++ ) { cellptr = carrayG[ pairArrayG[block][i] ] ; tileptr = cellptr->tileptr ; blklen[block] += tileptr->right - tileptr->left ; } } bigblkx = 0 ; largest_delta_row_lenG = -1000000 ; fprintf(fpoG,"BLOCK TOTAL CELL LENGTHS OVER/UNDER TARGET\n"); for( i = 1 ; i <= numRowsG ; i++ ) { if( blklen[i] > blklen[ bigblkx ] ) { bigblkx = i ; } delta_row_len = blklen[i] - barrayG[i]->desire ; if( delta_row_len > largest_delta_row_lenG ) { largest_delta_row_lenG = delta_row_len ; } fprintf( fpoG, "%5d %18d %17d\n", i, blklen[i] , delta_row_len ); } fprintf( fpoG, "\nLONGEST Block is:%d Its length is:%d\n", bigblkx , blklen[ bigblkx ] ) ; Ysafe_free( blklen ) ; return ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/gateswap.c000066400000000000000000000223241305746555600215150ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * Copyright (C) 2015 Tim Edwards * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: gateswap.c DESCRIPTION:evaluates proposed gate swaps CONTENTS: gateswap() DATE: May 19, 1989 REVISIONS: Apr 1, 1990 - fixed gateswap routine by changing sortpins for new data structure. Also added missing swap of txpos fields. Needed to pass the beginning of the cell pin listx instead of pina and pinb. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) gateswap.c (Yale) version 4.6 2/23/92" ; #endif #endif #include #include "ucxxglb.h" #include "parser.h" #include #include "readnets.h" gate_swap( between_two_cells, sgidxa, sgidxb ) INT between_two_cells ; INT sgidxa, sgidxb ; { CBOXPTR cell1ptr , cell2ptr ; PINLIST *term1 , *term2 , *term_list1 , *term_list2 , *term ; PINBOXPTR pin1 , pin2 , pina, pinb ; char *tmp_char_ptr ; struct equiv_box *tmp_eqptr ; INT cost , cell1 , cell2 , length ; INT tmp , i, swap_group ; INT truth , count ; INT pg1 , pg2 ; /* pg stands for 'pin group' */ INT newtimepenal ; SGLISTPTR cell1sgl, cell2sgl; term_list1 = NULL; term_list2 = NULL; if( between_two_cells ) { cell1 = aG ; cell2 = bG ; cell1ptr = carrayG[cell1] ; cell2ptr = carrayG[cell2] ; cell1sgl = cell1ptr->swapgroups + sgidxa; cell2sgl = cell2ptr->swapgroups + sgidxb; pg1 = XPICK_INT( 1 , cell1sgl->num_pin_group , 0 ) ; pg2 = XPICK_INT( 1 , cell2sgl->num_pin_group , 0 ) ; swap_group = cell1sgl->swap_group; term_list1 = (PINLISTPTR) Yhash_search( swap_group_listG[swap_group].pin_grp_hash, cell1ptr->cname, NULL, FIND ); while (pg1-- > 1) { if (term_list1->next_grp == NULL) break; term_list1 = term_list1->next_grp; } term_list2 = (PINLISTPTR) Yhash_search( swap_group_listG[swap_group].pin_grp_hash, cell2ptr->cname, NULL, FIND ); while (pg2-- > 1) { if (term_list2->next_grp == NULL) break; term_list2 = term_list2->next_grp; } } else { cell1 = aG ; cell2 = aG ; cell1ptr = carrayG[cell1] ; cell1sgl = cell1ptr->swapgroups + sgidxa; swap_group = cell1sgl->swap_group ; pg1 = XPICK_INT( 1 , cell1sgl->num_pin_group , 0 ) ; pg2 = XPICK_INT( 1 , cell1sgl->num_pin_group , pg1 ) ; if( pg1 > pg2 ) { /* we want to ensure that pg1 < pg2 */ i = pg1 ; pg1 = pg2 ; pg2 = i ; } term = (PINLISTPTR) Yhash_search( swap_group_listG[swap_group].pin_grp_hash, cell1ptr->cname, NULL, FIND ); term_list1 = term; while (pg1-- > 1) { term_list1 = term_list1->next_grp; } term_list2 = term; while (pg2-- > 1) { term_list2 = term_list2->next_grp; } } for( term1 = term_list1 ; term1 != NULL ; term1 = term1->next ) { pin1 = term1->swap_pin ; netarrayG[ pin1->net ]->dflag = 1 ; pin1->flag = 1 ; length = strcspn( pin1->pinname , "/" ) ; for( term2 = term_list2 ; term2 != NULL ; term2 = term2->next ) { pin2 = term2->swap_pin ; if( length == strcspn( pin2->pinname , "/" ) ) { if( strncmp( pin1->pinname , pin2->pinname , length ) == 0 ) { /* then this is the pair of pins to swap */ netarrayG[ pin2->net ]->dflag = 1 ; pin2->flag = 1 ; pin1->newx = pin2->xpos ; pin1->newy = pin2->ypos ; pin2->newx = pin1->xpos ; pin2->newy = pin1->ypos ; } } } } ASSERT( cell1 == term_list1->swap_pin->cell, NULL, "trouble\n" ) ; pina = carrayG[cell1]->pins ; ASSERT( cell2 == term_list2->swap_pin->cell, NULL, "trouble\n" ) ; pinb = carrayG[cell2]->pins ; cost = funccostG ; clear_net_set() ; /* reset set to mark nets that have ch'ged position */ /* dimbox routines mark the nets that have changed */ if( cell1 != cell2 ) { init_dbox_pos_swap( pina ) ; init_dbox_pos_swap( pinb ) ; new_dbox2( pina , pinb , &cost ) ; } else { init_dbox_pos_swap( pina ) ; new_dbox( pina , &cost ) ; } newtimepenal = timingcostG ; if( cell1 != cell2 ) { newtimepenal += calc_incr_time2( cell1, cell2 ) ; } else { newtimepenal += calc_incr_time( cell1 ) ; } ASSERT( dcalc_full_penalty(newtimepenal),NULL,"time problem") ; truth = acceptt( 2*(funccostG-cost), 2*(timingcostG-newtimepenal), 0 ) ; if( truth ) { for( term1 = term_list1 ; term1 != NULL ; term1 = term1->next ) { pin1 = term1->swap_pin ; length = strcspn( pin1->pinname , "/" ) ; for( term2 = term_list2; term2 != NULL ; term2 = term2->next ) { pin2 = term2->swap_pin ; if( length == strcspn( pin2->pinname , "/" ) ) { if( strncmp( pin1->pinname , pin2->pinname , length ) == 0 ) { /* this is the pair of pins which swapped */ term1->swap_pin = pin2 ; term2->swap_pin = pin1 ; tearrayG[ pin1->terminal ] = pin2 ; tearrayG[ pin2->terminal ] = pin1 ; tmp_eqptr = pin1->eqptr ; pin1->eqptr = pin2->eqptr ; pin2->eqptr = tmp_eqptr ; tmp_char_ptr = pin1->pinname ; pin1->pinname = pin2->pinname ; pin2->pinname = tmp_char_ptr ; tmp = pin1->terminal ; pin1->terminal = pin2->terminal ; pin2->terminal = tmp ; tmp = pin1->cell ; pin1->cell = pin2->cell ; pin2->cell = tmp ; tmp = pin1->pinloc ; pin1->pinloc = pin2->pinloc ; pin2->pinloc = tmp ; pin1->xpos = pin1->newx ; pin1->ypos = pin1->newy ; pin2->xpos = pin2->newx ; pin2->ypos = pin2->newy ; /* swap the cell relative pin positions */ tmp = pin1->txpos[0] ; pin1->txpos[0] = pin2->txpos[0] ; pin2->txpos[0] = tmp ; tmp = pin1->txpos[1] ; pin1->txpos[1] = pin2->txpos[1] ; pin2->txpos[1] = tmp ; tmp = pin1->typos[0] ; pin1->typos[0] = pin2->typos[0] ; pin2->typos[0] = tmp ; tmp = pin1->typos[1] ; pin1->typos[1] = pin2->typos[1] ; pin2->typos[1] = tmp ; } } } } if( cell1 != cell2 ) { sortpin2( cell1, cell2 ) ; /* must pass beginning of the list not pina and pinb */ dbox_pos_swap( carrayG[cell1]->pins ) ; dbox_pos_swap( carrayG[cell2]->pins ) ; update_time2() ; /* Now we have to put the paths on the correct cells since the cells have swapped some pins */ adjust_paths_on_cell( cell1 ) ; adjust_paths_on_cell( cell2 ) ; } else { sortpin1( cell1 ) ; dbox_pos_swap( pina ) ; update_time( cell1 ) ; } funccostG = cost ; timingcostG = newtimepenal ; return( 1 ) ; } else { return( 0 ) ; } } adjust_paths_on_cell( cell ) INT cell ; { INT net_number ; PSETPTR pathlist, enum_path_set() ; CBOXPTR ptr ; GLISTPTR path_ptr, tempPath ; DBOXPTR dimptr ; PINBOXPTR pinptr ; ptr = carrayG[cell] ; /* First, scrap all of the current path list */ tempPath = ptr->paths ; ptr->paths = NULL ; while( tempPath != NULL ) { path_ptr = tempPath ; tempPath = tempPath->next ; Ysafe_free( (GLISTPTR) path_ptr ) ; } clear_path_set() ; /* look for the UNIQUE paths that connects to this cell */ for(pinptr=ptr->pins;pinptr;pinptr=pinptr->nextpin){ net_number = pinptr->net ; /* now go to net array */ dimptr = netarrayG[net_number] ; /* look at all paths that use this net */ for( path_ptr=dimptr->paths;path_ptr;path_ptr=path_ptr->next){ add2path_set( path_ptr->p.path ) ; } } /* now add UNIQUE list of paths to this cell */ for( pathlist=enum_path_set(); pathlist; pathlist=pathlist->next){ if( tempPath = ptr->paths ){ path_ptr = ptr->paths = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; path_ptr->next = tempPath ; } else { /* start a new list */ path_ptr = ptr->paths = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; path_ptr->next = NULL ; } /* copy path to cell list of paths */ path_ptr->p.path = pathlist->path ; } return ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/globe.c000066400000000000000000001460301305746555600207730ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * Copyright (C) 2015 Tim Edwards * Copyright (C) 2015 Staf Verhaegen * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: globe.c DESCRIPTION:global routing routines. CONTENTS: globe() preFeedAssgn() free_static_in_globe() FeedAssgn( row ) INT row ; row_seg_intersect( ptr1 , ptr2 , segptr ) PINBOXPTR ptr1 , ptr2 ; SEGBOXPTR segptr ; copy_workerS_field( aptr, bptr ) FEED_SEG_PTR aptr, bptr ; assgn_impin( imptr , fsptr , row ) IPBOXPTR imptr ; FEED_SEG_PTR fsptr ; unequiv_pin_pre_processing() relax_padPins_pinloc() relax_unequiv_pinloc() check_unequiv_connectivity() DATE: Mar 27, 1989 REVISIONS: Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. Tue Jan 15 20:24:49 PST 1991 - added Carl's speedup to adding feeds and also fixed missing Ysafe_frees. Fri Jan 25 23:50:09 PST 1991 - now add extra memory if needed to worker and L_jog arrays. Tue Mar 12 17:10:47 CST 1991 - fixed DN10000 warnings. Thu Aug 22 22:29:28 CDT 1991 - Carl made changes for rigidly fixed cells. Wed Aug 28 14:37:40 EDT 1991 - Carl updated feed assignment code. Thu Sep 19 14:15:51 EDT 1991 - added equal width cell capability. Fixed initialization problem with rebuilding pins. Thu Nov 7 22:56:29 EST 1991 - added timing cost to cell swaps. Wed Dec 18 21:09:09 EST 1991 - handle special case of large number of feeds and small number of crossings. Tue May 12 22:23:31 EDT 1992 - fixed problem with orientation movement and added placement_improve switch. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) globe.c (Yale) version 4.24 5/12/92" ; #endif #endif #define GLOBE_VARS #include "standard.h" #include "groute.h" #include "main.h" #include "parser.h" #include "feeds.h" #include #include #include #include #define CARL_NEW #define PICK_INT(l,u) (((l)<(u)) ? ((RAND % ((u)-(l)+1))+(l)) : (l)) /* global variables */ BOOL connectFlagG ; /* external references */ extern BOOL rigidly_fixed_cellsG ; extern BOOL placement_improveG ; static LONG swap_cost( P1(BOOL perim_flag ) ) ; /* static variables */ static INT *wk_headS , max_feed_in_a_rowS ; static INT *L_jogS ; static FEED_SEG_PTR *workerS ; static INT wkS ; static LONG global_wire_lengthS ; static INT swap_limitS ; globe() { INT row , net , cost , last_cost , swaps , found , total_final_cost ; INT total_cost , total_final_global_wire , total_global_wire ; INT last_global_wire , total_reduction , index , i , j , k , check ; INT iterations, initial_time, last_index ; LONG initial_wire ; PINBOXPTR netptr , cnetptr ; int ok = 1; implicit_pins_usedG = 0 ; decide_boundary() ; link_imptr() ; preFeedAssgn() ; printf(" doing feed-through pins assignment\n" ) ; for( row = 1 ; row <= numRowsG ; row++ ) { FeedAssgn(row) ; } free_static_in_globe() ; printf(" building the net-tree now !\n" ) ; postFeedAssgn() ; #define CARL_NEW #ifdef CARL_NEW rebuild_nextpin() ; elim_unused_feedsSC() ; /* if( rigidly_fixed_cellsG ) { */ if( refine_fixed_placement() == 0 ) { ok = 0; goto out; } /* } */ fprintf(fpoG,"\nrow lengths after steiner trees:\n"); findunlap2() ; if( placement_improveG ){ iterations = 0 ; total_reduction = 0 ; j = 4 * numcellsG ; if( numcellsG <= 2000 ) { k = 3 ; } else if( numcellsG <= 4000 ) { k = 2 ; } else { k = 1 ; } rebuild_cell_paths() ; initial_wire = global_wire_lengthS = swap_cost( FALSE ) ; initial_time = timingcostG ; sprintf(YmsgG,"initial total global wire :\t%d\n", global_wire_lengthS); M( MSG, NULL, YmsgG ) ; sprintf(YmsgG,"initial total timing penalty:\t%d\n\n\n", timingcostG); M( MSG, NULL, YmsgG ) ; M( MSG, NULL, "\nSteiner cell swap and rotation optimization\n" ) ; swap_limitS = - (int)( (double) global_wire_lengthS * 0.00005 ) ; sprintf(YmsgG,"swap_limit:%d\n", swap_limitS ) ; M( MSG, NULL, YmsgG ) ; for( ; ; ) { swaps = 0 ; check = 0 ; for( i = 1 ; i <= j ; i++ ) { row = PICK_INT( 1 , numRowsG ) ; /* added by Carl 12/7/91 */ if( pairArrayG[row][0] <= 1 ) { check++ ; continue ; } /* added by Carl 12/7/91 */ last_index = pairArrayG[row][0] ; index = PICK_INT( 1 , last_index ) ; if( index < last_index ){ if( carrayG[pairArrayG[row][index]]->cclass < 0 || carrayG[pairArrayG[row][index+1]]->cclass < 0 ) { i-- ; if( ++check > j ) { break ; } else { continue ; } } swaps += improve_place_sequential( row , index ) ; } /* end if( index <... */ swaps += cell_rotate( row , index ) ; } /* end for( i = 1... */ iterations++ ; total_reduction += swaps ; if( iterations == 1 || iterations % 10 == 0 ) { sprintf(YmsgG,"reduction:\t%d\t\ttotal_red:%d\n", swaps , total_reduction ) ; M( MSG, NULL, YmsgG ) ; } if( swaps >= swap_limitS ) { if( --k == 0 ) { break ; } } } sprintf(YmsgG,"iterations :\t%d\n", iterations ) ; M( MSG, NULL, YmsgG ) ; sprintf(YmsgG,"final total global wire :\t%d\n", global_wire_lengthS ) ; M( MSG, NULL, YmsgG ) ; sprintf(YmsgG,"final total time penalty:\t%d\n", timingcostG ) ; M( MSG, NULL, YmsgG ) ; sprintf(YmsgG,"\nTotal global wire reduced by:\t%5.3f%%\n", 100.0 * (1.0 - (DOUBLE) global_wire_lengthS / (DOUBLE) initial_wire ) ) ; M( MSG, NULL, YmsgG ) ; if( initial_time ){ sprintf(YmsgG,"Total time penalty reduced by:\t%5.3f%%\n", 100.0 * (1.0 - (DOUBLE) timingcostG / (DOUBLE) initial_time ) ) ; M( MSG, NULL, YmsgG ) ; } M( MSG, NULL, "\nVERIFICATION\n" ) ; global_wire_lengthS = swap_cost( FALSE ) ; sprintf(YmsgG,"final total global wire :\t%d\n", global_wire_lengthS); M( MSG, NULL, YmsgG ) ; sprintf(YmsgG,"final total time penalty:\t%d\n\n\n", timingcostG); M( MSG, NULL, YmsgG ) ; } else { M( WARNMSG, "globe", "global routing placement improvement off\n" ) ; } postFeedAssgn_carl() ; /* end of added stuff */ #endif relax_padPins_pinloc() ; if( case_unequiv_pinG ) { relax_unequiv_pinloc() ; } switchable_or_not() ; printf(" set up the global routing grids\n" ) ; globroute() ; assgn_channel_to_seg() ; connectFlagG = TRUE ; printf(" removing redundant feed-through pins\n" ) ; for( net = 1 ; net <= numnetsG ; net++ ) { remove_overlap_segment( net ) ; remove_unnecessary_feed( net , 1 ) ; } if( connectFlagG ) { printf(" the connectivity of all the nets is verified\n" ) ; } else { printf(" the connectivity of some nets is lost\n" ) ; printf(" please contact with authors\n" ) ; } if( case_unequiv_pinG ) { if( check_unequiv_connectivity() ) { printf(" the usage of all unequivalent pins is legal\n" ); } else { printf(" illegal usage of some unequivalent pins\n" ) ; printf(" please contact with the authors\n" ) ; } } out: free_chan_seg() ; free_z_memory() ; return(ok) ; } globe_free_up() { netgraph_free_up(); } preFeedAssgn() { SEGBOXPTR segptr , nextptr ; INT i , net ; max_feed_in_a_rowS = 3 * TotRegPinsG / numRowsG ; wk_headS = (INT *)Ysafe_malloc( max_feed_in_a_rowS * sizeof(INT) ) ; L_jogS = (INT *)Ysafe_malloc( max_feed_in_a_rowS * sizeof(INT) ) ; workerS = (FEED_SEG_PTR *)Ysafe_malloc( ( max_feed_in_a_rowS + 1 ) * sizeof(FEED_SEG_PTR) ) ; for( i = 1 ; i <= max_feed_in_a_rowS ; i++ ) { workerS[i] = ( FEED_SEG_PTR )Ysafe_malloc( sizeof(FEED_SEG) ) ; } for( net = 1 ; net <= numnetsG ; net++ ) { segptr = netsegHeadG[net]->next ; if( segptr == NULL ) { continue ; } for( ; segptr ; segptr = nextptr ) { nextptr = segptr->next ; if( segptr->pin1ptr->row == segptr->pin2ptr->row && segptr->flag ) { segptr->prev->next = nextptr ; if( nextptr != NULL ) { nextptr->prev = segptr->prev ; } Ysafe_free( segptr ) ; } } } } free_static_in_globe() { INT i ; Ysafe_free( L_jogS ) ; for( i = 1 ; i <= max_feed_in_a_rowS ; i++ ) { Ysafe_free( workerS[i] ) ; } Ysafe_free( workerS ) ; Ysafe_free( wk_headS ) ; Ysafe_free( total_feed_in_the_rowG ) ; } #ifdef CARL_NEW FeedAssgn( row ) INT row ; { PINBOXPTR netptr , ptr1 , ptr2 ; SEGBOXPTR segptr , nextptr ; IPBOXPTR imptr , iptr , ipinptr[40] , i_imptr , f_imptr ; INT net , impcount , firstnode , spacing ; INT i , j , k , last_i , last_j ; INT min_i , min_x , x , jog_num ; INT comparenptr() ; /* added by Carl for the wild attempt to optimally align feeds */ INT **cost , *assign_to_track , feed , feed_xpos , track , track_xpos ; INT v_tracks , assigned_track , *assigned_to_track ; INT num_parts , bound , assign_iter ; INT i_bound , f_bound , num_feeds , start_feed_xpos , end_feed_xpos ; INT count , i_count , f_count ; INT req_remaining_fds , remaining_fds , tot_imp_fds , num_assigned ; wkS = 0 ; jog_num = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { for( netptr = steinerHeadG[net]->next ; netptr ; netptr = netptr->next ) { if( netptr->flag && netptr->row == row ) { row_seg_intersect( netptr , NULL , NULL ) ; } } for( segptr = netsegHeadG[net]->next ; segptr ; segptr = nextptr ) { nextptr = segptr->next ; ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; if( ptr1->row < row && ptr2->row > row ) { if( segptr->switchvalue == swL_down ) { row_seg_intersect( ptr2 , ptr1 , segptr ) ; } else { row_seg_intersect( ptr1 , ptr2 , segptr ) ; } } else if( ptr1->row == row && ptr2->row == row ) { if( segptr->switchvalue == swL_down ) { row_seg_intersect( ptr2 , ptr1 , segptr ) ; } else if( segptr->switchvalue == swL_up ) { row_seg_intersect( ptr1 , ptr2 , segptr ) ; } else if( ABS( segptr->pin1ptr->pinloc - segptr->pin2ptr->pinloc ) > 1 ) { row_seg_intersect( ptr1 , ptr2 , segptr ) ; } } else if( ptr1->row == row ) { if( segptr->switchvalue == swL_down && !segptr->flag ) { row_seg_intersect( ptr2 , ptr1 , segptr ) ; if( ptr1->pinloc >= NEITHER ) { L_jogS[ ++jog_num ] = wkS ; } } else if( (INT) ptr1->pinloc == BOTCELL ) { if( segptr->switchvalue == swL_down ) { row_seg_intersect( ptr2 , ptr1 , segptr ) ; } else { row_seg_intersect( ptr1 , ptr2 , segptr ) ; } } } else if( ptr2->row == row ) { if( segptr->switchvalue == swL_up && !segptr->flag ) { row_seg_intersect( ptr1 , ptr2 , segptr ) ; if( ptr2->pinloc <= NEITHER ) { L_jogS[ ++jog_num ] = wkS ; } } else if( ptr2->pinloc == TOPCELL ) { if( segptr->switchvalue == swL_down ) { row_seg_intersect( ptr2 , ptr1 , segptr ) ; } else { row_seg_intersect( ptr1 , ptr2 , segptr ) ; } } } else if( ptr2->row < row ) { segptr->prev->next = nextptr ; if( nextptr != NULL ) { nextptr->prev = segptr->prev ; } Ysafe_free( segptr ) ; } } } if( wkS == 0 ) { return ; } while( wkS > total_feed_in_the_rowG[row] ) { segptr = workerS[ L_jogS[1] ]->segptr ; min_i = 1 ; min_x = ABS( segptr->pin1ptr->xpos - segptr->pin2ptr->xpos ) ; for( i = 2 ; i <= jog_num ; i++ ) { segptr = workerS[ L_jogS[i] ]->segptr ; x = ABS( segptr->pin1ptr->xpos - segptr->pin2ptr->xpos ) ; if( x < min_x ) { min_i = i ; min_x = x ; } } if( min_i == jog_num ) { if( L_jogS[jog_num] < wkS ) { copy_workerS_field( workerS[ L_jogS[jog_num] ], workerS[wkS] ) ; } } else { copy_workerS_field( workerS[ L_jogS[min_i] ], workerS[ L_jogS[jog_num] ] ) ; copy_workerS_field( workerS[ L_jogS[jog_num] ], workerS[wkS] ) ; } wkS-- ; jog_num-- ; } /* Carl's attempt at improving the feed position assignment */ /* using, god forbid, a nonheuristic, nonhack algorithm for */ /* once (linear assignment) */ Yquicksort( (char *)(workerS+1), wkS, sizeof(FEED_SEG_PTR), comparenptr); if( impFeedsG[row]->next == NULL ) { return ; } /* find out the number of available feeds */ v_tracks = 0 ; for( imptr = impFeedsG[row]->next ; imptr ; imptr = imptr->next ) { v_tracks++ ; } #ifdef CARL_NEW assigned_to_track = (INT *) Ysafe_calloc( (1+v_tracks) , sizeof(INT) ) ; num_parts = v_tracks / 400 ; /* if remainder >= 100 or num_parts == 0 ) */ if( v_tracks - 400 * num_parts >= 100 || num_parts == 0 ) { num_parts++ ; } if( row % 5 == 0 ) { fprintf(fpoG,"Divide-and-Conquer Subdivisions in LA:%d at row:%d\n", num_parts, row ) ; fflush(fpoG); } /* READER: don't expect to understand anything until the end of the */ /* the "for" loop */ tot_imp_fds = 0 ; imptr = impFeedsG[row]->next ; for( ; ; ) { tot_imp_fds++ ; if( imptr->next != NULL ) { imptr = imptr->next ; } else { break ; } } bound = wkS / num_parts ; /* special case of large number of feeds and small number of crossings */ if( bound < num_parts ){ bound = wkS ; num_parts = 1 ; } f_count = 0 ; for( assign_iter = 1 ; assign_iter <= num_parts ; assign_iter++ ) { req_remaining_fds = wkS - bound * num_parts ; req_remaining_fds += bound * (num_parts - assign_iter + 1) ; i_bound = (assign_iter - 1) * bound + 1 ; if( assign_iter < num_parts ) { f_bound = assign_iter * bound ; } else { f_bound = wkS ; } num_feeds = f_bound - i_bound + 1 ; /* determines bounds */ start_feed_xpos = workerS[i_bound]->netptr->xpos ; end_feed_xpos = workerS[f_bound]->netptr->xpos ; remaining_fds = tot_imp_fds ; i_count = 0 ; imptr = impFeedsG[row]->next ; for( ; ; ) { i_count++ ; remaining_fds-- ; if( imptr->xpos >= start_feed_xpos && i_count > f_count ) { break ; } if( imptr->next != NULL ) { if( remaining_fds >= req_remaining_fds ) { imptr = imptr->next ; } else { break ; } } else { break ; } } count = 0 ; /* count is the number of unused feeds in the interval */ if( assign_iter < num_parts ) { req_remaining_fds = wkS - bound * num_parts ; req_remaining_fds += bound * (num_parts - assign_iter) ; } else { req_remaining_fds = 0 ; } i_imptr = imptr ; f_count = i_count - 1 ; remaining_fds++ ; for( ; ; ) { f_imptr = imptr ; f_count++ ; count++ ; remaining_fds-- ; if( imptr->xpos >= end_feed_xpos && count >= num_feeds ) { break ; } if( imptr->next != NULL ) { if( remaining_fds - 1 >= req_remaining_fds ) { imptr = imptr->next ; } else { break ; } } else { break ; } } if( count < num_feeds ) { fprintf(fpoG,"GR fails at line 501\n"); fflush(fpoG); } cost = Yassign_init( count , count ) ; for( feed = i_bound ; feed <= f_bound ; feed++ ) { feed_xpos = workerS[feed]->netptr->xpos ; track = 0 ; imptr = i_imptr ; for( i = i_count ; i <= f_count ; i++ ) { track++ ; track_xpos = imptr->xpos ; cost[feed-i_bound+1][track] = ABS( feed_xpos - track_xpos ) ; imptr = imptr->next ; } } for( feed = num_feeds + 1 ; feed <= count ; feed++ ) { track = 0 ; for( i = i_count ; i <= f_count ; i++ ) { track++ ; cost[feed][track] = 1000000 ; } } assign_to_track = Yassign( cost , count , count ) ; num_assigned = 0 ; for( feed = i_bound ; feed <= f_bound ; feed++ ) { assigned_track = assign_to_track[feed-i_bound+1] ; track = 0 ; imptr = i_imptr ; for( i = i_count ; i <= f_count ; i++ ) { if( ++track == assigned_track ) { break ; } imptr = imptr->next ; } if( assigned_to_track[i] != 0 ) { printf("total screw up\n"); fflush(stdout); } else { assigned_to_track[i] = feed ; } assgn_impin( imptr , workerS[feed] , row ) ; num_assigned++ ; } /* fprintf(fpoG,"row:%d\tnum_feeds:%d\tnum_assigned:%d\t\tcount:%d\n", row, num_feeds, num_assigned , count ) ; printf("row:%d\tnum_feeds:%d\tnum_assigned:%d\t\tcount:%d\n", row, num_feeds, num_assigned , count ) ; fflush(fpoG); fflush(stdout); */ Yassign_free( cost , count , count ) ; /* end of this fly-by-night attempt */ } Ysafe_free( assigned_to_track ) ; #else cost = Yassign_init( v_tracks , v_tracks ) ; for( feed = 1 ; feed <= wkS ; feed++ ) { feed_xpos = workerS[feed]->netptr->xpos ; track = 0 ; for( imptr = impFeeds[row]->next ; imptr ; imptr = imptr->next ) { track++ ; track_xpos = imptr->xpos ; cost[feed][track] = ABS( feed_xpos - track_xpos ) ; } } for( ; feed <= v_tracks ; feed++ ) { track = 0 ; for( imptr = impFeeds[row]->next ; imptr ; imptr = imptr->next ) { track++ ; cost[feed][track] = 1000000 ; } } assign_to_track = Yassign( cost , v_tracks , v_tracks ) ; for( feed = 1 ; feed <= wkS ; feed++ ) { assigned_track = assign_to_track[feed] ; track = 0 ; for( imptr = impFeeds[row]->next ; imptr ; imptr = imptr->next ) { if( ++track == assigned_track ) { break ; } } assgn_impin( imptr , workerS[feed] , row ) ; } Yassign_free( cost , v_tracks , v_tracks ) ; Ysafe_free( assigned_to_track ) ; /* end of this fly-by-night attempt */ #endif return ; } #else FeedAssgn( row ) INT row ; { PINBOXPTR netptr , ptr1 , ptr2 ; SEGBOXPTR segptr , nextptr ; IPBOXPTR imptr , iptr , ipinptr[40] ; FEED_DATA *feedptr ; INT net , impcount , firstnode , spacing ; INT i , j , k , last_i , last_j ; INT min_i , min_x , x , jog_num ; INT comparenptr() ; wkS = 0 ; jog_num = 0 ; feedptr = feedpptr[row] ; for( net = 1 ; net <= numnetsG ; net++ ) { for( netptr = steinerHead[net]->next ; netptr ; netptr = netptr->next ) { if( netptr->flag && netptr->row == row ) { row_seg_intersect( netptr , NULL , NULL ) ; } } for( segptr = netsegHead[net]->next ; segptr ; segptr = nextptr ) { nextptr = segptr->next ; ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; if( ptr1->row < row && ptr2->row > row ) { if( segptr->switchvalue == swL_down ) { row_seg_intersect( ptr2 , ptr1 , segptr ) ; } else { row_seg_intersect( ptr1 , ptr2 , segptr ) ; } } else if( ptr1->row == row && ptr2->row == row ) { if( segptr->switchvalue == swL_down ) { row_seg_intersect( ptr2 , ptr1 , segptr ) ; } else if( segptr->switchvalue == swL_up ) { row_seg_intersect( ptr1 , ptr2 , segptr ) ; } else if( ABS( segptr->pin1ptr->pinloc - segptr->pin2ptr->pinloc ) > 1 ) { row_seg_intersect( ptr1 , ptr2 , segptr ) ; } } else if( ptr1->row == row ) { if( segptr->switchvalue == swL_down && !segptr->flag ) { row_seg_intersect( ptr2 , ptr1 , segptr ) ; if( ptr1->pinloc >= NEITHER ) { L_jogS[ ++jog_num ] = wkS ; } } else if( (INT) ptr1->pinloc == BOTCELL ) { if( segptr->switchvalue == swL_down ) { row_seg_intersect( ptr2 , ptr1 , segptr ) ; } else { row_seg_intersect( ptr1 , ptr2 , segptr ) ; } } } else if( ptr2->row == row ) { if( segptr->switchvalue == swL_up && !segptr->flag ) { row_seg_intersect( ptr1 , ptr2 , segptr ) ; if( ptr2->pinloc <= NEITHER ) { L_jogS[ ++jog_num ] = wkS ; } } else if( ptr2->pinloc == TOPCELL ) { if( segptr->switchvalue == swL_down ) { row_seg_intersect( ptr2 , ptr1 , segptr ) ; } else { row_seg_intersect( ptr1 , ptr2 , segptr ) ; } } } else if( ptr2->row < row ) { segptr->prev->next = nextptr ; if( nextptr != NULL ) { nextptr->prev = segptr->prev ; } Ysafe_free( segptr ) ; } } } if( wkS == 0 ) { return ; } while( wkS > total_feed_in_the_rowG[row] ) { segptr = workerS[ L_jogS[1] ]->segptr ; min_i = 1 ; min_x = ABS( segptr->pin1ptr->xpos - segptr->pin2ptr->xpos ) ; for( i = 2 ; i <= jog_num ; i++ ) { segptr = workerS[ L_jogS[i] ]->segptr ; x = ABS( segptr->pin1ptr->xpos - segptr->pin2ptr->xpos ) ; if( x < min_x ) { min_i = i ; min_x = x ; } } if( min_i == jog_num ) { if( L_jogS[jog_num] < wkS ) { copy_workerS_field( workerS[ L_jogS[jog_num] ], workerS[wkS] ) ; } } else { copy_workerS_field( workerS[ L_jogS[min_i] ], workerS[ L_jogS[jog_num] ] ) ; copy_workerS_field( workerS[ L_jogS[jog_num] ], workerS[wkS] ) ; } wkS-- ; jog_num-- ; } imptr = impFeeds[row]->next ; Yquicksort( (char *)(workerS+1) , wkS , sizeof(FEED_SEG_PTR),comparenptr ); firstnode = set_node( workerS[1]->netptr->xpos ) ; i = 1 ; for( i = 1 ; i <= chan_node_no ; i++ ) { feedptr[i]->needed = 0 ; } for( i = 1 ; i <= wkS ; i++ ) { j = set_node( workerS[i]->netptr->xpos ) ; if( feedptr[j]->needed == 0 ) { wk_headS[j] = i ; } feedptr[j]->needed++ ; } /* assign the feedthru pin for the segment from count down to i */ for( k = firstnode ; k <= chan_node_no ; k++ ) { if( feedptr[k]->needed > feedptr[k]->actual ) { local_Assgn( row , k ) ; } } for( k = 1 ; k <= chan_node_no ; k++ ) { if( feedptr[k]->actual == 0 || feedptr[k]->needed == 0 ) { continue ; } else if( feedptr[k]->needed == feedptr[k]->actual ) { for( imptr = feedptr[k]->firstimp ; tearray[ imptr->terminal ] ; imptr = imptr->next ); last_i = wk_headS[k] + feedptr[k]->needed - 1 ; for( i = wk_headS[k] ; i <= last_i ; i++ ) { assgn_impin( imptr , workerS[i] , row ) ; imptr = imptr->next ; } } else { impcount = 0 ; for( imptr = feedptr[k]->firstimp ; tearray[ imptr->terminal ] ; imptr = imptr->next ); for( ; tearray[ imptr->terminal ] == NULL ; imptr = imptr->next ) { ipinptr[++impcount] = imptr ; if( impcount >= feedptr[k]->actual ) { break ; } } last_j = wk_headS[k] + feedptr[k]->needed - 1 ; for( j = wk_headS[k] ; j <= last_j ; j++ ) { spacing = INT_MAX ; for( i = 1 ; i <= impcount ; i++ ) { if( tearray[ ipinptr[i]->terminal ] ) { continue ; } if( ABS( ipinptr[i]->xpos - workerS[j]->netptr->xpos ) < spacing ) { iptr = ipinptr[i] ; spacing = ABS( iptr->xpos - workerS[j]->netptr->xpos ) ; } } assgn_impin( iptr , workerS[j] , row ) ; } } feedptr[k]->actual -= feedptr[k]->needed ; feedptr[k]->needed = 0 ; } } #endif row_seg_intersect( ptr1 , ptr2 , segptr ) PINBOXPTR ptr1 , ptr2 ; SEGBOXPTR segptr ; { INT i ; if( ++wkS > max_feed_in_a_rowS ) { max_feed_in_a_rowS = max_feed_in_a_rowS + 100 ; wk_headS = (INT *) Ysafe_realloc( wk_headS , max_feed_in_a_rowS * sizeof(INT) ) ; L_jogS = (INT *) Ysafe_realloc( L_jogS , max_feed_in_a_rowS * sizeof(INT) ) ; workerS = (FEED_SEG_PTR *)Ysafe_realloc( workerS , ( max_feed_in_a_rowS + 1 ) * sizeof(FEED_SEG_PTR) ) ; for( i = wkS ; i <= max_feed_in_a_rowS ; i++ ) { workerS[i] = ( FEED_SEG_PTR )Ysafe_malloc( sizeof(FEED_SEG) ) ; } } workerS[ wkS ]->netptr = ptr1 ; workerS[ wkS ]->refer = ptr2 ; workerS[ wkS ]->segptr = segptr ; } copy_workerS_field( aptr, bptr ) FEED_SEG_PTR aptr, bptr ; { aptr->netptr = bptr->netptr ; aptr->refer = bptr->refer ; aptr->segptr = bptr->segptr ; } #ifdef CARL_NEW assgn_impin( imptr , fsptr , row ) IPBOXPTR imptr ; FEED_SEG_PTR fsptr ; { INT net ; PINBOXPTR netptr , ptr1 , ptr2 ; SEGBOXPTR segptr ; ++implicit_pins_usedG ; if( fsptr->segptr ) { netptr = ( PINBOXPTR )Ysafe_calloc( 1, sizeof( PINBOX ) ) ; netptr->adjptr = (ADJASEGPTR)Ysafe_calloc( 1, sizeof(ADJASEG) ) ; netptr->net = net = fsptr->segptr->pin1ptr->net ; netptr->row = row ; netptr->next = netarrayG[net]->pins ; netarrayG[net]->pins = netptr ; segptr = fsptr->segptr ; netptr->xpos = imptr->xpos ; /* FIXME: the following line leaks memory but just freeing it gives freed memory access */ segptr->pin1ptr = netptr ; ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; #define TWF #ifdef TWF if( ptr2->row == ptr1->row ) { segptr->switchvalue == nswLINE ; segptr->flag = TRUE ; } else if( add_Lcorner_feedG && ABS( ptr1->xpos - ptr2->xpos ) >= average_feed_sepG ) { segptr->flag = FALSE ; } else { segptr->flag = TRUE ; } #else if( ptr2->row == ptr1->row ) { segptr->switchvalue == nswLINE ; segptr->flag = TRUE ; /* else if( add_Lcorner_feed && */ /* ABS( ptr1->xpos - ptr2->xpos ) >= average_feed_sep ) */ } else { segptr->flag = FALSE ; /* else */ /* segptr->flag = TRUE ; */ } #endif } else { /* a steiner point */ netptr = fsptr->netptr ; netptr->xpos = imptr->xpos ; } netptr->ypos = barrayG[row]->bycenter ; netptr->cell = imptr->cell ; netptr->pinloc = NEITHER ; netptr->terminal = imptr->terminal ; netptr->pinname = imptr->pinname ; tearrayG[ netptr->terminal ] = netptr ; netptr->eqptr = ( EQ_NBOXPTR )Ysafe_calloc( 1, sizeof(EQ_NBOX) ) ; netptr->eqptr->typos = carrayG[ netptr->cell ]->tileptr->bottom ; netptr->eqptr->pinname = imptr->eqpinname ; /* now add timing to feed thru */ if( strncmp( carrayG[netptr->cell]->cname, "twfeed", 6 ) == STRINGEQ ){ carrayG[netptr->cell]->paths = netarrayG[netptr->net]->paths ; } } #else assgn_impin( imptr , fsptr , row ) IPBOXPTR imptr ; FEED_SEG_PTR fsptr ; { INT net ; PINBOXPTR netptr , ptr1 , ptr2 ; SEGBOXPTR segptr ; ++implicit_pins_used ; if( fsptr->segptr ) { netptr = ( PINBOXPTR )Ysafe_malloc( sizeof( PINBOX ) ) ; netptr->adjptr = (ADJASEGPTR)Ysafe_calloc( 1, sizeof(ADJASEG) ) ; netptr->net = net = fsptr->segptr->pin1ptr->net ; netptr->row = row ; netptr->next = netarrayG[net]->pins ; netarrayG[net]->pins = netptr ; segptr = fsptr->segptr ; segptr->pin1ptr = netptr ; ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; netptr->xpos = imptr->xpos ; if( ptr2->row == ptr1->row ) { segptr->switchvalue == nswLINE ; segptr->flag = TRUE ; } else if( add_Lcorner_feed && ABS( ptr1->xpos - ptr2->xpos ) >= average_feed_sep ) { segptr->flag = FALSE ; } else { segptr->flag = TRUE ; } } else { /* a steiner point */ netptr = fsptr->netptr ; netptr->xpos = imptr->xpos ; } netptr->ypos = barrayG[row]->bycenter ; netptr->cell = imptr->cell ; netptr->pinloc = NEITHER ; netptr->terminal = imptr->terminal ; netptr->pinname = imptr->pinname ; tearray[ netptr->terminal ] = netptr ; netptr->eqptr = ( EQ_NBOXPTR )Ysafe_calloc( 1, sizeof(EQ_NBOX) ) ; netptr->eqptr->typos = carrayG[ netptr->cell ]->tileptr->bottom ; netptr->eqptr->pinname = imptr->eqpinname ; } local_Assgn( row , node ) INT row , node ; { INT next , back , head , end , LeftFlag , left_node , rite_node ; INT i , n , k , t , diff , orig_feed_needed , feed_need ; INT shift_left_start_index , shift_rite_start_index ; INT left_start , rite_start ; FEED_DATA *feedptr ; IPBOXPTR imptr ; back = 0 ; next = 0 ; left_node = rite_node = node ; feedptr = feedpptr[row] ; orig_feed_needed = feedptr[node]->needed ; feed_need = feedptr[node]->needed - feedptr[node]->actual ; head = wk_headS[node] ; end = head + orig_feed_needed - 1 ; shellsort_referx( workerS , head , orig_feed_needed ) ; LeftFlag = 0 ; while( feed_need > back + next ) { if( left_node > 1 ) { left_node-- ; t = feedptr[left_node]->actual - feedptr[left_node]->needed ; if( t > 0 ) { back += t ; if( back + next >= feed_need ) { LeftFlag = 1 ; break ; } } } if( rite_node < chan_node_no ) { rite_node++ ; t = feedptr[rite_node]->actual - feedptr[rite_node]->needed ; if( t > 0 ) { next += t ; } } } if( LeftFlag ) { shift_left_start_index = head + feed_need - next - 1 ; } else { shift_left_start_index = head + back - 1 ; } if( shift_left_start_index < head ) { shift_rite_start_index = head + feedptr[node]->actual ; } else { shift_rite_start_index = shift_left_start_index + feedptr[node]->actual + 1 ; } left_start = shift_left_start_index ; rite_start = shift_rite_start_index ; for( n = node - 1 ; n >= left_node ; n-- ) { diff = feedptr[n]->actual - feedptr[n]->needed ; if( diff <= 0 ) { continue ; } for( imptr = feedptr[n]->lastimp ; tearray[ imptr->terminal ] ; imptr = imptr->prev ) ; k = 0 ; for( i = 1 ; i <= diff ; i++ ) { if( left_start >= head ) { assgn_impin( imptr , workerS[ left_start-- ] , row ) ; imptr = imptr->prev ; ++k ; } else { break ; } } feedptr[n]->actual -= k ; } for( n = node + 1 ; n <= rite_node ; n++ ) { diff = feedptr[n]->actual - feedptr[n]->needed ; if( diff <= 0 ) { continue ; } for( imptr = feedptr[n]->firstimp ; tearray[ imptr->terminal ] ; imptr = imptr->next ) ; k = 0 ; for( i = 1 ; i <= diff ; i++ ) { if( rite_start <= end ) { assgn_impin( imptr , workerS[ rite_start++ ] , row ) ; imptr = imptr->next ; ++k ; } else { break ; } } feedptr[n]->actual -= k ; } imptr = feedptr[node]->firstimp ; k = shift_rite_start_index - 1 ; if( shift_rite_start_index > end ) { k = end ; } i = shift_left_start_index + 1 ; if( i < head ) { i = head ; } for( ; i <= k ; i++ ) { assgn_impin( imptr , workerS[i] , row ) ; imptr = imptr->next ; } feedptr[node]->actual = 0 ; feedptr[node]->needed = 0 ; } #endif unequiv_pin_pre_processing() { DBOXPTR dimptr ; PINBOXPTR ptr ; INT net, row, hi, lo, k, xmin, xmax ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[net] ; if( dimptr->numpins <= 1 ) continue ; ptr = dimptr->pins ; lo = hi = ptr->row ; for( ptr = ptr->next ; ptr ; ptr = ptr->next ) { if( lo > ptr->row ) lo = ptr->row ; if( hi < ptr->row ) hi = ptr->row ; } if( lo == hi ) { if( dimptr->numpins == 2 ) continue ; ptr = dimptr->pins ; xmin = xmax = ptr->xpos ; for( ptr = ptr->next ; ptr ; ptr = ptr->next ) { if( ptr->xpos < xmin ) { xmin = ptr->xpos ; } else if( ptr->xpos > xmax ) { xmax = ptr->xpos ; } } for( ptr = dimptr->pins ; ptr ; ptr = ptr->next ) { if( ptr->eqptr == NULL || ptr->eqptr->unequiv == 0 ) { continue ; } if( ptr->xpos != xmin && ptr->xpos != xmax ) { ptr->pinloc = BOTCELL ; } } } for( ptr = dimptr->pins ; ptr ; ptr = ptr->next ) { if( ptr->eqptr == NULL || ptr->eqptr->unequiv == 0 ) { continue ; } row = ptr->row ; if( row == hi ) { ptr->pinloc = BOTCELL ; } else if( row == lo ) { ptr->pinloc = TOPCELL ; } else { k = ( row - lo ) % 2 ; if( k == 1 ) { ptr->pinloc = BOTCELL ; } else { ptr->pinloc = TOPCELL ; } } } } } relax_padPins_pinloc() { INT i ; PINBOXPTR pinptr ; for( i = lastpadG ; i > numcellsG ; i-- ) { for( pinptr = carrayG[i]->pins ;pinptr ; pinptr = pinptr->nextpin ) { if( pinptr->adjptr->next == NULL ) { pinptr->pinloc = NEITHER ; } else if( pinptr->adjptr->next->next == NULL ) { pinptr->pinloc = NEITHER ; } } } } relax_unequiv_pinloc() { DBOXPTR dimptr ; PINBOXPTR ptr ; INT net ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[net] ; if( dimptr->numpins <= 2 ) continue ; for( ptr = dimptr->pins ; ptr ; ptr = ptr->next ) { if( ptr->pinloc == NEITHER || ptr->eqptr == NULL || ptr->eqptr->unequiv == 0 ) continue ; if( ptr->adjptr->next == NULL ) { ptr->pinloc = NEITHER ; } else if( ptr->adjptr->next->next == NULL ) { ptr->pinloc = NEITHER ; } } } } check_unequiv_connectivity() { INT net, channel, correctness ; ADJASEG *adj ; PINBOXPTR pinptr ; DBOXPTR dimptr ; correctness = 1 ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[net] ; if( dimptr->numpins <= 1 ) { continue ; } for( pinptr = dimptr->pins ; pinptr ; pinptr = pinptr->next ) { if( pinptr->eqptr == NULL || pinptr->eqptr->unequiv == 0 ) { continue ; } adj = pinptr->adjptr->next ; channel = adj->segptr->flag ; for( adj = adj->next ; adj ; adj = adj->next ) { if( channel != adj->segptr->flag ) { correctness = 0 ; printf(" unequivalent pin connection violation" ) ; printf(" for net %d pin %d\n", net, pinptr->terminal ) ; } } } } return( correctness ) ; } #define UNVISITED_SEG 0 #define VISITED_SEG 1 #define REVISITED_SEG 1 static LONG swap_cost( perim_flag ) BOOL perim_flag ; { PINBOXPTR pin1ptr , pin2ptr ; SEGBOXPTR segptr ; DBOXPTR net_p ; INT xwire, ywire ; INT net ; LONG global_wire_length ; INT newtimepenal ; FILE *fp ; static BOOL outputL = TRUE ; INT p_path, s_path ; INT Px, Sx, Py, Sy, Ppath, Spath ; /* used to cummulate info */ /* ----------------------------------------------------------------- We are going to use the half perimeter fields to calculate the timing costs. We find the global wire cost by adding up the length from the segments. ----------------------------------------------------------------- */ global_wire_length = 0 ; D( "twsc/swap_cost", if( outputL == TRUE ){ fp = TWOPEN( "wire", "w", ABORT ) ; fprintf( fp, "net\tnumpins\tPx\tSx\tPy\tSy\tPtime\tStime\n" ) ; Px = 0 ; Py = 0 ; Sx = 0 ; Sy = 0 ; Spath = 0 ; Ppath = 0 ; } ) ; for( net = 1; net <= numnetsG; net++ ){ xwire = 0 ; ywire = 0 ; for( segptr = netsegHeadG[net]->next;segptr;segptr = segptr->next ){ pin1ptr = segptr->pin1ptr ; pin2ptr = segptr->pin2ptr ; segptr->swap_flag = UNVISITED_SEG ; xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ; ywire += ABS(pin1ptr->ypos - pin2ptr->ypos) ; } /* end for( segptr = netsegHeadG[net]... */ global_wire_length += (LONG)xwire ; /* now save result in netarray */ net_p = netarrayG[net] ; if( perim_flag ){ if( net_p->newhalfPx != xwire ){ fprintf( stderr, "new x half perim:%d doesn't match calc.:%d\n", net_p->newhalfPx, xwire ) ; net_p->newhalfPx = xwire ; } if( net_p->newhalfPy != ywire ){ fprintf( stderr, "new y half perim:%d doesn't match calc.:%d\n", net_p->newhalfPy, ywire ) ; net_p->newhalfPy = ywire ; } } else { D( "twsc/swap_cost", if( outputL == TRUE ){ net_p->newhalfPx = xwire ; net_p->newhalfPy = ywire ; p_path = dpath_len( net, TRUE ) ; s_path = dpath_len( net, FALSE ) ; fprintf( fp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", net, net_p->numpins, net_p->halfPx, xwire, net_p->halfPy, ywire, p_path, s_path ) ; Px += net_p->halfPx ; Py += net_p->halfPy ; Sx += xwire ; Sy += ywire ; Spath += s_path ; Ppath += p_path ; } ) ; net_p->halfPx = net_p->newhalfPx = xwire ; net_p->halfPy = net_p->newhalfPy = ywire ; } } /* end for( net = 1... */ D( "twsc/swap_cost", if( outputL == TRUE ){ outputL = FALSE ; fprintf( fp, "----------------------------------------------------------------\n"); fprintf( fp, " \t \t%d\t%d\t%d\t%d\t%d\t%d\n", Px,Sx,Py,Sy,Ppath,Spath ) ; TWCLOSE(fp) ; } ) ; /* now recompute the timing penalty */ newtimepenal = recompute_timecost() ; D( "twsc/swap_cost", if( timingcostG != newtimepenal ){ fprintf( stderr, "Timing penalty mismatch %d vs %d\n", timingcostG, newtimepenal ) ; } ) ; timingcostG = newtimepenal ; return( global_wire_length ) ; } /* end swap_cost() */ improve_place_sequential( row , index ) INT row , index ; { INT cell1 , cell2 , shift1 , shift2 , swap ; LONG global_wire , new_global_wire ; INT cell , pin , xpos , other_cell ; LONG ic , fc ; INT net, xwire ; INT newtimepenal ; DBOXPTR net_p ; CBOXPTR ptr ; PINBOXPTR pin1ptr , pin2ptr , termptr ; ADJASEGPTR adjptr ; SEGBOXPTR segptr ; /* ----------------------------------------------------------------- In order to avoid counting segments twice, use the swap_flag field. Initially all segments are marked unvisited. When traversing segments of first cell mark them as visited. When traversing second cell we do not update any segments that have been visited. Everything is fine at this point but we need to set the flags back. We do this when traversing the cells a second time to find the new cost. We then reverse the roles of the flags. It is important to note that VISITED_SEG == REVISITED_SEG. ----------------------------------------------------------------- */ newtimepenal = timingcostG ; global_wire = 0 ; clear_net_set() ; D( "twsc/cell_swap_opt", ic = swap_cost( FALSE ) ; ) ; /* find current global wire lengths */ other_cell = cell = pairArrayG[row][index] ; ptr = carrayG[cell] ; for( termptr = ptr->pins; termptr; termptr = termptr->nextpin ) { pin = termptr->terminal ; net = termptr->net ; net_p = netarrayG[net] ; /* check to see if this net has been initialized */ if(!(member_net_set(net) )){ add2net_set( net ) ; net_p->newhalfPx = net_p->halfPx ; } xwire = 0 ; /* look at all the segments that this pin connects */ for( adjptr = termptr->adjptr->next;adjptr;adjptr = adjptr->next ) { segptr = adjptr->segptr ; if( segptr->swap_flag == UNVISITED_SEG ){ segptr->swap_flag = VISITED_SEG ; /* set to membership */ pin1ptr = segptr->pin1ptr ; pin2ptr = segptr->pin2ptr ; xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ; } } net_p->newhalfPx -= xwire ; global_wire += (LONG)xwire ; } cell = pairArrayG[row][index+1] ; ptr = carrayG[cell] ; for( termptr = ptr->pins; termptr; termptr = termptr->nextpin ) { pin = termptr->terminal ; net = termptr->net ; net_p = netarrayG[net] ; /* check to see if this net has been initialized */ if(!(member_net_set(net) )){ add2net_set( net ) ; net_p->newhalfPx = net_p->halfPx ; } xwire = 0 ; for( adjptr = termptr->adjptr->next;adjptr;adjptr = adjptr->next ) { segptr = adjptr->segptr ; if( segptr->swap_flag == UNVISITED_SEG ){ segptr->swap_flag = VISITED_SEG ; pin1ptr = segptr->pin1ptr ; pin2ptr = segptr->pin2ptr ; xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ; } } net_p->newhalfPx -= xwire ; global_wire += (LONG)xwire ; } /* swap cells */ cell1 = pairArrayG[row][index] ; cell2 = pairArrayG[row][index+1] ; shift1 = carrayG[cell2]->clength ; shift2 = -carrayG[cell1]->clength ; carrayG[cell1]->cxcenter += shift1 ; carrayG[cell2]->cxcenter += shift2 ; pairArrayG[row][index] = cell2 ; pairArrayG[row][index+1] = cell1 ; /* ...update pin positions now..... */ for( termptr = carrayG[cell1]->pins; termptr; termptr = termptr->nextpin ) { termptr->xpos += shift1 ; } for( termptr = carrayG[cell2]->pins; termptr; termptr = termptr->nextpin ) { termptr->xpos += shift2 ; } /* find new global wire lengths */ new_global_wire = 0 ; other_cell = cell = pairArrayG[row][index] ; ptr = carrayG[cell] ; for( termptr = ptr->pins; termptr; termptr = termptr->nextpin ) { pin = termptr->terminal ; net_p = netarrayG[termptr->net] ; xwire = 0 ; for( adjptr = termptr->adjptr->next;adjptr;adjptr = adjptr->next ) { segptr = adjptr->segptr ; if( segptr->swap_flag == REVISITED_SEG ){ segptr->swap_flag = UNVISITED_SEG ; pin1ptr = segptr->pin1ptr ; pin2ptr = segptr->pin2ptr ; xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ; } } net_p->newhalfPx += xwire ; new_global_wire += (LONG)xwire ; } cell = pairArrayG[row][index+1] ; ptr = carrayG[cell] ; for( termptr = ptr->pins; termptr; termptr = termptr->nextpin ) { pin = termptr->terminal ; net_p = netarrayG[termptr->net] ; xwire = 0 ; for( adjptr = termptr->adjptr->next;adjptr;adjptr = adjptr->next ) { segptr = adjptr->segptr ; if( segptr->swap_flag == REVISITED_SEG ){ segptr->swap_flag = UNVISITED_SEG ; pin1ptr = segptr->pin1ptr ; pin2ptr = segptr->pin2ptr ; xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ; } } net_p->newhalfPx += xwire ; new_global_wire += (LONG)xwire ; } /* ----------------------------------------------------------------- Calculate the timing penalty for swap. ----------------------------------------------------------------- */ newtimepenal += calc_incr_time2( cell1, cell2 ) ; D( "twsc/check_timing/globe", if( dcalc_full_penalty(newtimepenal) == FALSE ){ fprintf( stderr, "Problem with timing penalty\n" ) ; } ) ; D( "twsc/cell_swap_opt", fc = swap_cost( TRUE ) ; if( fc - ic != new_global_wire - global_wire ) { fprintf(stderr,"error in improve_place_sequential()\n"); } ) ; // (global_wire - new_global_wire) is assumed to not exceed size INT // although each termin is size LONG if( accept_greedy( (INT)(global_wire-new_global_wire), timingcostG-newtimepenal, 0 )){ swap = (INT)(new_global_wire - global_wire) ; global_wire_lengthS += (LONG)swap ; swap += newtimepenal - timingcostG ; if( numpathsG ){ update_time2() ; timingcostG = newtimepenal ; /* ----------------------------------------------------------------- There might be some redundancy here but the checking for it has overhead. Do simple method for now. ----------------------------------------------------------------- */ ptr = carrayG[cell1] ; for( termptr = ptr->pins;termptr;termptr=termptr->nextpin ) { net_p = netarrayG[termptr->net] ; net_p->halfPx = net_p->newhalfPx ; } ptr = carrayG[cell2] ; for( termptr = ptr->pins;termptr;termptr=termptr->nextpin ) { net_p = netarrayG[termptr->net] ; net_p->halfPx = net_p->newhalfPx ; } } return( swap ) ; } else { /* swap cells back to original position */ cell1 = pairArrayG[row][index] ; cell2 = pairArrayG[row][index+1] ; shift1 = carrayG[cell2]->clength ; shift2 = -carrayG[cell1]->clength ; carrayG[cell1]->cxcenter += shift1 ; carrayG[cell2]->cxcenter += shift2 ; pairArrayG[row][index] = cell2 ; pairArrayG[row][index+1] = cell1 ; /* ...update pin positions now..... */ for( termptr = carrayG[cell1]->pins; termptr; termptr = termptr->nextpin ) { termptr->xpos += shift1 ; } for( termptr = carrayG[cell2]->pins; termptr; termptr = termptr->nextpin ) { termptr->xpos += shift2 ; } return(0); } } cell_rotate( row , index ) INT row , index ; { INT cell, swap ; LONG global_wire , new_global_wire ; INT pin , xpos ; LONG ic, fc ; INT net, xwire, xc, left, right, dist_l, dist_r ; INT newtimepenal ; DBOXPTR net_p ; CBOXPTR ptr ; PINBOXPTR pin1ptr , pin2ptr , termptr ; ADJASEGPTR adjptr ; SEGBOXPTR segptr ; /* ----------------------------------------------------------------- In order to avoid counting segments twice, use the swap_flag field. ----------------------------------------------------------------- */ D( "twsc/cell_swap_opt", ic = swap_cost( FALSE ) ; ) ; global_wire = 0 ; clear_net_set() ; /* find current global wire lengths */ cell = pairArrayG[row][index] ; ptr = carrayG[cell] ; if( ptr->orflag == 0){ return(0) ; } for( termptr = ptr->pins; termptr; termptr = termptr->nextpin ) { pin = termptr->terminal ; net = termptr->net ; net_p = netarrayG[net] ; /* check to see if this net has been initialized */ if(!(member_net_set(net) )){ add2net_set( net ) ; net_p->newhalfPx = net_p->halfPx ; } xwire = 0 ; /* look at all the segments that this pin connects */ for( adjptr = termptr->adjptr->next;adjptr;adjptr = adjptr->next ) { segptr = adjptr->segptr ; if( segptr->swap_flag == UNVISITED_SEG ){ segptr->swap_flag = VISITED_SEG ; /* set to membership */ pin1ptr = segptr->pin1ptr ; pin2ptr = segptr->pin2ptr ; xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ; } } net_p->newhalfPx -= xwire ; global_wire += (LONG)xwire ; } /* rotate the cell */ xc = ptr->cxcenter ; left = xc + ptr->tileptr->left ; right = xc + ptr->tileptr->right ; /* ...update pin positions now..... */ for( termptr = carrayG[cell]->pins; termptr; termptr = termptr->nextpin ) { dist_l = termptr->xpos - left ; dist_r = right - termptr->xpos ; if( dist_l < dist_r ){ /* pin closer to left edge move to right edge */ termptr->xpos = right - dist_l ; } else { /* pin closer to right edge move to left edge */ termptr->xpos = left + dist_r ; } } /* find new global wire lengths */ new_global_wire = 0 ; for( termptr = ptr->pins; termptr; termptr = termptr->nextpin ) { pin = termptr->terminal ; net_p = netarrayG[termptr->net] ; xwire = 0 ; for( adjptr = termptr->adjptr->next;adjptr;adjptr = adjptr->next ) { segptr = adjptr->segptr ; if( segptr->swap_flag == REVISITED_SEG ){ segptr->swap_flag = UNVISITED_SEG ; pin1ptr = segptr->pin1ptr ; pin2ptr = segptr->pin2ptr ; xwire += ABS(pin1ptr->xpos - pin2ptr->xpos) ; } } net_p->newhalfPx += xwire ; new_global_wire += (LONG)xwire ; } /* ----------------------------------------------------------------- Calculate the timing penalty for swap. ----------------------------------------------------------------- */ newtimepenal = timingcostG + calc_incr_time( cell ) ; D( "twsc/check_timing", ASSERT( dcalc_full_penalty(newtimepenal), NULL, "time problem\n" ) ; ) ; D( "twsc/cell_swap_opt", fc = swap_cost( TRUE ) ; if( fc - ic != new_global_wire - global_wire ) { fprintf(stderr,"error in cell_rotate()\n"); } ) ; if( accept_greedy( (INT)(global_wire-new_global_wire), timingcostG-newtimepenal, 0 )){ swap = (INT)(new_global_wire - global_wire ); global_wire_lengthS += (LONG)swap ; swap += newtimepenal - timingcostG ; if( numpathsG ){ update_time(cell) ; timingcostG = newtimepenal ; /* ----------------------------------------------------------------- There might be some redundancy here but the checking for it has overhead. Do simple method for now. ----------------------------------------------------------------- */ ptr = carrayG[cell] ; for( termptr = ptr->pins;termptr;termptr=termptr->nextpin ) { net_p = netarrayG[termptr->net] ; net_p->halfPx = net_p->newhalfPx ; } } /* make sure to update cell orient field */ if( ptr->corient == 0 ){ ptr->corient = 2 ; } else if( ptr->corient == 2 ){ ptr->corient = 0 ; } else if( ptr->corient == 1 ){ ptr->corient = 3; } else if( ptr->corient == 3 ){ ptr->corient = 1; } else { sprintf( YmsgG, "Invalid rotation for cell:%s\n", ptr->cname ) ; M( ERRMSG, "cell_rotate", YmsgG ) ; } return( swap ) ; } else { /* rotate cells back to original position */ for( termptr = carrayG[cell]->pins; termptr; termptr = termptr->nextpin ) { dist_l = termptr->xpos - left ; dist_r = right - termptr->xpos ; if( dist_l < dist_r ){ /* pin closer to left edge move to right edge */ termptr->xpos = right - dist_l ; } else { /* pin closer to right edge move to left edge */ termptr->xpos = left + dist_r ; } } return(0); } } /* end cell_rotate() */ elim_unused_feedsSC() { CBOXPTR ptr , cellptr , first_cptr , last_cptr ; PINBOXPTR termptr ; INT row, feed_count, i , last , cell_left , length , max_length ; INT j , k , elim , cell , limit , left_edge , corient ; INT *Aray , longest_row , shift , *row_len , total_elim ; row_len = (INT *) Ysafe_calloc( (1+numRowsG) , sizeof(INT) ) ; for( i = 1 ; i <= numRowsG ; i++ ) { Aray = pairArrayG[i] ; first_cptr = carrayG[ Aray[1] ] ; last_cptr = carrayG[ Aray[ Aray[0] ] ] ; length = last_cptr->cxcenter + last_cptr->tileptr->right - first_cptr->cxcenter - first_cptr->tileptr->left ; row_len[i] = length ; } total_elim = 0 ; for( ; ; ) { /* find longest row */ max_length = 0 ; for( i = 1 ; i <= numRowsG ; i++ ) { if( row_len[i] > max_length ) { max_length = row_len[i] ; row = i ; } } i = 0 ; limit = pairArrayG[row][0] ; for( k = limit ; k >= 1 ; k-- ) { cell = pairArrayG[row][k] ; if( strncmp(carrayG[cell]->cname,"twfeed",6) == STRINGEQ ) { if( tearrayG[carrayG[cell]->imptr->terminal] == NULL ) { if( carrayG[cell]->clength != 0 ) { /* we have here an unused feed cell */ row_len[row] -= carrayG[cell]->clength ; carrayG[cell]->clength = 0 ; carrayG[cell]->tileptr->left = 0 ; carrayG[cell]->tileptr->right = 0 ; i++ ; break ; } } } } if( i == 0 ) { fprintf(fpoG,"Eliminated %d unused feeds in the longest row\n", total_elim ) ; break ; } else { total_elim++ ; /* replace, i.e. repack, the cells for this row */ left_edge = barrayG[row]->bxcenter + barrayG[row]->bleft ; for( i = 1 ; i <= limit ; i++ ) { cellptr = carrayG[ pairArrayG[row][i] ] ; cell_left = cellptr->tileptr->left ; shift = (left_edge - cell_left) - cellptr->cxcenter ; /* new minus old */ cellptr->cxcenter += shift ; for( termptr = cellptr->pins; termptr; termptr = termptr->nextpin ){ termptr->xpos += shift ; } left_edge += cellptr->tileptr->right - cell_left ; } } } /* now print out the new row lengths */ fprintf(fpoG,"BLOCK TOTAL CELL LENGTHS OVER/UNDER TARGET\n"); max_length = 0 ; for( i = 1 ; i <= numRowsG ; i++ ) { Aray = pairArrayG[i] ; first_cptr = carrayG[ Aray[1] ] ; last_cptr = carrayG[ Aray[ Aray[0] ] ] ; length = last_cptr->cxcenter + last_cptr->tileptr->right - first_cptr->cxcenter - first_cptr->tileptr->left ; fprintf( fpoG, "%3d %7d \n", i, length ); if( max_length < length ) { longest_row = i ; max_length = length ; } } fprintf( fpoG, "\nLONGEST Row is:%d Its length is:%d\n", longest_row , max_length ) ; Ysafe_free( row_len ); return ; } rebuild_nextpin() { INT net, cell ; PINBOXPTR netptr , cnetptr ; /* added by Carl 22 July 1990 */ /* blow off the old nextpin fields as they may be corrupted anyway */ for( net = 1 ; net <= numnetsG ; net++ ) { for( netptr = netarrayG[net]->pins ; netptr ; netptr = netptr->next ) { netptr->nextpin = NULL ; } } for( cell = 1 ; cell <= lastpadG ; cell++ ) { carrayG[cell]->pins = NULL ; } /* now rebuild the nextpin fields */ for( net = 1 ; net <= numnetsG ; net++ ) { for( netptr = netarrayG[net]->pins ; netptr ; netptr = netptr->next ) { if( netptr->net <= 0 ){ fprintf( stderr, "We have an zero net\n" ) ; continue ; } /* add it into this cell's pin list */ cnetptr = carrayG[netptr->cell]->pins ; carrayG[netptr->cell]->pins = netptr ; carrayG[netptr->cell]->pins->nextpin = cnetptr ; } } } /* end rebuild_nextpin */ rebuild_cell_paths() { INT i ; CBOXPTR ptr ; GLISTPTR path_p, freepath_p ; for( i=1;i<=lastpadG; i++ ){ ptr = carrayG[i] ; for( path_p = ptr->paths;path_p; ){ freepath_p = path_p ; path_p = path_p->next ; Ysafe_free( freepath_p ) ; } ptr->paths = NULL ; } add_paths_to_cells() ; } /* end rebuild_cell_paths() */ graywolf-0.1.4+20170307gite1bf319/src/twsc/globroute.c000066400000000000000000000135141305746555600217050ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * Copyright (C) 2015 Staf Verhaegen * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: globroute.c DESCRIPTION:global routing functions. CONTENTS: globroute() process_cross( segptr , status ) INT status ; SEGBOXPTR segptr ; DATE: Mar 27, 1989 REVISIONS: Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) globroute.c (Yale) version 4.5 12/15/90" ; #endif #endif #include "standard.h" #include "groute.h" #include "main.h" /* global variables */ extern INT Max_numPinsG ; #define TOP 1 #define BOT 0 globroute() { INT flips , attempts , net ; INT pick , number , attlimit ; INT found , trys , maxtrys ; INT x , x1 , x2 , channel ; SEGBOXPTR segptr , *segment ; DENSITYPTR denptr ; PINBOXPTR netptr1 , netptr2 ; changrid( ) ; pre_findrcost( ) ; findrcost() ; fprintf(fpoG,"\n\nTHIS IS THE ORIGINAL NUMBER OF TRACKS: %d\n\n\n" , tracksG ) ; fflush(fpoG); flips = 0 ; attempts = 0 ; attlimit = 25 * numnetsG ; segment = ( SEGBOXPTR *)Ysafe_malloc( ( Max_numPinsG + 1 ) * sizeof( SEGBOXPTR ) ) ; while( ++attempts < attlimit ) { if( attempts % 1000 == 0 ) { printf(" tracks = %3d at attempts = %5d\n" ,tracksG ,attempts ) ; } do { net = (INT) ( (DOUBLE) numnetsG * ( (DOUBLE) RAND / (DOUBLE) 0x7fffffff ) ) + 1 ; } while( net == numnetsG + 1 ) ; number = 0 ; for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ process_cross( segptr , 1 ) ; if( segptr->switchvalue != nswLINE ) { segment[ ++number ] = segptr ; } } maxtrys = 4 * number ; trys = 0 ; while( ++trys <= maxtrys ) { do { pick = (INT) ( (DOUBLE) number * ( (DOUBLE) RAND / (DOUBLE) 0x7fffffff ) ) + 1 ; } while( pick == number + 1 ) ; segptr = segment[ pick ] ; netptr1 = segptr->pin1ptr ; netptr2 = segptr->pin2ptr ; if( segptr->switchvalue == swUP ) { channel = netptr1->row + 1 ; } else { channel = netptr2->row ; } x1 = netptr1->xpos ; x2 = netptr2->xpos ; found = NO ; for( denptr = DboxHeadG[ channel ][ maxTrackG[channel] ]->next ; denptr != DENSENULL ; denptr = denptr->next ) { x = denptr->grdptr->netptr->xpos ; if( x1 <= x && x2 >= x ) { found = YES ; break ; } } if( !found ) { continue ; } if( urcost( segptr ) ) { flips++ ; } } for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ process_cross( segptr , 0 ) ; } } Ysafe_free( segment ); fprintf(fpoG,"no. of accepted flips: %d\n", flips ) ; fprintf(fpoG,"no. of attempted flips: %d\n", attempts ) ; fprintf(fpoG,"THIS IS THE NUMBER OF TRACKS: %d\n\n\n" , tracksG ) ; fflush(fpoG); return ; } process_cross( segptr , status ) INT status ; SEGBOXPTR segptr ; { INT x1 , x2 ; PINBOXPTR pin1ptr , pin2ptr ; CHANGRDPTR ptr1 , ptr2 , ptr ; pin1ptr = segptr->pin1ptr ; pin2ptr = segptr->pin2ptr ; x1 = pin1ptr->xpos ; x2 = pin2ptr->xpos ; if( x1 == x2 ) { return ; } if( pin1ptr->row < pin2ptr->row ) { ptr1 = TgridG[ pin1ptr->terminal ]->up ; ptr2 = TgridG[ pin2ptr->terminal ]->down ; } else if( pin1ptr->row > pin2ptr->row ) { ptr1 = TgridG[ pin1ptr->terminal ]->down ; ptr2 = TgridG[ pin2ptr->terminal ]->up ; } else if( segptr->switchvalue == swUP ) { ptr1 = TgridG[ pin1ptr->terminal ]->up ; ptr2 = TgridG[ pin2ptr->terminal ]->up ; } else if( segptr->switchvalue == swDOWN ) { ptr1 = TgridG[ pin1ptr->terminal ]->down ; ptr2 = TgridG[ pin2ptr->terminal ]->down ; } else if( pin1ptr->pinloc >= NEITHER && pin2ptr->pinloc >= NEITHER ) { ptr1 = TgridG[ pin1ptr->terminal ]->up ; ptr2 = TgridG[ pin2ptr->terminal ]->up ; } else { ptr1 = TgridG[ pin1ptr->terminal ]->down ; ptr2 = TgridG[ pin2ptr->terminal ]->down ; } while( ptr1->prevgrd ) { if( ptr1->prevgrd->netptr->xpos == x1 ) { ptr1 = ptr1->prevgrd ; } else { break ; } } while( ptr2->nextgrd ) { if( ptr2->nextgrd->netptr->xpos == x2 ) { ptr2 = ptr2->nextgrd ; } else { break ; } } ptr2 = ptr2->nextgrd ; if( status == 1 ) { for( ptr = ptr1 ; ptr != ptr2 ; ptr = ptr->nextgrd ) { ptr->cross++ ; } } else { for( ptr = ptr1 ; ptr != ptr2 ; ptr = ptr->nextgrd ) { ptr->cross = 0 ; } } } graywolf-0.1.4+20170307gite1bf319/src/twsc/graphics.c000066400000000000000000000503311305746555600215010ustar00rootroot00000000000000/* * Copyright (C) 1990-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: graphics.c DESCRIPTION:graphics routines CONTENTS: DATE: Jun 14, 1990 REVISIONS: Jun 21, 1990 - added graphics abort macro. Oct 20, 1990 - fixed graphics update mode. Nov 23, 1990 - now draw rectilinear cell properly. Fri Feb 15 15:14:34 EST 1991 - added check to prevent drawing data before proper initialization. Tue Mar 19 16:25:17 CST 1991 - now output cell name during drawLabel. Thu Apr 18 01:47:00 EDT 1991 - now set graphics update to its correct state and fixed draw_single_cell_move. Tue May 7 00:09:43 EDT 1991 - added TWsetFrame initialization and draw orientation markers. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) graphics.c version 4.21 5/15/92" ; #endif #include "standard.h" #include "main.h" #include "readpar.h" #include "pads.h" #ifndef NOGRAPHICS #include #include #include #include #include #define INTRO "Welcome to TimberWolfSC" #define GRAPHICSABORT if(!(doGraphicsG)) return ; #define NETCOLOR TWRED #define PINCOLOR TWBLACK #define BLACK TWBLACK #define FCOLOR TWYELLOW #define MODE 2 #define MENUP "sc_menu" /* #define DEVELOPMENU */ /* During development use TWread_menus in place of menuS */ /* to create menu record, ie. TWread_menus(MENUP) */ #ifdef DEVELOPMENU #define MENUREAD() menuS = TWread_menus(MENUP) ; #else #define MENUREAD() #endif #include extern INT actual_feed_thru_cells_addedG ; /* ***************************************************************** */ static BOOL avoidDump = FALSE ; static BOOL drawPinS = FALSE ; /* whether or not to draw pins */ static BOOL drawLabelS = FALSE ; /* whether to draw labels or not */ static BOOL drawBlockS = TRUE ; /* whether to draw blocks or not */ static BOOL drawCellS = TRUE ; /* whether to draw stdcells or not */ static BOOL auto_drawS = TRUE ; /* whether to draw immediately after exp.*/ static BOOL updateS = TRUE ; /* normally in the update mode */ static BOOL single_cell_moveS = FALSE ; /* whether we have single cell moves */ static BOOL drawOrientS = FALSE ; /* whether to draw orientation mark */ static BOOL initS = FALSE ; /* true if all initialization complete */ static INT *heat_indexS ; /* how much the cells are moving */ static INT *heat_attemptS ; /* how many attempts during the run */ static INT heat_allocS ; /* size of temperature index array */ static INT drawNetS = 0 ; /* draw nets 0:none 1...n:net >numnets:all */ static INT pinsizeS ; /* size of the pin */ static draw_fs(); extern VOID draw_a_cell( INT ); extern INT draw_the_data() ; initGraphics( argc, argv, windowId ) INT argc ; char *argv[] ; INT windowId ; { char *host ; char *Ygetenv() ; extern INT horizontal_track_pitchG ; extern INT vertical_track_pitchG ; GRAPHICSABORT ; /* we need to find host for display */ if(!(host = Ygetenv("DISPLAY"))) { M(WARNMSG,"initGraphics","Can't get environment variable "); M(MSG,NULL, "for display. Aborting graphics...\n\n" ) ; avoidDump = TRUE ; doGraphicsG = FALSE ; return ; } MENUREAD() ; /* initialize the boolean menu entries according to current state */ /* "Graphics Update On","Graphics Update Off",1,0,8,9, is the 8 line */ menuS[7].bool_init = updateS ; if( windowId ){ /* init windows as a parasite */ if(!(TWinitParasite(argc,argv,TWnumcolors(),TWstdcolors(), FALSE,menuS, draw_the_data, windowId ))){ M(ERRMSG,"initGraphics","Aborting graphics."); doGraphicsG = FALSE ; avoidDump = TRUE ; return ; } } else { /* init window as a master */ if(!(TWinitGraphics(argc,argv,TWnumcolors(),TWstdcolors(),FALSE, menuS,draw_the_data ))){ M(ERRMSG,"initGraphics","Aborting graphics."); doGraphicsG = FALSE ; avoidDump = TRUE ; return ; } } TWsetwindow( 0, 0, 10, 10 ) ; TWsetFrame(0) ; TWdrawCell( 0, 0,0,11,11, TWBLUE, INTRO ) ; setGraphicWindow() ; TWdrawMenus() ; TWmessage("To interupt program click on top menu window") ; TWflushFrame() ; /* use TWinterupt to turn off window enter/leave lights */ TWinterupt() ; /* set the default pin size */ pinsizeS = (vertical_track_pitchG + horizontal_track_pitchG) / 4 - 1 ; pinsizeS = MAX( 1, pinsizeS ) ; } /* end initGraphics */ init_heat_index() { GRAPHICSABORT ; heat_allocS = lastpadG + 1; heat_indexS = (INT *) Ysafe_malloc( heat_allocS * sizeof(INT) ) ; heat_attemptS = (INT *) Ysafe_malloc( heat_allocS * sizeof(INT) ) ; reset_heat_index() ; initS = TRUE ; } /* end init_heat_index */ expand_heat_index() { INT oldnum, i; GRAPHICSABORT ; oldnum = heat_allocS; heat_allocS = lastpadG + actual_feed_thru_cells_addedG + 1; if (oldnum < heat_allocS) { heat_indexS = (INT *) Ysafe_realloc( heat_indexS, heat_allocS * sizeof(INT) ) ; heat_attemptS = (INT *) Ysafe_realloc( heat_attemptS, heat_allocS * sizeof(INT) ) ; for( i = oldnum; i < heat_allocS ; i++ ){ heat_indexS[i] = 0 ; heat_attemptS[i] = 0 ; } } } /* end expand_heat_index */ setGraphicWindow() { INT expand ; INT minx ; INT maxx ; INT miny ; INT maxy ; INT xc, yc ; /* cell center */ INT i ; /* counter */ CBOXPTR cptr ; /* cell record pointer */ minx = INT_MAX ; miny = INT_MAX ; maxx = INT_MIN ; maxy = INT_MIN ; /* look thru cells to find overall bounding box */ for( i = 1; i <= lastpadG ; i++ ){ cptr = carrayG[i] ; xc = cptr->cxcenter ; yc = cptr->cycenter ; if( yc == GATE_ARRAY_MAGIC_CONSTANT ){ /* don't draw these */ continue ; } minx = MIN( minx, cptr->tileptr->left + xc ) ; miny = MIN( miny, cptr->tileptr->bottom + yc ) ; maxx = MAX( maxx, cptr->tileptr->right + xc ) ; maxy = MAX( maxy, cptr->tileptr->top + yc ) ; } expand = MAX( maxy - miny, maxx - minx ) ; expand = (INT) (0.1 * (DOUBLE) expand ) ; TWsetwindow( minx - expand, miny - expand, maxx + expand, maxy + expand ) ; } /* end setGraphicWindow */ /* heart of the graphic syskem processes user input */ process_graphics() { INT x, y ; /* coordinates from pointer */ INT selection ; /* the users pick */ char *reply ; /* user reply to a querry */ BOOL ok ; /* loop until this value is true */ /* data might have changed so show user current config */ /* any function other that the draw controls need to worry about */ /* this concurrency problem - show user current config */ GRAPHICSABORT ; setGraphicWindow() ; draw_the_data() ; /* use TWcheckExposure to flush exposure events since we just */ /* drew the data */ TWcheckExposure() ; TWmessage( "TimberWolfSC is waiting for your response..." ) ; selection = CANCEL ; while( selection != CONTINUE_PGM ){ /* loop until exit */ selection = TWcheckMouse() ; switch( selection ){ case CANCEL: /* do nothing */ break ; case AUTO_REDRAW_ON: auto_drawS = TRUE ; break ; case AUTO_REDRAW_OFF: auto_drawS = FALSE ; break ; case COLORS: TWtoggleColors() ; break ; case CONTINUE_PGM: break ; case DUMP_GRAPHICS: graphics_dump() ; break ; case FULLVIEW: TWfullView() ; break ; case GRAPHICS_UPDATE_ON: updateS = TRUE ; break ; case GRAPHICS_UPDATE_OFF: updateS = FALSE ; selection = CONTINUE_PGM ; /* exit loop */ break ; case CLOSE_GRAPHICS: closegraphics() ; return ; case REDRAW: draw_the_data() ; /* use TWcheckExposure to flush exposure events since */ /* we just drew the data */ TWcheckExposure() ; break ; case TELL_POINT: TWmessage( "Pick a point" ) ; TWgetPt( &x, &y ) ; sprintf( YmsgG,"The point is (%d,%d)",x,y ) ; TWmessage( YmsgG ) ; break ; case TRANSLATE: TWtranslate() ; break ; case ZOOM: TWzoom() ; break ; case DRAW_BLOCKS: drawBlockS = TRUE ; TWmessage( "Standard cell rows will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_BLOCKS: drawBlockS = FALSE ; TWmessage( "Standard cell rows will be omitted from drawing"); TWforceRedraw() ; break ; case DRAW_STDCELLS: drawCellS = TRUE ; TWmessage( "Standard cells will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_STDCELLS: drawCellS = FALSE ; TWmessage( "Standard cells will be omitted from drawing"); TWforceRedraw() ; break ; case DRAW_LABELS: drawLabelS = TRUE ; TWmessage( "Labels will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_LABELS: drawLabelS = FALSE ; TWmessage( "Labels will be omitted from drawing" ) ; TWforceRedraw() ; break ; case DRAW_NETS: drawNetS = INT_MAX ; TWmessage( "Nets will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_NETS: drawNetS = FALSE ; TWmessage( "Nets will be omitted from drawing" ) ; TWforceRedraw() ; break ; case DRAW_PINS: drawPinS = TRUE ; TWmessage( "Pins will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_PINS: drawPinS = FALSE ; TWmessage( "Pins will be omitted from drawing" ) ; TWforceRedraw() ; break ; case DRAW_SINGLE_NET: /* get a net from the user */ ok = FALSE ; do { /* get string from user */ reply = TWgetString( "Enter net number:") ; if(!(reply)){ continue ; } drawNetS = atoi( reply ) ; if( drawNetS > 0 && drawNetS <= numnetsG ){ ok = TRUE ; TWforceRedraw() ; } else { TWmessage( "ERROR:invalid net number!" ) ; (void) sleep( (unsigned) 2 ) ; } } while ( !(ok) ) ; break ; case DRAW_SINGLE_CELL_MOVES: single_cell_moveS = TRUE ; break ; case IGNORE_SINGLE_MOVES: single_cell_moveS = FALSE ; break ; case DRAW_ORIENT: drawOrientS = TRUE ; TWmessage( "Orientation markers will be drawn" ) ; TWforceRedraw() ; break ; case IGNORE_ORIENT: drawOrientS = FALSE ; TWmessage("Orientation markers will be omitted from drawing"); TWforceRedraw() ; break ; } /*********************** end graphics SWITCH *****************/ if( auto_drawS && TWcheckExposure() ){ draw_the_data() ; } } TWmessage("Continuing - to interupt program click on top menu window") ; /* use TWinterupt to turn off window enter/leave lights */ TWinterupt() ; } /* end process_graphics */ /* the graphics program can draw the results at each desired */ /* timestep. */ INT draw_the_data() { INT i ; INT x ; INT y ; INT l, r, b, t ; INT layer ; INT last_cell ; /* end of cells to be drawn */ PINBOXPTR curPin ; char *pinname, *find_layer( /* pinname, layer */ ) ; if( avoidDump || !(doGraphicsG) || !(initS) ){ return ; } TWstartFrame() ; TWmessage( "Drawing the data...Please wait" ) ; if( drawBlockS ){ /* draw the desired standard cell rows if necessary */ for( i = 1 ; i <= numRowsG ; i++ ) { x = barrayG[i]->bxcenter ; y = barrayG[i]->bycenter ; l = x + barrayG[i]->bleft; r = x + barrayG[i]->bright; b = y + barrayG[i]->bbottom; t = y + barrayG[i]->btop; TWdrawCell( i, l,b,r,t, TWWHITE, NULL ) ; } } /* DRAW the CELLS */ if( drawCellS ){ i = 1 ; /* start with standard cells */ } else { i = numcellsG + 1 ; /* start with pads and macros */ } last_cell = lastpadG + actual_feed_thru_cells_addedG ; for( ; i <= last_cell ; i++ ) { draw_a_cell( i ) ; } /* now build net file */ /* nets are the interconnections between the cells */ if( drawNetS ){ Ymst_init( get_max_pin() ) ; for( i=1;i<=numnetsG;i++){ /* this is the single net case */ if( drawNetS <= numnetsG && i != drawNetS ){ continue ; } Ymst_clear() ; for(curPin=netarrayG[i]->pins;curPin;curPin=curPin->next){ Ymst_addpt( curPin->xpos, curPin->ypos ) ; } Ymst_draw() ; } Ymst_free() ; } /* now output pins */ /* pins are the terminal points on a net */ if( drawPinS ){ for( i = 1 ; i <= maxtermG ; i++ ) { curPin = tearrayG[i] ; if( !(curPin)){ continue ; } x = curPin->xpos ; y = curPin->ypos ; if( drawLabelS ){ pinname = find_layer( curPin->pinname, &layer ) ; TWdrawPin( curPin->net,x-pinsizeS,y-pinsizeS, x+pinsizeS,y+pinsizeS, PINCOLOR, pinname ) ; } else { TWdrawPin( curPin->net,x-pinsizeS,y-pinsizeS, x+pinsizeS,y+pinsizeS, PINCOLOR, NULL ) ; } } } /* clear wait message and FLUSH OUTPUT BUFFER */ TWmessage( NULL ) ; TWflushFrame() ; } /* end draw_the_data */ VOID draw_a_cell( cell ) INT cell ; { INT x ; INT y ; INT l, r, b, t ; INT pt ; INT color ; INT cell_temp ; /* cell temperature */ INT attempts ; CBOXPTR cptr ; PADBOXPTR padptr ; char label[LRECL] ; char *labelptr ; FLOAT acc_rate ; cptr = carrayG[cell] ; x = cptr->cxcenter ; y = cptr->cycenter ; if( y == GATE_ARRAY_MAGIC_CONSTANT ){ /* don't draw these */ return ; } /* name the cell */ /* draw cell labels if requested */ if( drawLabelS ){ sprintf(label,"C%d:%s",cell, carrayG[cell]->cname ) ; labelptr = label ; } else { labelptr = NIL(char *) ; } cell_temp = heat_indexS[cell] ; attempts = heat_attemptS[cell] ; if( attempts <= 0 ){ if( strncmp(carrayG[cell]->cname,"twfeed",6) == STRINGEQ ) { color = TWYELLOW ; } else { color = TWGREEN ; } } else { /* don't need to be very accurate here */ acc_rate = (FLOAT) cell_temp / (FLOAT) attempts ; /* now pick the color base on acceptance rate */ /* 44% + 10% error margin */ if( acc_rate > (FLOAT) 0.48 ){ color = TWRED ; } else if( acc_rate < (FLOAT) 0.40 ){ /* 44% - 10% error margin */ color = TWBLUE ; } else { /* in the 44% region */ color = TWORANGE ; } } padptr = cptr->padptr ; if( padptr && padptr->numcorners > 4 ){ /* way to draw a rectilinear cell */ TWarb_init() ; for( pt = 0; pt < padptr->numcorners; pt++ ){ /* rel position is a macro which calculates */ /* absolute pin loc - defined in relpos.h */ REL_POS( (INT) cptr->corient, l, b, /* result */ padptr->xpoints[pt], padptr->ypoints[pt], /* cell relative */ x, y ) ; /* cell center */ TWarb_addpt( l, b ) ; } TWdrawArb( cell, color, labelptr ) ; } else { l = cptr->tileptr->left ; r = cptr->tileptr->right ; b = cptr->tileptr->bottom ; t = cptr->tileptr->top ; YtranslateT( &l, &b, &r, &t, (INT) cptr->corient ) ; l += x ; r += x ; b += y ; t += y ; TWdrawCell( cell, l,b,r,t, color, labelptr ) ; } if( drawOrientS && padptr ){ draw_fs( cptr ) ; } } /* end draw a cell */ static draw_fs( cptr ) CBOXPTR cptr ; { INT x[10], y[10] ; /* only 10 points to an F */ INT l, b, r, t ; /* bounding box points */ INT xout, yout ; /* rotated points */ INT wid ; /* with of the F */ INT pt ; /* point counter */ TIBOXPTR bounptr ; /* cell's boundary */ bounptr = cptr->tileptr ; l = bounptr->left ; b = bounptr->bottom ; r = bounptr->right ; t = bounptr->top ; wid = (INT) (0.25 * (DOUBLE)( t - b ) ) ; /* now set the points */ x[0] = l ; y[0] = b ; x[1] = l ; y[1] = t ; x[2] = r ; y[2] = t ; x[3] = r ; y[3] = t - wid ; x[4] = l + wid ; y[4] = y[3] ; x[5] = x[4] ; y[5] = y[4] - wid ; x[6] = l + 2*wid ; y[6] = y[5] ; x[7] = x[6] ; y[7] = y[6] - wid ; x[8] = x[5] ; y[8] = y[7] ; x[9] = x[4] ; y[9] = b ; TWarb_init() ; for( pt = 0; pt <= 9; pt++ ){ /* rel position is a macro which calculates */ /* absolute pin loc - defined in relpos.h */ REL_POS( (INT) cptr->corient, xout, yout, /* result */ x[pt], y[pt], /* cell relative */ cptr->cxcenter, cptr->cycenter ) ; /* cell center */ TWarb_addpt( xout, yout ) ; } TWdrawArb( 0, FCOLOR, NIL(char *) ) ; } /* end draw_fs */ erase_a_cell( cell, x, y ) INT cell ; INT x, y ; { INT i, j ; INT l, r, b, t ; INT block ; INT lobin, hibin ; INT *cells_in_bins ; CBOXPTR cptr ; GRAPHICSABORT ; if( !(binptrG) || !(single_cell_moveS) || !(updateS) ){ /* won't work if binptr is not valid */ return ; } cptr = carrayG[cell] ; l = x + cptr->tileptr->left ; r = x + cptr->tileptr->right ; b = y + cptr->tileptr->bottom ; t = y + cptr->tileptr->top ; TWdrawCell( cell, l,b,r,t, TWWHITE, NULL ) ; /* now find the bins that it overlaps and redraw all the cells */ /* in these bins */ lobin = SetBin( l ) ; hibin = SetBin( r ) ; block = cptr->cblock ; for( i = lobin; i <= hibin ; i++ ){ cells_in_bins = binptrG[block][i]->cell ; for( j = 1 ; j <= *cells_in_bins ; j++ ) { draw_a_cell( cells_in_bins[j] ) ; } } } /* end draw a cell */ /* dumps the data to a file for future study */ graphics_dump() { /* now change mode to dump to file */ TWsetMode(1) ; /* dump the data to a file now instead of screen */ draw_the_data() ; /* restore the state to previous condition and set draw to screen */ TWsetMode(0) ; } /* see if uses wishes an interupt otherwise just draw the data */ check_graphics( drawFlag ) BOOL drawFlag ; { if( doGraphicsG ){ if( TWinterupt() ){ process_graphics() ; } else if( drawFlag && updateS ){ setGraphicWindow() ; draw_the_data() ; } } } /* end check_graphics */ graphics_cell_update( cell ) INT cell ; { GRAPHICSABORT ; if( !(single_cell_moveS) || !(updateS) ){ return ; } ASSERTNRETURN( cell > 0 && cell < heat_allocS, "graphics_cell_update", "cell out of bounds\n" ) ; heat_indexS[cell]++ ; heat_attemptS[cell]++ ; draw_a_cell( cell ) ; } /* end graphics_cell_update */ graphics_cell_attempt( cell ) INT cell ; { GRAPHICSABORT ; ASSERTNRETURN( cell > 0 && cell < heat_allocS, "graphics_cell_update", "cell out of bounds\n" ) ; heat_attemptS[cell]++ ; } /* end graphics_cell_attempt */ reset_heat_index() { INT i ; /* counter */ GRAPHICSABORT ; for( i = 0; i < heat_allocS ; i++ ){ heat_indexS[i] = 0 ; heat_attemptS[i] = 0 ; } } /* end reset_heat_index */ set_update( flag ) BOOL flag ; { updateS = flag ; } /* end set_update */ #endif /* NOGRAPHICS */ /* close graphics window on fault */ closegraphics( ) { if( doGraphicsG ){ G( TWcloseGraphics() ) ; doGraphicsG = FALSE ; } } /* end closegraphics */ graywolf-0.1.4+20170307gite1bf319/src/twsc/groute.h000066400000000000000000000062761305746555600212240ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) groute.h (Yale) version 4.7 3/23/92" FILE: globe.h DESCRIPTION:global routing definitions and typedefs. CONTENTS: DATE: Mar 27, 1989 REVISIONS: Fri Jan 25 23:47:24 PST 1991 - removed redundant variables. Fri Mar 22 15:16:41 CST 1991 - changed SHORT to INT since it wasn't saving space and could be a problem for large designs. ----------------------------------------------------------------- */ #ifndef GLOBE_H #define GLOBE_H #ifdef GLOBE_VARS #define EXTERN #else #define EXTERN extern #endif #ifdef INFINITY #undef INFINITY #endif #define INFINITY 0x7fffffff #define LEFT -1 #define RIGHT 1 #define OLD 0 #define NEW 1 #define swLINE 1 #define nswLINE 2 #define swL_up 3 #define swL_down 4 #define VERTICAL 6 #define HORIZONTAL 7 #define swUP 8 #define swDOWN 9 typedef struct changrdbox { PINBOXPTR netptr ; SHORT cross ; SHORT tracks ; struct changrdbox *prevgrd ; struct changrdbox *nextgrd ; struct densitybox *dptr ; } *CHANGRDPTR , CHANGRDBOX ; typedef struct tgridbox { CHANGRDPTR up ; CHANGRDPTR down ; } *TGRIDPTR , TGRIDBOX ; typedef struct densitybox { CHANGRDPTR grdptr ; struct densitybox *next ; struct densitybox *back ; } *DENSITYPTR , DENSITYBOX ; typedef struct segm_box { SHORT flag ; UNSIGNED_INT switchvalue : 8 ; UNSIGNED_INT swap_flag : 8 ; PINBOXPTR pin1ptr ; PINBOXPTR pin2ptr ; struct segm_box *next ; struct segm_box *prev ; } *SEGBOXPTR , SEGBOX ; typedef struct adjacent_seg { struct adjacent_seg *next ; struct segm_box *segptr ; } *ADJASEGPTR , ADJASEG ; typedef struct imp_box { char *pinname ; char *eqpinname ; INT txpos ; struct imp_box *next ; struct imp_box *prev ; INT cell ; INT xpos ; INT terminal ; } IPBOX , *IPBOXPTR ; typedef struct feedcountbox { SHORT needed ; SHORT actual ; struct imp_box *firstimp ; struct imp_box *lastimp ; } FEED_DBOX , *FEED_DATA ; #define GRDNULL ( ( CHANGRDPTR ) NULL ) #define DENSENULL ( ( DENSITYPTR ) NULL ) EXTERN CHANGRDPTR *BeginG ; EXTERN CHANGRDPTR *EndG ; EXTERN DENSITYPTR **DenseboxG ; EXTERN DENSITYPTR **DboxHeadG ; EXTERN TGRIDPTR *TgridG ; EXTERN SEGBOXPTR *netsegHeadG ; EXTERN SEGBOXPTR *netsegTailG ; EXTERN DOUBLE mean_widthG ; EXTERN INT **pairArrayG ; EXTERN INT numnetsG ; EXTERN INT numSegsG ; EXTERN INT numSwSegsG ; EXTERN INT tracksG ; EXTERN INT *maxTrackG ; EXTERN INT *nmaxTrackG ; EXTERN INT max_tdensityG ; EXTERN INT gxstartG ; EXTERN INT gxstopG ; EXTERN INT blkleftG , blkriteG ; EXTERN INT gtopChanG , gbotChanG ; EXTERN INT uneven_cell_heightG ; EXTERN INT ffeedsG , track_pitchG ; EXTERN INT fdthrusG ; EXTERN INT chan_node_noG ; EXTERN INT enough_built_in_feedG ; EXTERN INT *FeedInRowG ; EXTERN INT blk_most_leftG ; EXTERN INT blk_most_riteG ; EXTERN INT *row_rite_classG ; EXTERN INT *right_most_in_classG ; EXTERN INT hznode_sepG ; EXTERN INT add_Lcorner_feedG ; EXTERN INT average_feed_sepG ; EXTERN INT average_pin_sepG ; EXTERN PINBOXPTR *steinerHeadG ; EXTERN FEED_DATA **feedpptrG ; EXTERN IPBOXPTR *impFeedsG ; #undef EXTERN #endif /* GLOBE_H */ graywolf-0.1.4+20170307gite1bf319/src/twsc/main.c000066400000000000000000000650151305746555600206320ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * Copyright (C) 2014 Ruben Undheim * Copyright (C) 2015 Staf Verhaegen * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: main.c DESCRIPTION:TimberWolfSC's main function. CONTENTS: main( argc , argv ) INT argc ; char *argv[] ; initialize_global_router1() initialize_global_router() execute_global_router() init_utemp() install_swap_pass_thrus( netptr ) PINBOXPTR netptr ; incorporate_ECOs() DATE: Mar 27, 1989 REVISIONS: Oct 20, 1990 - fixed problem with graphics close. Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. Sun Jan 20 21:47:52 PST 1991 - ported to AIX. Wed Jan 23 02:41:07 PST 1991 - output now at density if requested. Fri Jan 25 23:48:09 PST 1991 - avoid crashing if empty rows exist. Fri Feb 15 15:15:52 EST 1991 - place pads here so that initialize_global_router1 save correct state. Thu Mar 7 01:53:39 EST 1991 - now call SGGR automatically. Tue Mar 12 17:10:47 CST 1991 - fixed DN10000 warnings. Fri Mar 15 00:39:41 CST 1991 - now pick best global route based on area. Thu Apr 18 01:48:52 EDT 1991 - now output feed percentage so user can use this in the next run. Wed Jun 5 16:37:52 CDT 1991 - during global routing maintain side. Thu Aug 1 16:12:05 CDT 1991 - now save orient correctly during global routing. Thu Aug 22 22:12:58 CDT 1991 - now let gate_array mode run both row evenning and not. Fri Sep 6 15:14:47 CDT 1991 - fixed graphics calls to make it less confusing to user. Thu Sep 19 14:15:51 EDT 1991 - added equal width cell capability. Fri Sep 27 20:54:48 EDT 1991 - fixed ECO problem. Thu Nov 7 23:03:57 EST 1991 - fixed problem with picking best global route criteria and added new row evener. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) main.c (Yale) version 4.38 5/15/92" ; #endif #define MAIN_VARS #include "standard.h" #include "main.h" #include "groute.h" #include "readpar.h" #include "parser.h" #include "feeds.h" #include "pads.h" #include #include #include #include #include "config-build.h" #define EXPECTEDMEMORY (512 * 1024) /* global variables definitions */ INT row_extentG ; INT **bin_configG ; INT left_row_boundaryG ; INT save_abs_min_flagG ; INT actual_feed_thru_cells_addedG = 0 ; BOOL orientation_optimizationG = FALSE ; /* global variable references */ extern BOOL do_fast_globalG ; extern BOOL no_row_lengthsG ; extern BOOL do_not_even_rowsG ; extern BOOL ignore_crossbusesG ; extern BOOL output_at_densityG ; extern BOOL absolute_minimum_feedsG ; extern BOOL glob_route_only_crit_netsG ; extern BOOL vertical_track_on_cell_edgeG ; extern BOOL route_padnets_outsideG ; extern BOOL call_row_evenerG ; extern BOOL placement_improveG ; extern BOOL ignore_feedsG ; extern INT ECOs_existG ; extern INT spacer_widthG ; extern INT longest_row_lengthG ; extern INT largest_delta_row_lenG ; extern INT total_row_lengthG ; /* static variables */ static INT routing_loopS ; static INT *save_cell_xS ; static INT *save_cell_yS ; static INT *save_cell_bS ; static INT *save_cell_cS ; static INT *save_desireS ; static INT *save_orientS ; static INT *save_orig_desireS ; static char *twdirS ; static INT num_feeds_addedS ;/* number of feeds added on best iteration */ static DOUBLE ave_row_sepS ; /* the row separation for a run */ main( argc , argv ) INT argc ; char *argv[] ; { FILE *fp ; DOUBLE quality_value(); char filename[LRECL] ; INT ll, rr, bb, tt ; INT bdxlen , bdylen ; INT block ; INT yaleIntro() ; INT cx, cy, cl, cr, cb, ct, cell ; char *ptr ; char *Ystrclone() ; BOOL debug ; BOOL parasite ; BOOL windowId ; BOOL verbose ; INT arg_count ; char *Ygetenv() ; /* ********************** start initialization *********************** */ /* start up cleanup handler */ YINITCLEANUP( argv[0], NULL, MAYBEDUMP ) ; Yinit_memsize( EXPECTEDMEMORY ) ; USER_INITIALIZATION() ; if( argc < 2 || argc > 4 ){ syntax() ; } else { debug = FALSE ; parasite = FALSE ; verbose = FALSE ; #ifndef NOGRAPHICS windowId = 0 ; doGraphicsG = TRUE ; #else /* NOGRAPHICS case */ doGraphicsG = FALSE ; #endif /* NOGRAPHICS */ arg_count = 1 ; if( *argv[1] == '-' ){ for( ptr = ++argv[1]; *ptr; ptr++ ){ switch( *ptr ){ case 'd': debug = TRUE ; break ; case 'n': doGraphicsG = FALSE ; break ; case 'v': verbose = TRUE ; break ; case 'w': parasite = TRUE ; break ; default: sprintf( YmsgG,"Unknown option:%c\n", *ptr ) ; M(ERRMSG,"main",YmsgG); syntax() ; } } YdebugMemory( debug ) ; cktNameG = Ystrclone( argv[++arg_count] ); /* now tell the user what he picked */ M(MSG,NULL,"\n\nTimberWolfSC switches:\n" ) ; if( debug ){ YsetDebug( TRUE ) ; M(MSG,NULL,"\tdebug on\n" ) ; } if( doGraphicsG ){ M(MSG,NULL,"\tGraphics mode on\n" ) ; } else { M(MSG,NULL,"\tGraphics mode off\n" ) ; } if( parasite ){ M(MSG,NULL,"\tTimberWolfSC will inherit window\n" ) ; /* look for windowid */ if(argc != 4){ M(ERRMSG,"main","Need to specify windowID\n" ) ; syntax() ; } else { G( windowId = atoi( argv[++arg_count] ) ) ; } } if( verbose ){ M(MSG,NULL,"\tVerbose mode on\n" ) ; Ymessage_mode( M_VERBOSE ) ; } M(MSG,NULL,"\n" ) ; } else if( argc == 2 ){ /* order is important here */ YdebugMemory( FALSE ) ; cktNameG = Ystrclone( argv[1] ); } else { syntax() ; } } sprintf( filename , "%s.out" , cktNameG ) ; fpoG = TWOPEN( filename, "w", ABORT ) ; Ymessage_init( fpoG ) ; /* send all the messages to a file normally */ YinitProgram( "TimberWolfSC", "v6.0", yaleIntro ); /* ********************** end initialization ************************* */ readParFile(); /* check to see if twdir is set so we can run SGGR */ if( SGGRG ){ if( !(twdirS = TWFLOWDIR)){ M( ERRMSG,main,"TWDIR environment variable not set.\n"); M( ERRMSG,NULL,"Please set it to TimberWolf root directory\n"); M( ERRMSG,NULL,"SGGR cannot automatically be run after annealing\n"); } } G( initGraphics( argc, argv, windowId ) ) ; Yset_random_seed( (INT) randomSeedG ) ; fprintf( fpoG, "\nThe random number generator seed is: %u\n\n\n", randomSeedG ) ; /* get a pointer to blockfile */ sprintf( filename , "%s.blk" , cktNameG ) ; fp = TWOPEN( filename , "r" , ABORT ) ; readblck( fp ) ; TWCLOSE( fp ) ; maxCellOG = 0 ; for( block = 1 ; block <= numRowsG ; block++ ) { if( barrayG[block]->borient == 2 ) { maxCellOG = 1 ; break ; } } if( rowsG > 0 ) { sprintf( filename , "%s.scel" , cktNameG ) ; } else { sprintf( filename , "%s.cel" , cktNameG ) ; } /* avoid crashes later on */ if( spacer_widthG == -1 && (rowsG > 0 || gate_arrayG) ){ M( ERRMSG, "main", "Neither spacer width nor feedthru width was specified in .par file\n" ) ; M( ERRMSG, NULL, "FATAL:must exit\n\n" ) ; } fp = TWOPEN( filename , "r" , ABORT ) ; readcell( fp ) ; TWCLOSE( fp ) ; /* get a pointer to the netlist input file */ sprintf( filename , "%s.net" , cktNameG ) ; fp = TWOPEN( filename , "r", NOABORT ) ; readnets( fp ) ; if( fp ) { TWCLOSE( fp ) ; } if ( Equal_Width_CellsG && file_conversionG ) { closegraphics() ; calc_cells_width(); fprintf(stderr,"\n***************************************************"); fprintf(stderr,"\nThe file stdcell.comp has the converted equal cells"); fprintf(stderr,"\n***************************************************"); fprintf(stderr,"\n\n"); YexitPgm(PGMOK); } iterationG = 0 ; tt = INT_MIN ; bb = INT_MAX ; rr = INT_MIN ; ll = INT_MAX ; for( block = 1 ; block <= numRowsG ; block++ ) { cx = barrayG[block]->bxcenter ; cy = barrayG[block]->bycenter ; cl = barrayG[block]->bleft; cr = barrayG[block]->bright; cb = barrayG[block]->bbottom; ct = barrayG[block]->btop; if( cx + cr > rr ) { rr = cx + cr ; } if( cx + cl < ll ) { ll = cx + cl ; } if( cy + ct > tt ) { tt = cy + ct ; } if( cy + cb < bb ) { bb = cy + cb ; } } blkxspanG = rr - ll ; blkyspanG = tt - bb ; left_row_boundaryG = ll ; row_extentG = rr - ll ; fprintf(fpoG,"block x-span:%d block y-span:%d\n",blkxspanG,blkyspanG); for( cell = 1 ; cell <= lastpadG ; cell++ ) { if( cell > numcellsG - extra_cellsG && cell <= numcellsG ) { continue ; } cx = carrayG[cell]->cxcenter ; cy = carrayG[cell]->cycenter ; cl = carrayG[cell]->tileptr->left; cr = carrayG[cell]->tileptr->right; cb = carrayG[cell]->tileptr->bottom; ct = carrayG[cell]->tileptr->top; if( cx + cr > rr ) { rr = cx + cr ; } if( cx + cl < ll ) { ll = cx + cl ; } if( cy + ct > tt ) { tt = cy + ct ; } if( cy + cb < bb ) { bb = cy + cb ; } } bdxlen = rr - ll ; bdylen = tt - bb ; lrtxspanG = rr ; lrtyspanG = tt ; if( Equal_Width_CellsG ) { binpenConG = 0 ; roLenConG = 0 ; } else { binpenConG = 1.0 ; roLenConG = 6.0 ; } calc_init_timeFactor() ; fprintf(fpoG,"Using default value of bin.penalty.control:%f\n", binpenConG ) ; pairArrayG = NULL ; funccostG = findcost() ; fprintf( fpoG , "bdxlen:%d bdylen:%d\n", bdxlen , bdylen ) ; fprintf( fpoG , "l:%d t:%d r:%d b:%d\n", ll , tt , rr , bb ) ; fprintf( fpoG, "\n\n\nTHIS IS THE ROUTE COST OF THE "); fprintf( fpoG, "CURRENT PLACEMENT: %d\n" , funccostG ) ; fprintf( fpoG, "\n\n\nTHIS IS THE PENALTY OF THE ") ; fprintf( fpoG , "CURRENT PLACEMENT: %d\n" , penaltyG ) ; fflush( fpoG ) ; if( intelG && !ignore_crossbusesG ) { handle_crossbuses() ; } G( init_heat_index() ) ; G( check_graphics(TRUE) ) ; fflush(fpoG); fflush(stdout); if( orientation_optimizationG ) { costonlyG = FALSE ; } if( ECOs_existG ) { costonlyG = TRUE ; printf("ECOs are being incorporated as requested\n"); fprintf(fpoG,"ECOs are being incorporated as requested\n"); incorporate_ECOs() ; } if( costonlyG ) { orientation_optimizationG = TRUE ; utemp() ; } else { init_utemp() ; utemp() ; } fprintf( fpoG , "\nStatistics:\n"); fprintf( fpoG , "Number of Cells: %d\n", numcellsG ); fprintf( fpoG , "Number of Pads: %d \n", numtermsG - numpadgrpsG ); fprintf( fpoG , "Number of Nets: %d \n", numnetsG ) ; fprintf( fpoG , "Number of Pins: %d \n", maxtermG ) ; fprintf( fpoG , "Number of PadGroups: %d \n", numpadgrpsG ); fprintf( fpoG , "Number of Implicit Feed Thrus: %d\n", implicit_feed_countG++ ) ; fprintf( fpoG , "Number of Feed Thrus Added: %d\n", num_feeds_addedS ) ; fprintf( fpoG , "Feed Percentage: %4.2f%%\n", 100.0 * (DOUBLE) (num_feeds_addedS * fdWidthG) / (DOUBLE) total_row_lengthG ) ; fprintf( fpoG , "Average Row Separation: %4.2f\n", ave_row_sepS ) ; if( intelG ) { fprintf( fpoG , "Checking violations at the end\n"); check_violations() ; } Yprint_stats(fpoG); /* TWCLOSE(fpoG) ; */ /* Handled by Ymessage_close() in YexitPgm() */ closegraphics() ; YexitPgm(PGMOK); } /* end main */ initialize_global_router1() { INT cell , row ; save_cell_xS = (INT *) Ysafe_malloc( (1 + numcellsG + numtermsG) * sizeof(INT)); save_cell_yS = (INT *) Ysafe_malloc( (1 + numcellsG + numtermsG) * sizeof(INT)); save_cell_bS = (INT *) Ysafe_malloc( (1 + numcellsG + numtermsG) * sizeof(INT)); save_cell_cS = (INT *) Ysafe_malloc( (1 + numcellsG + numtermsG) * sizeof(INT)); save_orientS = (INT *) Ysafe_malloc( (1 + numcellsG + numtermsG) * sizeof(INT)); save_desireS = (INT *) Ysafe_malloc( (1 + numRowsG) * sizeof(INT)); save_orig_desireS = (INT *) Ysafe_malloc( (1 + numRowsG) * sizeof(INT)); for( cell = 1 ; cell <= lastpadG ; cell++ ) { save_cell_xS[cell] = carrayG[cell]->cxcenter ; save_cell_yS[cell] = carrayG[cell]->cycenter ; save_cell_bS[cell] = carrayG[cell]->cblock ; save_cell_cS[cell] = carrayG[cell]->cclass ; save_orientS[cell] = carrayG[cell]->corient ; } for( row = 1 ; row <= numRowsG ; row++ ) { save_desireS[row] = barrayG[row]->desire ; save_orig_desireS[row] = barrayG[row]->orig_desire ; } return ; } initialize_global_router() { CBOXPTR ptr ; PINBOXPTR pinptr, pin, cnetptr , netptr ; INT cell , row , net ; BOOL coreConnection ; rebuild_nextpin() ; insert_row(0) ; for( cell = 1 ; cell <= lastpadG; cell++ ) { carrayG[cell]->cxcenter = save_cell_xS[cell] ; row = carrayG[cell]->cblock = save_cell_bS[cell] ; if( row != 0 ){ carrayG[cell]->cycenter = barrayG[row]->bycenter ; } else { carrayG[cell]->cycenter = save_cell_yS[cell] ; } carrayG[cell]->cclass = save_cell_cS[cell] ; carrayG[cell]->corient = (char) save_orientS[cell] ; } for( cell = 1 ; cell <= lastpadG ; cell++ ) { ptr = carrayG[cell] ; if( cell > numcellsG ) { for( pinptr = ptr->pins; pinptr ; pinptr = pinptr->nextpin ) { if( route_padnets_outsideG ){ /* look at each net on the pads to see if it has a */ /* connection in the core */ coreConnection = FALSE ; for( pin = netarrayG[pinptr->net]->pins; pin; pin = pin->next ){ if( pin->cell <= numcellsG ){ coreConnection = TRUE ; break ; } } if(!(coreConnection )){ /* no connection to the core we can route this in */ /* the top channel */ pinptr->row = numRowsG + 1 ; pinptr->pinloc = BOTCELL ; /* now go on to the next pin */ continue ; } } /* set the pinlocation for the pads and macros */ if( ptr->padptr->padside ) { if( pinptr->row > numRowsG ) { pinptr->pinloc = BOTCELL ; } else { pinptr->pinloc = TOPCELL ; } } } } else { for( pinptr = ptr->pins; pinptr ; pinptr = pinptr->nextpin ) { if( pinptr->typos[(ptr->corient)%2] > 0 ) { pinptr->pinloc = TOPCELL ; } else if(pinptr->typos[(ptr->corient)%2] < 0 ){ pinptr->pinloc = BOTCELL ; } else { pinptr->pinloc = NEITHER ; } } } } for( row = 1 ; row <= numRowsG ; row++ ) { barrayG[row]->desire = save_desireS[row] ; barrayG[row]->orig_desire = save_orig_desireS[row] ; } no_row_lengthsG = 1 ; findunlap(0) ; no_row_lengthsG = 0 ; return ; } execute_global_router() { PINBOXPTR netptr ; INT i , j, row ; INT loop_boundary ; INT temp ; INT core_height ; INT core_width ; INT total_row_height ; INT best_tracks ; DOUBLE area ; DOUBLE best_area ; BOOL decision ; char command[LRECL] ; if( gate_arrayG && vertical_track_on_cell_edgeG ) { findunlap(0) ; fprintf(fpoG,"Removed %d redundant implicit feeds\n", rm_overlapping_feeds() ) ; } loop_boundary = 4 ; routing_loopS = 8 ; /* added by Carl 24 Jan 91 */ total_row_height = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { if( pairArrayG[row][0] < 1 ) { fprintf(fpoG,"Trying to fix empty row problem ...") ; printf("Trying to fix empty row problem ...") ; fflush(fpoG); fflush(stdout); even_the_rows(0,FALSE) ; if( pairArrayG[row][0] < 1 ) { /* take even more drastic measures */ even_the_rows(0,TRUE) ; } for( row = 1 ; row <= numRowsG ; row++ ) { if( pairArrayG[row][0] < 1 ) { fprintf(fpoG,"Global router cannot handle a row without cells\n"); printf("Global router cannot handle a row without cells\n"); YexitPgm(PGMFAIL); } } fprintf(fpoG," fixed\n"); printf(" fixed\n"); fflush(fpoG); fflush(stdout); break ; } /* accumulate the total row height */ total_row_height += barrayG[row]->btop - barrayG[row]->bbottom ; } /* end */ if( swap_netG > 0 ) { /* there are TW_PASS_THRU pins on a swap-able gate */ /* we must add them to the implicit list on the relevant cell */ netptr = netarrayG[swap_netG]->pins ; for( ; netptr ; netptr = netptr->next ) { install_swap_pass_thrus( netptr ) ; } netarrayG[swap_netG]->ignore = -1 ; } if( glob_route_only_crit_netsG ) { route_only_critical_nets() ; } else { elim_nets(1) ; /* nets which are NOT to be global routed */ } actual_feed_thru_cells_addedG = 0 ; initialize_global_router1() ; if( SGGRG ) { initialize_global_router() ; coarseglb() ; /* this function returns "early" if SGGR */ /* now place pads for the final time using real cell positions for core */ /* boundary to insure we don't have overlap */ setVirtualCore( TRUE ) ; placepads() ; output() ; fprintf(fpoG,"\nTimberWolfSC placement is complete; Now ready for execution of SGGR\n"); Yprint_stats(fpoG); closegraphics() ; if( twdirS ){ Ymessage_mode( M_VERBOSE ) ; M( MSG, NULL, "\n\nPlacement phase complete...\n\n" ) ; M( MSG, NULL, "\n\nNow calling SGGR...\n\n" ) ; TWCLOSE(fpoG) ; sprintf( command, "%s/bin/SGGR %s", twdirS, cktNameG ) ; Ysystem( "SGGR", ABORT, command, NULL ) ; } else TWCLOSE(fpoG) ; YexitPgm(PGMOK); } best_area = DBL_MAX ; USER_NEXT_METER() ; USER_SEND_VALUE( routing_loopS ) ; save_abs_min_flagG = absolute_minimum_feedsG ; /* now place pads using real cell positions for core */ /* boundary to insure we don't have overlap */ setVirtualCore( TRUE ) ; placepads() ; /* draw the data */ G( check_graphics(TRUE) ) ; if( !(placement_improveG )){ /* limit the number of cases since we won't move cells */ routing_loopS = 4 ; call_row_evenerG = FALSE ; } /* from here on, the pad side must be retained during global routing */ placepads_retain_side( TRUE ) ; for( j = 1 ; j <= routing_loopS ; j++ ) { if( j == routing_loopS || j == loop_boundary ) { absolute_minimum_feedsG = TRUE ; } else { absolute_minimum_feedsG = save_abs_min_flagG ; } if( j <= loop_boundary ) { if( call_row_evenerG ){ do_not_even_rowsG = FALSE ; fprintf(fpoG,"TimberWolfSC did call even_the_rows()\n"); } else { do_not_even_rowsG = TRUE ; fprintf(fpoG,"TimberWolfSC did NOT call even_the_rows()\n"); } } else { do_not_even_rowsG = FALSE ; fprintf(fpoG,"TimberWolfSC did call even_the_rows()\n"); } if( absolute_minimum_feedsG ) { fprintf(fpoG,"TimberWolfSC using absolute_minimum_feeds\n"); } tracksG = 0 ; initialize_global_router() ; coarseglb() ; if( globe() == 0 ) { fprintf(fpoG,"WARNING: refine_fixed_placement failed\n"); printf("WARNING: refine_fixed_placement failed\n"); fflush(fpoG); fflush(stdout); USER_INCR_METER() ; continue ; } if( output_at_densityG ){ density() ; } placepads() ; /* draw the data */ G( check_graphics(TRUE) ) ; core_width = barrayG[1]->desire ; for( row = 2 ; row <= numRowsG ; row++ ) { if( core_width < barrayG[row]->desire ) { core_width = barrayG[row]->desire ; } } core_width += largest_delta_row_lenG ; core_height = tracksG * track_pitchG + total_row_height ; area = (DOUBLE) core_height * (DOUBLE) core_width ; if( area < best_area ){ best_area = area ; decision = TRUE ; best_tracks = tracksG ; } else { decision = FALSE ; } if( decision ) { fprintf(fpoG,"THIS G. ROUTING IS BEING SAVED AS BEST SO FAR\n"); fprintf(fpoG,"\nFINAL NUMBER OF ROUTING TRACKS: %d\n\n", tracksG); for( i = 1 ; i <= numChansG ; i++ ) { fprintf(fpoG,"MAX OF CHANNEL:%3d is: %3d\n", i , maxTrackG[i]); } outpins() ; output() ; print_paths() ; best_tracks = tracksG ; /* save this for final statistics */ num_feeds_addedS = actual_feed_thru_cells_addedG ; /* save the effective row separation */ ave_row_sepS = (DOUBLE) (tracksG * track_pitchG) / (DOUBLE) total_row_height ; } globe_free_up() ; final_free_up() ; USER_INCR_METER() ; } fprintf(fpoG,"\n\n***********************************************\n"); fprintf(fpoG,"*ACTUAL* FINAL NUMBER OF ROUTING TRACKS: %d\n", best_tracks); fprintf(fpoG,"***********************************************\n\n"); fflush(fpoG); fprintf(stdout,"\n\n***********************************************\n"); fprintf(stdout,"*ACTUAL* FINAL NUMBER OF ROUTING TRACKS: %d\n", best_tracks); fprintf(stdout,"***********************************************\n\n"); fflush(stdout); return ; } init_utemp() { INT row , bin ; bin_configG = (INT **) Ysafe_malloc( (1 + numRowsG) * sizeof(INT *) ) ; for( row = 1 ; row <= numRowsG ; row++ ) { bin_configG[row] = (INT *) Ysafe_malloc( (1 + numBinsG) * sizeof(INT) ); for( bin = 0 ; bin <= numBinsG ; bin++ ) { bin_configG[row][bin] = 0 ; } } return ; } install_swap_pass_thrus( netptr ) PINBOXPTR netptr ; { CBOXPTR ptr ; IPBOXPTR imptr ; PINBOXPTR termptr ; INT impxpos , impypos , cell ; char *pname ; /* code borrowed from readcell() */ /* fscanf( fp , " %d %d " , &impxpos , &impypos ) ; */ /* impxpos and impypos are rel. to cell center -- to get these we need to find the relevant pin on the cell */ cell = netptr->cell ; ptr = carrayG[cell] ; for( termptr = ptr->pins ;termptr ; termptr = termptr->nextpin ) { if( termptr == netptr ) { impxpos = termptr->txpos[0] ; impypos = termptr->typos[0] ; fprintf(fpoG,"FOUND the connection in install_swap...\n"); break ; } } imptr = ( IPBOXPTR )Ysafe_malloc( sizeof( IPBOX ) ) ; imptr->pinname = (char *) Ysafe_malloc( (strlen( netptr->pinname ) + 1 ) * sizeof( char ) ) ; imptr->eqpinname = (char *) Ysafe_malloc( (strlen( netptr->eqptr->pinname ) + 1 ) * sizeof( char ) ) ; sprintf( imptr->pinname , "%s" , netptr->pinname ) ; sprintf( imptr->eqpinname , "%s" , netptr->eqptr->pinname ) ; imptr->txpos = impxpos ; imptr->cell = cell ; imptr->terminal = ++last_pin_numberG ; imptr->next = ptr->imptr ; ptr->imptr = imptr ; if( impypos > 0 ) { /* swap the pinnames */ pname = imptr->pinname ; imptr->pinname = imptr->eqpinname ; imptr->eqpinname = pname ; } return ; } incorporate_ECOs() { PINBOXPTR termptr , netptr ; INT *nets, xspot, yspot , i , net , cell , count, maxpins ; INT orient , row , xmin, xmax, ymin, ymax , x , y ; xspot = 0 ; yspot = 0 ; maxpins = get_max_pin() ; nets = (INT *) Ysafe_calloc( maxpins+1, sizeof(INT) ) ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { if( carrayG[cell]->ECO_flag == 1 ) { printf("ECO added cell being processed: <%s> ", carrayG[cell]->cname ) ; fprintf(fpoG,"ECO added cell being processed: <%s> ", carrayG[cell]->cname ) ; termptr = carrayG[cell]->pins ; for( ; termptr ; termptr = termptr->nextpin ) { net = termptr->net ; for( i = 0 ; nets[i] != 0 ; i++ ) { if( nets[i] == net ) { break ; } } if( nets[i] == 0 ) { nets[i] = net ; } } /* nets[] is the list of unique nets for the cell */ count = 0 ; for( i = 0 ; nets[i] != 0 ; i++ ) { /* compute bounding boxes of the unique nets, taking care to ignore ECO_added cells */ /* ************ updated on 12/21/90 by Carl */ net = nets[i] ; if( !(netptr = netarrayG[net]->pins)) { continue ; } if( carrayG[ netptr->cell ]->ECO_flag == 1 ) { /* don't let ECO added cells influence the decision */ xmin = INT_MAX ; xmax = INT_MIN ; ymin = INT_MAX ; ymax = INT_MIN ; } else { xmin = xmax = netptr->xpos ; ymin = ymax = netptr->ypos ; } count = 0 ; for( netptr = netptr->next ; netptr ; netptr = netptr->next ) { if( carrayG[ netptr->cell ]->ECO_flag == 1 ) { continue ; /* don't let ECO_added cells influence the decision */ } x = netptr->xpos ; y = netptr->ypos ; if( x < xmin ) { xmin = x ; } if( x > xmax ) { xmax = x ; } if( y < ymin ) { ymin = y ; } if( y > ymax ) { ymax = y ; } } /* ************ */ xspot += (xmax + xmin) / 2 ; yspot += (ymax + ymin) / 2 ; count++ ; } if( count >= 1 ){ xspot /= count ; yspot /= count ; } else { fprintf( stderr, "Incorrectly specified ECO cell:%s", carrayG[cell]->cname ) ; } for( row = 1 ; row <= numRowsG ; row++ ) { if( barrayG[row]->bycenter > yspot ) { break ; } } if( row > numRowsG ) { row = numRowsG ; } else if( row > 1 ) { if( barrayG[row]->bycenter - yspot > yspot - barrayG[row-1]->bycenter ) { row-- ; } } yspot = barrayG[row]->bycenter ; carrayG[cell]->cxcenter = xspot ; carrayG[cell]->cycenter = yspot ; carrayG[cell]->cblock = row ; carrayG[cell]->ECO_flag = 0 ; printf(" ... placed in row:%d x:%d\n", row , xspot ) ; fprintf(fpoG," ... placed in row:%d x:%d\n", row , xspot ) ; orient = carrayG[cell]->corient ; for( termptr = carrayG[cell]->pins ; termptr ; termptr = termptr->nextpin ) { termptr->xpos = termptr->txpos[ orient/2 ] + xspot ; termptr->ypos = termptr->typos[ orient%2 ] + yspot ; } } } return ; } /* give user correct syntax */ syntax() { M(ERRMSG,NULL,"\n" ) ; M(MSG,NULL,"Incorrect syntax. Correct syntax:\n"); sprintf( YmsgG, "\nTimberWolfSC [-dnw] designName [windowId] \n" ) ; M(MSG,NULL,YmsgG ) ; M(MSG,NULL,"\twhose options are zero or more of the following:\n"); M(MSG,NULL,"\t\td - prints debug info and performs extensive\n"); M(MSG,NULL,"\t\t error checking\n"); M(MSG,NULL,"\t\tn - no graphics - the default is to open the\n"); M(MSG,NULL,"\t\t display and output graphics to an Xwindow\n"); M(MSG,NULL,"\t\tv - verbose mode - echo output to the screen\n"); M(MSG,NULL,"\t\tw - parasite mode - user must specify windowId\n"); YexitPgm(PGMFAIL); } /* end syntax */ graywolf-0.1.4+20170307gite1bf319/src/twsc/main.h000066400000000000000000000023521305746555600206320ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) main.h (Yale) version 4.6 1/25/91" FILE: main.h DESCRIPTION:global definitions for TimberWolfSC CONTENTS: DATE: Mar 27, 1989 REVISIONS: Sun Jan 20 21:47:52 PST 1991 - ported to AIX. Fri Jan 25 23:46:21 PST 1991 - removed redundant variables. ----------------------------------------------------------------- */ #ifndef MAIN_H #define MAIN_H /* global variables defined for main */ #ifdef MAIN_VARS #define EXTERN #else #define EXTERN extern #endif EXTERN char *cktNameG ; EXTERN INT rowsG ; EXTERN INT attmaxG ; EXTERN INT maxCellOG ; EXTERN INT iterationG ; EXTERN INT blkxspanG ; EXTERN INT blkyspanG ; EXTERN INT ffeedsG ; EXTERN INT lrtxspanG ; EXTERN INT lrtyspanG ; EXTERN INT ifrangeG ; EXTERN INT *fixarrayG ; EXTERN FILE *fpoG ; EXTERN INT d_costG ; EXTERN INT resume_runG ; EXTERN INT implicit_pins_usedG ; EXTERN INT rowHeightG ; EXTERN INT fdthrusG ; EXTERN DOUBLE TG ; EXTERN DOUBLE imprangeG ; EXTERN DOUBLE rowSepG ; EXTERN INT rowSepAbsG ; EXTERN DOUBLE stopdegG ; EXTERN unsigned Yrandom_seed() ; EXTERN unsigned randomSeedG ; EXTERN unsigned randomSeed2G ; #undef EXTERN #endif /* MAIN_H */ graywolf-0.1.4+20170307gite1bf319/src/twsc/menus.h000066400000000000000000000033031305746555600210320ustar00rootroot00000000000000 /* TWmenu definitions */ #define TWNUMMENUS 23 #define CANCEL 0 #define AUTO_REDRAW_ON 1 #define AUTO_REDRAW_OFF 2 #define CLOSE_GRAPHICS 3 #define COLORS 4 #define CONTINUE_PGM 5 #define DUMP_GRAPHICS 6 #define FULLVIEW 7 #define GRAPHICS_UPDATE_ON 8 #define GRAPHICS_UPDATE_OFF 9 #define REDRAW 10 #define TELL_POINT 11 #define TRANSLATE 12 #define ZOOM 13 #define DRAW_BLOCKS 20 #define IGNORE_BLOCKS 21 #define DRAW_STDCELLS 22 #define IGNORE_STDCELLS 23 #define DRAW_LABELS 24 #define IGNORE_LABELS 25 #define DRAW_NETS 26 #define IGNORE_NETS 27 #define DRAW_ORIENT 33 #define IGNORE_ORIENT 34 #define DRAW_PINS 28 #define IGNORE_PINS 29 #define DRAW_SINGLE_NET 30 #define DRAW_SINGLE_CELL_MOVES 31 #define IGNORE_SINGLE_MOVES 32 #ifndef DEVELOPMENU static TWMENUBOX menuS[24] = { "CONTROL",0,0,1,0,0, "Auto Redraw On","Auto Redraw Off",1,0,1,2, "Close Graphics",0,0,0,3,0, "Colors",0,0,0,4,0, "Continue Pgm",0,0,0,5,0, "Dump Graphics",0,0,0,6,0, "FullView",0,0,0,7,0, "Graphics Update On","Graphics Update Off",1,0,8,9, "Redraw",0,0,0,10,0, "Tell Point",0,0,0,11,0, "Translate",0,0,0,12,0, "Zoom",0,0,0,13,0, "Cancel",0,0,0,0,0, "DRAW ",0,0,1,0,0, "Draw Blocks","Ignore Blocks",1,0,20,21, "Draw Stdcells","Ignore Stdcells",1,0,22,23, "Draw Labels","Ignore Labels",0,0,24,25, "Draw Nets","Ignore Nets",0,0,26,27, "Draw Orient","Ignore Orient",0,0,33,34, "Draw Pins","Ignore Pins",0,0,28,29, "Draw Single Net",0,0,0,30,0, "Draw Single Cell Moves","Ignore Single Moves",0,0,31,32, "Cancel",0,0,0,0,0, 0,0,0,0,0,0 } ; #else /* DEVELOPMENU */ static TWMENUBOX *menuS ; #endif /* DEVELOPMENU */ graywolf-0.1.4+20170307gite1bf319/src/twsc/mergeseg.c000066400000000000000000000242531305746555600215030ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * Copyright (C) 2015 Staf Verhaegen * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: mergeseg.c DESCRIPTION:segment code. CONTENTS: mergeseg( netptr ) NBOX *netptr ; mergedge( netptr, direction ) NBOX *netptr ; INT direction ; rplacseg( netptr, oldnode, newnode ) PINBOXPTR netptr, oldnode, newnode ; set_steiner_flag( ptr1, ptr2, ptr3 , stptr ) PINBOXPTR ptr1, ptr2, ptr3, stptr ; recheck_steiner_flag( stptr ) NBOX *stptr ; PINBOXPTR xmedianfun( aptr, bptr, cptr ) PINBOXPTR aptr, bptr, cptr ; PINBOXPTR ymedianfun( aptr, bptr, cptr ) PINBOXPTR aptr, bptr, cptr ; DATE: Mar 27, 1989 REVISIONS: Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) mergeseg.c (Yale) version 4.4 12/15/90" ; #endif #endif #include "standard.h" #include "groute.h" #define NORTH 1 #define SOUTH 2 #define WEST 3 #define EAST 4 /* global variables */ extern INT *add_st_flagG ; /* external routines */ extern INT cmpr_sx(), cmpr_lx(), cmpr_sy(), cmpr_ly() ; extern SEGBOX *makeseg() ; extern PINBOXPTR makeSTpt() , xmedianfun(), ymedianfun() ; /* static definitions */ static PINBOXPTR nthptrS[30], sthptrS[30], wstptrS[30], estptrS[30] ; static INT nthS, sthS, wstS, estS ; /*------------------------------------------------------------------* * The function mergeseg() tries to combines the edges incident * * on the same nodes in the minimum spanning trees by introducing * * new nodes. * *------------------------------------------------------------------*/ mergeseg( netptr ) PINBOXPTR netptr ; { PINBOXPTR ptr ; ADJASEG *adj ; SEGBOX *segptr ; INT x, y ; wstS = estS = nthS = sthS = 0 ; x = netptr->xpos ; y = netptr->newy ; adj = netptr->adjptr->next ; if( adj->next == NULL ) { return ; /* only one edge is incident on this node, return */ } for( ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( segptr->pin1ptr == netptr ) { ptr = segptr->pin2ptr ; } else { ptr = segptr->pin1ptr ; } if( ptr->newy < y ) { sthptrS[ ++sthS ] = ptr ; } else if( ptr->newy > y ) { nthptrS[ ++nthS ] = ptr ; } else if( ptr->xpos + average_feed_sepG <= x ) { wstptrS[ ++wstS ] = ptr ; } else if( ptr->xpos - average_feed_sepG >= x ) { estptrS[ ++estS ] = ptr ; } } mergedge( netptr, NORTH ) ; mergedge( netptr, SOUTH ) ; mergedge( netptr, WEST ) ; mergedge( netptr, EAST ) ; } mergedge( netptr, direction ) PINBOXPTR netptr ; INT direction ; { PINBOXPTR stptr, astptr, *dirptr, xmedian, ymedian ; INT i, n, (*funcptr)() ; if( direction == NORTH ) { dirptr = nthptrS ; funcptr = cmpr_sy ; n = nthS ; } else if( direction == SOUTH ) { dirptr = sthptrS ; funcptr = cmpr_ly ; n = sthS ; } else if( direction == WEST ) { dirptr = wstptrS ; funcptr = cmpr_lx ; n = wstS ; } else if( direction == EAST ) { dirptr = estptrS ; funcptr = cmpr_sx ; n = estS ; } Yquicksort( (char *)(dirptr+1), n, sizeof(PINBOXPTR), funcptr ) ; if( n == 0 ) { return ; } else if( n == 1 ) { if( direction == WEST || direction == EAST ) { return ; } if( dirptr[1]->xpos + average_feed_sepG < netptr->xpos ) { wstptrS[ ++wstS ] = dirptr[1] ; } else if( dirptr[1]->xpos - average_feed_sepG > netptr->xpos ) { estptrS[ ++estS ] = dirptr[1] ; } else { /* straight vertical segment */ return ; } } else { astptr = dirptr[n] ; for( i = n - 1 ; i >= 1 ; i-- ) { xmedian = xmedianfun( astptr, dirptr[i], netptr ) ; ymedian = ymedianfun( astptr, dirptr[i], netptr ) ; if( ABS( dirptr[i]->xpos - xmedian->xpos ) <= average_feed_sepG && dirptr[i]->newy == ymedian->newy ){ stptr = dirptr[i] ; rplacseg( astptr, netptr, dirptr[i] ) ; if( stptr->terminal == 0 && stptr->flag == 0 ) { recheck_steiner_flag( stptr ) ; } } else if( ABS( astptr->xpos - xmedian->xpos ) <= average_feed_sepG && astptr->newy == ymedian->newy ) { stptr = astptr ; rplacseg( dirptr[i], netptr, astptr ) ; if( stptr->terminal == 0 && stptr->flag == 0 ) { recheck_steiner_flag( stptr ) ; } } else { /* FIXME: Next line causes memory leaks according to valgrind; not fixed as ownerships seems not to be clear. */ stptr = makeSTpt( netptr->net, xmedian, ymedian ) ; rplacseg( astptr, netptr, stptr ) ; rplacseg( dirptr[i], netptr, stptr ) ; makeseg( netptr, stptr ) ; if( add_st_flagG[stptr->row] ) { stptr->flag = 1 ; } else { set_steiner_flag( dirptr[i], astptr, netptr,stptr ) ; } } astptr = stptr ; } if( direction == NORTH || direction == SOUTH ) { if( astptr->xpos + average_feed_sepG < netptr->xpos ) { wstptrS[ ++wstS ] = astptr ; } else if( astptr->xpos - average_feed_sepG > netptr->xpos ) { estptrS[ ++estS ] = astptr ; } } } } rplacseg( netptr, oldnode, newnode ) PINBOXPTR netptr, oldnode, newnode ; { ADJASEG *adj, *tmpadj ; SEGBOX *segptr ; for( adj = netptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( segptr->pin1ptr == oldnode ) { segptr->pin1ptr = newnode ; break ; } else if( segptr->pin2ptr == oldnode ) { segptr->pin2ptr = newnode ; break ; } } for( adj = oldnode->adjptr ; adj->next ; adj = adj->next ) { if( adj->next->segptr == segptr ) { tmpadj = adj->next ; adj->next = adj->next->next ; Ysafe_free( tmpadj ) ; break ; } } add_adj( segptr, newnode ) ; update_segment_data( segptr ) ; } set_steiner_flag( ptr1, ptr2, ptr3 , stptr ) PINBOXPTR ptr1, ptr2, ptr3, stptr ; { PINBOXPTR hiptr, loptr ; hiptr = loptr = ptr1 ; if( loptr->newy > ptr2->newy ) { loptr = ptr2 ; } if( hiptr->newy < ptr2->newy ) { hiptr = ptr2 ; } if( loptr->newy > ptr3->newy ) { loptr = ptr3 ; } if( hiptr->newy < ptr3->newy ) { hiptr = ptr3 ; } if( hiptr->row > stptr->row ) { if( stptr->row > loptr->row ) { stptr->flag = 1 ; } else { /* stptr->row == loptr->row */ if( (INT) loptr->pinloc == BOTCELL ) { stptr->flag = 1 ; } else { stptr->flag = 0 ; } } } else { /* hiptr->row == stptr->row */ if( stptr->row > loptr->row ) { if( hiptr->pinloc == TOPCELL ) { stptr->flag = 1 ; } else { stptr->flag = 0 ; } } else { /* hiptr->row == stptr->row == loptr->row */ if( hiptr->pinloc == TOPCELL && (INT) loptr->pinloc == BOTCELL ) { stptr->flag = 1 ; } else { stptr->flag = 0 ; } } } } recheck_steiner_flag( stptr ) PINBOXPTR stptr ; { ADJASEG *adj ; SEGBOX *segptr ; PINBOXPTR ptr, loptr, hiptr ; loptr = hiptr = stptr ; for( adj = stptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( segptr->pin1ptr == stptr ) { ptr = segptr->pin2ptr ; } else { ptr = segptr->pin1ptr ; } if( ptr->newy > hiptr->newy ) { hiptr = ptr ; } if( ptr->newy < loptr->newy ) { loptr = ptr ; } } if( hiptr->row > stptr->row ) { if( stptr->row > loptr->row ) { stptr->flag = 1 ; } else { /* stptr->row == loptr->row */ if( (INT) loptr->pinloc == BOTCELL ) { stptr->flag = 1 ; } } } else { /* hiptr->row == stptr->row */ if( stptr->row > loptr->row ) { if( hiptr->pinloc == TOPCELL ) { stptr->flag = 1 ; } } else { /* hiptr->row == stptr->row == loptr->row */ if( hiptr->pinloc == TOPCELL && (INT) loptr->pinloc == BOTCELL ) { stptr->flag = 1 ; } } } } PINBOXPTR xmedianfun( aptr, bptr, cptr ) PINBOXPTR aptr, bptr, cptr ; { if( aptr->xpos <= bptr->xpos && aptr->xpos <= cptr->xpos ) { if( bptr->xpos <= cptr->xpos ) { return( bptr ) ; } else { return( cptr ) ; } } else if( bptr->xpos <= aptr->xpos && bptr->xpos <= cptr->xpos ) { if( aptr->xpos <= cptr->xpos ) { return( aptr ) ; } else { return( cptr ) ; } } else { if( aptr->xpos <= bptr->xpos ) { return( aptr ) ; } else { return( bptr ) ; } } } PINBOXPTR ymedianfun( aptr, bptr, cptr ) PINBOXPTR aptr, bptr, cptr ; { if( aptr->newy <= bptr->newy && aptr->newy <= cptr->newy ) { if( bptr->newy <= cptr->newy ) { return( bptr ) ; } else { return( cptr ) ; } } else if( bptr->newy <= aptr->newy && bptr->newy <= cptr->newy ) { if( aptr->newy <= cptr->newy ) { return( aptr ) ; } else { return( cptr ) ; } } else { if( aptr->newy <= bptr->newy ) { return( aptr ) ; } else { return( bptr ) ; } } } graywolf-0.1.4+20170307gite1bf319/src/twsc/netgraph.c000066400000000000000000001011731305746555600215120ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * Copyright (C) 2015 Staf Verhaegen * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: netgraph.c DESCRIPTION:network graph code. CONTENTS: postFeedAssgn() rebuild_netgraph( net ) INT net ; remove_unnecessary_feed( net , flag ) INT net , flag ; find_set_name( v ) INT v ; do_set_union( i , j ) INT i , j ; switchable_or_not() free_z_memory() DATE: Mar 27, 1989 REVISIONS: Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. Tue Jan 15 20:30:05 PST 1991 - changed frees to Ysafe_frees. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) netgraph.c (Yale) version 4.7 1/15/91" ; #endif #endif #include "standard.h" #include "groute.h" #include "main.h" typedef struct graph_edge_cost { SHORT node1 ; SHORT node2 ; INT cost ; INT channel ; } *EDGE_COST , EDGE_COST_BOX ; /* global variable definitions */ INT *count_G = NULL; INT *father_G = NULL; INT *root_G = NULL; INT *stack_G = NULL; PINBOXPTR *vertex_G = NULL; /* global variable references */ extern INT Max_numPinsG ; /* static definitions */ static INT maxpin_numberS ; static INT *pins_at_rowS = NULL; static INT *first_indexS = NULL; static PINBOXPTR **z_S ; static EDGE_COST *edge_dataS ; netgraph_free_up() { Ysafe_free( count_G ) ; count_G = NULL ; Ysafe_free( father_G ) ; father_G = NULL ; Ysafe_free( root_G ) ; root_G = NULL; Ysafe_free( stack_G ) ; stack_G = NULL ; Ysafe_free( vertex_G ) ; vertex_G = NULL ; } postFeedAssgn() { INT net , i , row , botrow , toprow , last_i ; SEGBOXPTR segptr , nextseg ; PINBOXPTR netptr , nextptr , st_head , stptr ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = nextseg ) { nextseg = segptr->next ; Ysafe_free( segptr ) ; } netsegHeadG[net]->next = NULL ; netptr = netarrayG[net]->pins ; st_head = steinerHeadG[net] ; if( st_head->next ) { /* there are steiner point for this net */ for( stptr = st_head ; stptr->next ; ) { nextptr = stptr->next ; if( nextptr->terminal == 0 || !nextptr->flag ) { /* steiner point in bottom pads or top pads or they are pseudo steiner point. */ stptr->next = nextptr->next ; Ysafe_free( nextptr ) ; } else { stptr = nextptr ; } } stptr->next = netptr ; netarrayG[net]->pins = st_head->next ; /* put all the netbox of the steiner point into the netarrayG linked lists. */ } Ysafe_free( steinerHeadG[net] ) ; } Ysafe_free( steinerHeadG ) ; maxpin_numberS = 0 ; pins_at_rowS = (INT *)Ysafe_calloc( numChansG + 1, sizeof(INT) ) ; for( net = 1 ; net <= numnetsG ; net++ ) { if( netarrayG[net]->numpins <= 2 ) { continue ; } botrow = numChansG ; toprow = 0 ; for( netptr = netarrayG[net]->pins ; netptr ; netptr = netptr->next ) { row = netptr->row ; pins_at_rowS[ row ]++ ; if( row < botrow ) { botrow = row ; } if( row > toprow ) { toprow = row ; } } for( row = botrow ; row <= toprow ; row++ ) { if( pins_at_rowS[row] > maxpin_numberS ) { maxpin_numberS = pins_at_rowS[row] ; } pins_at_rowS[row] = 0 ; } } maxpin_numberS += 3 ; count_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; father_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; root_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; stack_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; first_indexS = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof( INT ) ) ; vertex_G = (PINBOXPTR *)Ysafe_malloc( 2 * Max_numPinsG * sizeof(PINBOXPTR) ); last_i = maxpin_numberS * maxpin_numberS * numRowsG - 1 ; edge_dataS = (EDGE_COST *)Ysafe_malloc( ( last_i + 1 ) * sizeof(EDGE_COST) ) ; for( i = 1 ; i <= last_i ; i++ ) { edge_dataS[i] = (EDGE_COST)Ysafe_malloc( sizeof(EDGE_COST_BOX) ); } z_S = (PINBOXPTR **)Ysafe_malloc( ( numChansG + 1 ) * sizeof(PINBOXPTR *) ) ; for( i = 0 ; i <= numChansG ; i++ ) { z_S[i] = (PINBOXPTR *)Ysafe_malloc( maxpin_numberS * sizeof(PINBOXPTR) ) ; } for( net = 1 ; net <= numnetsG ; net++ ) { if( netarrayG[net]->numpins <= 1 ) { continue ; } rebuild_netgraph( net ) ; /* find minimum cost tree connection from all the pins of a net */ } } rebuild_netgraph( net ) INT net ; { PINBOXPTR netptr ; SEGBOXPTR segptr ; ADJASEGPTR adj ; INT row , botrow , toprow , i , j , k , x ; INT node1 , node2 , last_j , last_k ; INT num_edge , tree_edge , vtx , j_rite ; INT comparepinx(), compare_cost() ; netptr = netarrayG[net]->pins ; toprow = 0 ; botrow = numRowsG + 1 ; for( ; netptr ; netptr = netptr->next ) { row = netptr->row ; if( row > toprow ) { toprow = row ; } if( row < botrow ) { botrow = row ; } z_S[ row ][ ++pins_at_rowS[row] ] = netptr ; } for( i = botrow ; i <= toprow ; i++ ) { if( pins_at_rowS[i] == 0 ) { printf("there are no pin in row %d for net %d\n", i, net ); dbx_terminal( net , net ) ; YexitPgm(PGMFAIL) ; } else { if( pins_at_rowS[i] > 1 ) { Yquicksort( (char *)(z_S[i]+1), pins_at_rowS[i], sizeof(PINBOXPTR), comparepinx ); } } } vtx = 0 ; num_edge = 0 ; first_indexS[botrow] = 0 ; for( i = 1 ; i <= pins_at_rowS[botrow] ; i++ ) { vertex_G[ ++vtx ] = z_S[botrow][i] ; } for( i = botrow + 1 ; i <= toprow ; i++ ) { first_indexS[i] = first_indexS[i-1] + pins_at_rowS[i-1] ; for( j = 1 ; j <= pins_at_rowS[i] ; j++ ) { vertex_G[ ++vtx ] = z_S[i][j] ; } } /* build complete graph for pins in adjacent rows */ for( i = botrow ; i < toprow ; i++ ) { last_j = first_indexS[i] + pins_at_rowS[i] ; last_k = first_indexS[i+1] + pins_at_rowS[i+1] ; for( j = first_indexS[i] + 1 ; j <= last_j ; j++ ) { if( vertex_G[j]->pinloc < NEITHER ) { continue ; } for( k = first_indexS[i+1] + 1 ; k <= last_k ; k++ ) { if( vertex_G[k]->pinloc > NEITHER ) { continue ; } edge_dataS[ ++num_edge ]->node1 = j ; edge_dataS[ num_edge ]->node2 = k ; x = ABS( vertex_G[j]->xpos - vertex_G[k]->xpos ) ; if( x < average_pin_sepG ) { edge_dataS[ num_edge ]->cost = x ; } else { edge_dataS[ num_edge ]->cost = 5 * x / 2 ; } } } } /* hook up the pins in the same row one by one */ for( i = botrow ; i <= toprow ; i++ ) { last_j = first_indexS[i] + pins_at_rowS[i] ; for( j = first_indexS[i] + 1 ; j < last_j ; j++ ) { if( vertex_G[j]->pinloc > NEITHER ) { for( j_rite = j+1 ; j_rite <= last_j ; j_rite++ ) { if( vertex_G[j_rite]->pinloc >= NEITHER ) { edge_dataS[ ++num_edge ]->node1 = j ; edge_dataS[ num_edge ]->node2 = j_rite ; edge_dataS[ num_edge ]->cost = 5 * ABS( vertex_G[j]->xpos - vertex_G[j_rite]->xpos ) / 2 ; break ; } } } else if( vertex_G[j]->pinloc < NEITHER ) { for( j_rite = j+1 ; j_rite <= last_j ; j_rite++ ) { if( vertex_G[j_rite]->pinloc <= NEITHER ) { edge_dataS[ ++num_edge ]->node1 = j ; edge_dataS[ num_edge ]->node2 = j_rite ; edge_dataS[ num_edge ]->cost = 5 * ABS( vertex_G[j]->xpos - vertex_G[j_rite]->xpos ) / 2 ; break ; } } } else { for( j_rite = j+1 ; j_rite <= last_j ; j_rite++ ) { if( vertex_G[j_rite]->pinloc < NEITHER ) { edge_dataS[ ++num_edge ]->node1 = j ; edge_dataS[ num_edge ]->node2 = j_rite ; edge_dataS[ num_edge ]->cost = 5 * ABS( vertex_G[j]->xpos - vertex_G[j_rite]->xpos ) / 2 ; break ; } } for( j_rite = j+1 ; j_rite <= last_j ; j_rite++ ) { if( vertex_G[j_rite]->pinloc > NEITHER ) { edge_dataS[ ++num_edge ]->node1 = j ; edge_dataS[ num_edge ]->node2 = j_rite ; edge_dataS[ num_edge ]->cost = 5 * ABS( vertex_G[j]->xpos - vertex_G[j_rite]->xpos ) / 2 ; break ; } } for( j_rite = j+1 ; j_rite <= last_j ; j_rite++ ) { if( vertex_G[j_rite]->pinloc == NEITHER ) { edge_dataS[ ++num_edge ]->node1 = j ; edge_dataS[ num_edge ]->node2 = j_rite ; edge_dataS[ num_edge ]->cost = ABS( vertex_G[j]->xpos - vertex_G[j_rite]->xpos ) / 2 ; break ; } } } } } /* find the minimum spanning tree for the graph build above */ /* -----------------------------------------------------------* * * * Kruskal's minimum spanning tree * * * * -----------------------------------------------------------*/ for( i = 1 ; i <= vtx ; i++ ) { count_G[i] = 1 ; father_G[i] = 0 ; root_G[i] = i ; } tree_edge = 0 ; Yquicksort( (char *)(edge_dataS+1), num_edge, sizeof(EDGE_COST), compare_cost ) ; segptr = netsegHeadG[net] ; for( i = 1 ; i <= num_edge ; i++ ) { node1 = edge_dataS[i]->node1 ; node2 = edge_dataS[i]->node2 ; j = find_set_name( node1 ) ; k = find_set_name( node2 ) ; if( j != k ) { /* node1 and node2 belong to two different set*/ do_set_union( j , k ) ; segptr->next = (SEGBOXPTR)Ysafe_calloc( 1, sizeof(SEGBOX) ) ; segptr->next->prev = segptr ; segptr = segptr->next ; if( vertex_G[node1]->xpos <= vertex_G[node2]->xpos ) { segptr->pin1ptr = vertex_G[node1] ; segptr->pin2ptr = vertex_G[node2] ; } else { segptr->pin1ptr = vertex_G[node2] ; segptr->pin2ptr = vertex_G[node1] ; } adj = (ADJASEGPTR)Ysafe_calloc( 1, sizeof(ADJASEG) ) ; adj->next = vertex_G[node1]->adjptr->next ; adj->segptr = segptr ; vertex_G[node1]->adjptr->next = adj ; adj = (ADJASEGPTR)Ysafe_calloc( 1, sizeof(ADJASEG) ) ; adj->next = vertex_G[node2]->adjptr->next ; adj->segptr = segptr ; vertex_G[node2]->adjptr->next = adj ; if( ++tree_edge >= vtx ) { break ; } } } remove_unnecessary_feed( net , 0 ) ; /* remove the feed through pins that has only one edge incident on it. */ for( i = botrow ; i <= toprow ; i++ ) { pins_at_rowS[i] = 0 ; } return ; } /* ------------------------------------------------------------------* * the do - while loop below try to remove all the feed through * * pins such that there are only one edge incident on them * *--------------------------------------------------------------------*/ remove_unnecessary_feed( net , flag ) INT net , flag ; { DBOXPTR dimptr ; PINBOXPTR netptr , nextptr , ptr , ptr1 , ptr2 ; PINBOXPTR straight_ptr ; SEGBOXPTR segptr , segptr1 , segptr2 ; SEGBOXPTR asegptr[10] , straight_seg ; ADJASEGPTR adj , adjnext ; INT remove_feed_flag ; INT i, n, fixFlag, channel ; if( !(netarrayG[net]->pins) ) { return ; } do { remove_feed_flag = 0 ; dimptr = netarrayG[net] ; netptr = dimptr->pins ; for( ; netptr->next ; netptr = netptr->next ){ nextptr = netptr->next ; if( nextptr->terminal > TotRegPinsG ) { if( nextptr->adjptr->next == NULL ) { netptr->next = nextptr->next ; Ysafe_free( nextptr->eqptr ) ; Ysafe_free( nextptr->adjptr ) ; /* added by Carl 7/14/89 */ tearrayG[nextptr->terminal] = NULL ; /* end of addition */ Ysafe_free( nextptr ) ; implicit_pins_usedG-- ; remove_feed_flag = 1 ; } else if( nextptr->adjptr->next->next == NULL ) { segptr = nextptr->adjptr->next->segptr ; segptr->prev->next = segptr->next ; if( segptr->next != NULL ) { segptr->next->prev = segptr->prev ; } if( segptr->pin1ptr == nextptr ) { ptr = segptr->pin2ptr ; } else { ptr = segptr->pin1ptr ; } for( adj = ptr->adjptr ; adj->next ; adj = adj->next ) { adjnext = adj->next ; if( adjnext->segptr == segptr ) { adj->next = adjnext->next ; Ysafe_free( adjnext ) ; break ; } } Ysafe_free( segptr ) ; netptr->next = nextptr->next ; Ysafe_free( nextptr->eqptr ) ; Ysafe_free( nextptr->adjptr->next ) ; Ysafe_free( nextptr->adjptr ) ; /* added by Carl 7/14/89 */ tearrayG[nextptr->terminal] = NULL ; /* end of addition */ Ysafe_free( nextptr ) ; implicit_pins_usedG-- ; remove_feed_flag = 1 ; } else if( flag && nextptr->adjptr->next->next->next == NULL ) { segptr1 = nextptr->adjptr->next->segptr ; segptr2 = nextptr->adjptr->next->next->segptr ; if( segptr1->flag == segptr2->flag ) { /*same channel*/ segptr2->prev->next = segptr2->next ; if( segptr2->next != NULL ) { segptr2->next->prev = segptr2->prev ; } if( segptr1->pin1ptr == nextptr ) { ptr1 = segptr1->pin2ptr ; } else { ptr1 = segptr1->pin1ptr ; } if( segptr2->pin1ptr == nextptr ) { ptr2 = segptr2->pin2ptr ; } else { ptr2 = segptr2->pin1ptr ; } if( ptr1->xpos <= ptr2->xpos ) { segptr1->pin1ptr = ptr1 ; segptr1->pin2ptr = ptr2 ; } else { segptr1->pin1ptr = ptr2 ; segptr1->pin2ptr = ptr1 ; } if( ptr1->row == ptr2->row && ptr1->pinloc == NEITHER && ptr2->pinloc == NEITHER ) { if( segptr1->flag == ptr1->row + 1 ) { segptr1->switchvalue = swUP ; } else { segptr1->switchvalue = swDOWN ; } } else { segptr1->switchvalue = nswLINE ; } /* old way: segptr1->switchvalue = nswLINE ; */ for( adj = ptr2->adjptr->next ; adj ; adj = adj->next ) { if( adj->segptr == segptr2 ) { adj->segptr = segptr1 ; break ; } } Ysafe_free( segptr2 ) ; netptr->next = nextptr->next ; Ysafe_free( nextptr->eqptr ) ; Ysafe_free( nextptr->adjptr->next->next ) ; Ysafe_free( nextptr->adjptr->next ) ; Ysafe_free( nextptr->adjptr ) ; /* added by Carl 7/14/89 */ tearrayG[nextptr->terminal] = NULL ; /* end of addition */ Ysafe_free( nextptr ) ; implicit_pins_usedG-- ; remove_feed_flag = 1 ; } } else if( flag ) { fixFlag = 0 ; n = 0 ; adj = nextptr->adjptr->next ; channel = adj->segptr->flag ; straight_seg = NULL ; for( ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( segptr->flag != channel ) { fixFlag = 1 ; break ; } else if( segptr->pin1ptr->xpos == segptr->pin2ptr->xpos && straight_seg == NULL ) { straight_seg = segptr ; /* straight vertical segment */ } else { asegptr[ ++n ] = segptr ; /* switchable segment */ } } if( fixFlag ) { /* not all the adjcent segments are in the same channel */ /* nothing need to be done */ continue ; } if( straight_seg->pin1ptr == nextptr ) { straight_ptr = straight_seg->pin2ptr ; } else { straight_ptr = straight_seg->pin1ptr ; } /* straight_ptr is the pointer to the terminal which is straight above the feed-through pin */ for( i = 1 ; i <= n ; i++ ) { if( asegptr[i]->pin1ptr == nextptr ) { asegptr[i]->pin1ptr = straight_ptr ; } else { asegptr[i]->pin2ptr = straight_ptr ; } asegptr[i]->switchvalue = nswLINE ; } straight_seg->prev->next = straight_seg->next ; if( straight_seg->next ) { straight_seg->next->prev = straight_seg->prev ; } /* delete straight segment from the segment linked lists */ for( adj = straight_ptr->adjptr->next ; adj ; adj = adj->next ) { if( adj->segptr == straight_seg ) { adj->segptr = asegptr[1] ; break ; } } for( i = 2 ; i <= n ; i++ ) { adj = (ADJASEG *)Ysafe_calloc( 1 , sizeof(ADJASEG) ); adj->segptr = asegptr[i] ; adj->next = straight_ptr->adjptr->next ; straight_ptr->adjptr->next = adj ; } netptr->next = nextptr->next ; Ysafe_free( straight_seg ) ; Ysafe_free( nextptr->eqptr ) ; for( adj = nextptr->adjptr ; adj ; adj = adjnext ) { adjnext = adj->next ; Ysafe_free( adj ) ; } /* added by Carl 7/14/89 */ tearrayG[nextptr->terminal] = NULL ; Ysafe_free( nextptr ) ; /* end of addition */ implicit_pins_usedG-- ; remove_feed_flag = 1 ; } } else { break ; } } netptr = dimptr->pins ; if( netptr->terminal > TotRegPinsG ) { if( netptr->adjptr->next == NULL ) { dimptr->pins = netptr->next ; Ysafe_free( netptr->eqptr ) ; Ysafe_free( netptr->adjptr ) ; /* added by Carl 7/14/89 */ tearrayG[netptr->terminal] = NULL ; /* end of addition */ Ysafe_free( netptr ) ; remove_feed_flag = 1 ; } else if( netptr->adjptr->next->next == NULL ) { segptr = netptr->adjptr->next->segptr ; segptr->prev->next = segptr->next ; if( segptr->next != NULL ) { segptr->next->prev = segptr->prev ; } if( segptr->pin1ptr == netptr ) { ptr = segptr->pin2ptr ; } else { ptr = segptr->pin1ptr ; } for( adj = ptr->adjptr ; adj->next ; adj = adj->next ) { adjnext = adj->next ; if( adjnext->segptr == segptr ) { adj->next = adjnext->next ; Ysafe_free( adjnext ) ; break ; } } Ysafe_free( segptr ) ; dimptr->pins = netptr->next ; Ysafe_free( netptr->eqptr ) ; Ysafe_free( netptr->adjptr ) ; /* added by Carl 7/14/89 */ tearrayG[netptr->terminal] = NULL ; /* end of addition */ Ysafe_free( netptr ) ; remove_feed_flag = 1 ; } else if( flag && netptr->adjptr->next->next->next == NULL ) { segptr1 = netptr->adjptr->next->segptr ; segptr2 = netptr->adjptr->next->next->segptr ; if( segptr1->flag == segptr2->flag ) { /*same channel*/ segptr2->prev->next = segptr2->next ; if( segptr2->next != NULL ) { segptr2->next->prev = segptr2->prev ; } if( segptr1->pin1ptr == netptr ) { ptr1 = segptr1->pin2ptr ; } else { ptr1 = segptr1->pin1ptr ; } if( segptr2->pin1ptr == netptr ) { ptr2 = segptr2->pin2ptr ; } else { ptr2 = segptr2->pin1ptr ; } if( ptr1->xpos <= ptr2->xpos ) { segptr1->pin1ptr = ptr1 ; segptr1->pin2ptr = ptr2 ; } else { segptr1->pin1ptr = ptr2 ; segptr1->pin2ptr = ptr1 ; } if( ptr1->row == ptr2->row && ptr1->pinloc == NEITHER && ptr2->pinloc == NEITHER ) { if( segptr1->flag == ptr1->row + 1 ) { segptr1->switchvalue = swUP ; } else { segptr1->switchvalue = swDOWN ; } } else { segptr1->switchvalue = nswLINE ; } /* old way: segptr1->switchvalue = nswLINE ; */ for( adj = ptr2->adjptr->next ; adj ; adj = adj->next ) { if( adj->segptr == segptr2 ) { adj->segptr = segptr1 ; break ; } } Ysafe_free( segptr2 ) ; dimptr->pins = netptr->next ; Ysafe_free( netptr->eqptr ) ; Ysafe_free( netptr->adjptr->next->next ) ; Ysafe_free( netptr->adjptr->next ) ; Ysafe_free( netptr->adjptr ) ; /* added by Carl 7/14/89 */ tearrayG[netptr->terminal] = NULL ; /* end of addition */ Ysafe_free( netptr ) ; implicit_pins_usedG-- ; remove_feed_flag = 1 ; } } else if( flag ) { fixFlag = 0 ; n = 0 ; adj = netptr->adjptr->next ; channel = adj->segptr->flag ; straight_seg = NULL ; for( ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( segptr->flag != channel ) { fixFlag = 1 ; break ; } else if( segptr->pin1ptr->xpos == segptr->pin2ptr->xpos && straight_seg == NULL ) { straight_seg = segptr ; /* straight vertical segment */ } else { asegptr[ ++n ] = segptr ;/* switchable segment */ } } if( fixFlag ) { /* not all the adjcent segments are in the same channel */ /* nothing need to be done */ continue ; } if( straight_seg->pin1ptr == netptr ) { straight_ptr = straight_seg->pin2ptr ; } else { straight_ptr = straight_seg->pin1ptr ; } /* straight_ptr is the pointer to the terminal which is straight above the feed-through pin */ for( i = 1 ; i <= n ; i++ ) { if( asegptr[i]->pin1ptr == netptr ) { asegptr[i]->pin1ptr = straight_ptr ; } else { asegptr[i]->pin2ptr = straight_ptr ; } asegptr[i]->switchvalue = nswLINE ; } straight_seg->prev->next = straight_seg->next ; if( straight_seg->next ) { straight_seg->next->prev = straight_seg->prev ; } /* delete the straight segment form the segment linked lists */ for( adj = straight_ptr->adjptr->next ; adj ; adj = adj->next ) { if( adj->segptr == straight_seg ) { adj->segptr = asegptr[1] ; break ; } } for( i = 2 ; i <= n ; i++ ) { adj = (ADJASEG *)Ysafe_calloc( 1 , sizeof(ADJASEG) ) ; adj->segptr = asegptr[i] ; adj->next = straight_ptr->adjptr->next ; straight_ptr->adjptr->next = adj ; } dimptr->pins = netptr->next ; Ysafe_free( straight_seg ) ; Ysafe_free( netptr->eqptr ) ; for( adj = netptr->adjptr ; adj ; adj = adjnext ) { adjnext = adj->next ; Ysafe_free( adj ) ; } /* added by Carl 7/14/89 */ tearrayG[netptr->terminal] = NULL ; Ysafe_free( netptr ) ; /* end of addition */ implicit_pins_usedG-- ; remove_feed_flag = 1 ; } } } while( remove_feed_flag ) ; return ; } find_set_name( v ) INT v ; { INT i , k ; k = 0 ; while( father_G[v] ) { stack_G[ ++k ] = v ; v = father_G[v] ; } for( i = 1 ; i <= k ; i++ ) { father_G[ stack_G[i] ] = v ; } /* path compression */ return( v ) ; } /*--------------------------------------------------------------* * see "The Design and Analysis of Computer Algorithm" by Aho , * * Hopcroft and Ullman page 129 to 139 for this algorithm of * * Union and Find problem. * *--------------------------------------------------------------*/ do_set_union( i , j ) INT i , j ; { INT large , small ; if( count_G[ root_G[i] ] <= count_G[ root_G[j] ] ) { large = root_G[j] ; small = root_G[i] ; } else { large = root_G[i] ; small = root_G[j] ; } father_G[small] = large ; count_G[large] += count_G[small] ; } switchable_or_not() { SEGBOXPTR segptr ; PINBOXPTR ptr1 , ptr2 ; DOUBLE r ; INT net ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ){ ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; if( ptr1->row == ptr2->row ) { if( ptr1->row == 0 || ptr1->row == numRowsG + 1 ) { segptr->switchvalue = nswLINE ; } else if( ptr1->pinloc != NEITHER || ptr2->pinloc != NEITHER ) { segptr->switchvalue = nswLINE ; } else { r = (DOUBLE) RAND / (DOUBLE) 0x7fffffff ; if( r >= 0.5 ) { segptr->switchvalue = swUP ; } else { segptr->switchvalue = swDOWN ; } } } else { segptr->switchvalue = nswLINE ; } } } } free_z_memory() { INT i , j , last_i ; if ( z_S != NULL ) { j = numRowsG + 1 ; for( i = 0 ; i <= j ; i++ ) { Ysafe_free( z_S[i] ) ; } Ysafe_free( z_S ) ; z_S = NULL ; } Ysafe_free( pins_at_rowS ) ; pins_at_rowS = NULL ; Ysafe_free( first_indexS ) ; first_indexS = NULL ; if ( edge_dataS != NULL ) { last_i = maxpin_numberS * maxpin_numberS * numRowsG - 1 ; for( i = 1 ; i <= last_i ; i++ ) { Ysafe_free( edge_dataS[i] ) ; } Ysafe_free( edge_dataS ) ; edge_dataS = NULL ; } } postFeedAssgn_carl() { INT net , i , row , botrow , toprow , last_i ; SEGBOXPTR segptr , nextseg ; PINBOXPTR netptr , nextptr , st_head , stptr , ptr ; ADJASEGPTR adj , nextadj ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net]->next ; segptr ; segptr = nextseg ) { nextseg = segptr->next ; Ysafe_free( segptr ) ; } netsegHeadG[net]->next = NULL ; for( ptr = netarrayG[net]->pins ; ptr ; ptr = ptr->next ) { for( adj = ptr->adjptr->next ; adj ; adj = nextadj ) { nextadj = adj->next ; Ysafe_free( adj ) ; } ptr->adjptr->next = NULL ; } } maxpin_numberS = 0 ; Ysafe_free( pins_at_rowS ); pins_at_rowS = (INT *)Ysafe_calloc( numChansG + 1, sizeof(INT) ) ; for( net = 1 ; net <= numnetsG ; net++ ) { if( netarrayG[net]->numpins <= 2 ) { continue ; } botrow = numChansG ; toprow = 0 ; for( netptr = netarrayG[net]->pins ; netptr ; netptr = netptr->next ) { row = netptr->row ; pins_at_rowS[ row ]++ ; if( row < botrow ) { botrow = row ; } if( row > toprow ) { toprow = row ; } } for( row = botrow ; row <= toprow ; row++ ) { if( pins_at_rowS[row] > maxpin_numberS ) { maxpin_numberS = pins_at_rowS[row] ; } pins_at_rowS[row] = 0 ; } } maxpin_numberS += 3 ; last_i = maxpin_numberS * maxpin_numberS * numRowsG - 1 ; /* Free data before regenerating, better is likely to just clear the data */ Ysafe_free( count_G ); Ysafe_free( father_G ); Ysafe_free( root_G ); Ysafe_free( stack_G ); Ysafe_free( first_indexS ); Ysafe_free( vertex_G ); for( i = 1 ; i <= last_i ; i++ ) { Ysafe_free( edge_dataS[i] ); } Ysafe_free( edge_dataS ); for( i = 0 ; i <= numChansG ; i++ ) { Ysafe_free( z_S[i] ); } Ysafe_free( z_S ); count_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; father_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; root_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; stack_G = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; first_indexS = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof( INT ) ) ; vertex_G = (PINBOXPTR *)Ysafe_malloc( 2 * Max_numPinsG * sizeof(PINBOXPTR) ); edge_dataS = (EDGE_COST *)Ysafe_malloc( ( last_i + 1 ) * sizeof(EDGE_COST) ) ; for( i = 1 ; i <= last_i ; i++ ) { edge_dataS[i] = (EDGE_COST)Ysafe_malloc( sizeof(EDGE_COST_BOX) ); } z_S = (PINBOXPTR **)Ysafe_malloc( ( numChansG + 1 ) * sizeof(PINBOXPTR *) ) ; for( i = 0 ; i <= numChansG ; i++ ) { z_S[i] = (PINBOXPTR *)Ysafe_malloc( maxpin_numberS * sizeof(PINBOXPTR) ) ; } for( net = 1 ; net <= numnetsG ; net++ ) { if( netarrayG[net]->numpins <= 1 ) { continue ; } rebuild_netgraph_carl( net ) ; /* find minimum cost tree connection from all the pins of a net */ } } rebuild_netgraph_carl( net ) INT net ; { PINBOXPTR netptr ; SEGBOXPTR segptr ; ADJASEGPTR adj ; INT row , botrow , toprow , i , j , k , x ; INT node1 , node2 , last_j , last_k ; INT num_edge , tree_edge , vtx , j_rite ; INT comparepinx(), compare_cost() ; netptr = netarrayG[net]->pins ; toprow = 0 ; botrow = numRowsG + 1 ; for( ; netptr ; netptr = netptr->next ) { row = netptr->row ; if( row > toprow ) { toprow = row ; } if( row < botrow ) { botrow = row ; } z_S[ row ][ ++pins_at_rowS[row] ] = netptr ; } for( i = botrow ; i <= toprow ; i++ ) { if( pins_at_rowS[i] == 0 ) { printf("there are no pin in row %d for net %d\n", i, net ); dbx_terminal( net , net ) ; YexitPgm(PGMFAIL) ; } else { if( pins_at_rowS[i] > 1 ) { Yquicksort( (char *)(z_S[i]+1), pins_at_rowS[i], sizeof(PINBOXPTR), comparepinx ); } } } vtx = 0 ; num_edge = 0 ; first_indexS[botrow] = 0 ; for( i = 1 ; i <= pins_at_rowS[botrow] ; i++ ) { vertex_G[ ++vtx ] = z_S[botrow][i] ; } for( i = botrow + 1 ; i <= toprow ; i++ ) { first_indexS[i] = first_indexS[i-1] + pins_at_rowS[i-1] ; for( j = 1 ; j <= pins_at_rowS[i] ; j++ ) { vertex_G[ ++vtx ] = z_S[i][j] ; } } /* build complete graph for pins in adjacent rows */ for( i = botrow ; i < toprow ; i++ ) { last_j = first_indexS[i] + pins_at_rowS[i] ; last_k = first_indexS[i+1] + pins_at_rowS[i+1] ; for( j = first_indexS[i] + 1 ; j <= last_j ; j++ ) { if( vertex_G[j]->pinloc < NEITHER ) { continue ; } for( k = first_indexS[i+1] + 1 ; k <= last_k ; k++ ) { if( vertex_G[k]->pinloc > NEITHER ) { continue ; } edge_dataS[ ++num_edge ]->node1 = j ; edge_dataS[ num_edge ]->node2 = k ; x = ABS( vertex_G[j]->xpos - vertex_G[k]->xpos ) ; if( x < average_pin_sepG ) { edge_dataS[ num_edge ]->cost = x ; } else { edge_dataS[ num_edge ]->cost = 5 * x / 2 ; } } } } /* hook up the pins in the same row one by one */ for( i = botrow ; i <= toprow ; i++ ) { last_j = first_indexS[i] + pins_at_rowS[i] ; for( j = first_indexS[i] + 1 ; j < last_j ; j++ ) { if( vertex_G[j]->pinloc > NEITHER ) { for( j_rite = j+1 ; j_rite <= last_j ; j_rite++ ) { if( vertex_G[j_rite]->pinloc >= NEITHER ) { edge_dataS[ ++num_edge ]->node1 = j ; edge_dataS[ num_edge ]->node2 = j_rite ; edge_dataS[ num_edge ]->cost = 5 * ABS( vertex_G[j]->xpos - vertex_G[j_rite]->xpos ) / 2 ; break ; } } } else if( vertex_G[j]->pinloc < NEITHER ) { for( j_rite = j+1 ; j_rite <= last_j ; j_rite++ ) { if( vertex_G[j_rite]->pinloc <= NEITHER ) { edge_dataS[ ++num_edge ]->node1 = j ; edge_dataS[ num_edge ]->node2 = j_rite ; edge_dataS[ num_edge ]->cost = 5 * ABS( vertex_G[j]->xpos - vertex_G[j_rite]->xpos ) / 2 ; break ; } } } else { for( j_rite = j+1 ; j_rite <= last_j ; j_rite++ ) { if( vertex_G[j_rite]->pinloc < NEITHER ) { edge_dataS[ ++num_edge ]->node1 = j ; edge_dataS[ num_edge ]->node2 = j_rite ; edge_dataS[ num_edge ]->cost = 5 * ABS( vertex_G[j]->xpos - vertex_G[j_rite]->xpos ) / 2 ; break ; } } for( j_rite = j+1 ; j_rite <= last_j ; j_rite++ ) { if( vertex_G[j_rite]->pinloc > NEITHER ) { edge_dataS[ ++num_edge ]->node1 = j ; edge_dataS[ num_edge ]->node2 = j_rite ; edge_dataS[ num_edge ]->cost = 5 * ABS( vertex_G[j]->xpos - vertex_G[j_rite]->xpos ) / 2 ; break ; } } for( j_rite = j+1 ; j_rite <= last_j ; j_rite++ ) { if( vertex_G[j_rite]->pinloc == NEITHER ) { edge_dataS[ ++num_edge ]->node1 = j ; edge_dataS[ num_edge ]->node2 = j_rite ; edge_dataS[ num_edge ]->cost = ABS( vertex_G[j]->xpos - vertex_G[j_rite]->xpos ) / 2 ; break ; } } } } } /* find the minimum spanning tree for the graph build above */ /* -----------------------------------------------------------* * * * Kruskal's minimum spanning tree * * * * -----------------------------------------------------------*/ for( i = 1 ; i <= vtx ; i++ ) { count_G[i] = 1 ; father_G[i] = 0 ; root_G[i] = i ; } tree_edge = 0 ; Yquicksort( (char *)(edge_dataS+1), num_edge, sizeof(EDGE_COST), compare_cost ) ; segptr = netsegHeadG[net] ; for( i = 1 ; i <= num_edge ; i++ ) { node1 = edge_dataS[i]->node1 ; node2 = edge_dataS[i]->node2 ; j = find_set_name( node1 ) ; k = find_set_name( node2 ) ; if( j != k ) { /* node1 and node2 belong to two different set*/ do_set_union( j , k ) ; segptr->next = (SEGBOXPTR)Ysafe_calloc( 1, sizeof(SEGBOX) ) ; segptr->next->prev = segptr ; segptr = segptr->next ; if( vertex_G[node1]->xpos <= vertex_G[node2]->xpos ) { segptr->pin1ptr = vertex_G[node1] ; segptr->pin2ptr = vertex_G[node2] ; } else { segptr->pin1ptr = vertex_G[node2] ; segptr->pin2ptr = vertex_G[node1] ; } adj = (ADJASEGPTR)Ysafe_calloc( 1, sizeof(ADJASEG) ) ; adj->next = vertex_G[node1]->adjptr->next ; adj->segptr = segptr ; vertex_G[node1]->adjptr->next = adj ; adj = (ADJASEGPTR)Ysafe_calloc( 1, sizeof(ADJASEG) ) ; adj->next = vertex_G[node2]->adjptr->next ; adj->segptr = segptr ; vertex_G[node2]->adjptr->next = adj ; if( ++tree_edge >= vtx ) { break ; } } } remove_unnecessary_feed( net , 0 ) ; /* remove the feed through pins that has only one edge incident on it. */ for( i = botrow ; i <= toprow ; i++ ) { pins_at_rowS[i] = 0 ; } return ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/newtemp.c000066400000000000000000000115511305746555600213610ustar00rootroot00000000000000/* * Copyright (C) 1988-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: newtemp.c DESCRIPTION:update temparature of the simulated annealing algorithm. CONTENTS: DOUBLE calc_acceptance_ratio( iternum ) DOUBLE iternum ; init_acceptance_rate() DATE: Dec 19, 1988 REVISIONS: ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) newtemp.c (Yale) version 4.3 9/7/90" ; #endif #endif #include "standard.h" #include /* ----------------------------------------------------------------- The temperature regions are defined as follows: Iterations Purpose -1 - 0 Initialization 1 - HIGHTEMP High temperature regime exponential decay HIGHTEMP+1 - MEDTEMP Critical temp. 0.44 - range limiter MEDTEMP+1 - LASTTEMP Low temperature regime exponential decay. Note: If you change definitions here, check uloop.c ----------------------------------------------------------------------- */ #define HIGHTEMP 23.00 /* (15.0) last iteration of high temp regime */ #define MEDTEMP 81.00 /* (52.0) last iteration of range limiter */ #define LOWTEMP 125.00 /* (100.0) temperature @ 6% acceptance rate */ #define LASTTEMP 155.00 /* last iteration */ #define CRITRATIO 0.44 /* critical ratio */ #define LOWRATIO 0.06 /* temperature for controler turn off */ static DOUBLE alphaS ; /* exponential decay constant for high temp */ static DOUBLE betaS ; /* exponential decay constant for low temp */ /* calculate static exponential time constants */ init_acceptance_rate() { /* determine alpha */ alphaS = - log( CRITRATIO ) / HIGHTEMP ; /* determine beta */ betaS = - log( ( LOWRATIO/CRITRATIO ) ) / (LOWTEMP - MEDTEMP ) ; } /* end init_acceptance_rate */ /* given an iteration number return desired acceptance rate */ DOUBLE calc_acceptance_ratio( iternum ) DOUBLE iternum ; { DOUBLE desired_ratio ; if( iternum <= HIGHTEMP ){ /* -------------------------------------------------------- desired_ratio = exp( - alphaS * iternum ) ; -------------------------------------------------------- */ desired_ratio = iternum ; desired_ratio *= - alphaS ; desired_ratio = exp( desired_ratio ) ; } else if( iternum <= MEDTEMP ){ desired_ratio = CRITRATIO ; } else if( iternum > LOWTEMP ){ if( iternum < LASTTEMP ) { desired_ratio = LOWRATIO - ( (LOWRATIO / (LASTTEMP - LOWTEMP)) * (iternum - LOWTEMP) ) ; } else { desired_ratio = 0.0 ; } } else { /* low temp */ /* -------------------------------------------------------- desired_ratio = 0.44 * exp( - betaS * ( iternum - MEDTEMP )) -------------------------------------------------------- */ desired_ratio = iternum - MEDTEMP ; desired_ratio *= - betaS ; desired_ratio = CRITRATIO * exp( desired_ratio ) ; } return( desired_ratio ) ; } /* end calc_acceptance ratio */ /* #define TESTRATIO */ #ifdef TESTRATIO /* test program for desired acceptance rate profile */ main( argc , argv ) INT argc ; char *argv[] ; { DOUBLE d_ratio, calc_acceptance_rate() ; INT i ; init_acceptance_rate() ; for( i= 0; i<= 150; i++ ){ d_ratio = calc_acceptance_ratio( (DOUBLE) i ) ; printf( "%4.2le\n" , d_ratio ) ; } } /* end main */ #endif /* TESTRATIO */ graywolf-0.1.4+20170307gite1bf319/src/twsc/outcm.c000066400000000000000000000074311305746555600210330ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: outcm.c DESCRIPTION:input/output to connection machine. CONTENTS: outcm() incm(fp) FILE *fp ; DATE: Mar 27, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) outcm.c (Yale) version 4.3 9/7/90" ; #endif #endif #include "standard.h" #include "groute.h" #include "main.h" #if SIZEOF_VOID_P == 64 #define INTSCANSTR "%ld" #else #define INTSCANSTR "%d" #endif outcm() { char filename[64] ; FILE *fp ; PINBOXPTR netptr ; INT net , x , local_pin_count , pin_count ; INT cell , row , length , xstart ; sprintf( filename , "%s.cm" , cktNameG ) ; fp = TWOPEN ( filename , "w", ABORT ) ; pin_count = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { local_pin_count = 0 ; for( netptr = netarrayG[net]->pins; netptr; netptr = netptr->next){ if( netptr->cell <= numcellsG ) { local_pin_count++ ; } } if( local_pin_count > 1 ) { pin_count += local_pin_count ; } } fprintf(fp,"%d\n", pin_count ) ; for( net = 1 ; net <= numnetsG ; net++ ) { local_pin_count = 0 ; for( netptr = netarrayG[net]->pins; netptr; netptr = netptr->next){ if( netptr->cell <= numcellsG ) { local_pin_count++ ; } } if( local_pin_count <= 1 ) { continue ; } for( netptr = netarrayG[net]->pins; netptr; netptr = netptr->next){ if( netptr->cell > numcellsG ) { continue ; } cell = netptr->cell ; row = carrayG[cell]->cblock ; x = netptr->xpos ; length = carrayG[cell]->tileptr->right - carrayG[cell]->tileptr->left ; xstart = carrayG[cell]->cxcenter + carrayG[cell]->tileptr->left ; fprintf(fp,"%8d %8d %8d %8d %8d %8d\n", row, cell, net, x, length, xstart ); } } TWCLOSE(fp); return ; } incm(fp) FILE *fp ; { CBOXPTR ptr ; INT net , x , pin_count , pin ; INT cell , row , length , xstart ; fscanf(fp, INTSCANSTR, &pin_count ) ; for( pin = 1 ; pin <= pin_count ; pin++ ) { fscanf(fp, INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR, &row, &cell, &net, &x, &length, &xstart ); ptr = carrayG[cell] ; ptr->cblock = row ; ptr->cxcenter = xstart + length / 2 ; ptr->cycenter = barrayG[row]->bycenter ; } TWCLOSE(fp); return ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/outpins.c000066400000000000000000000647121305746555600214120ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * Copyright (C) 2015 Tim Edwards * Copyright (C) 2015 Staf Verhaegen * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: outpins.c DESCRIPTION:output the pin (global route) information. CONTENTS: outpins() do_outpins( ptr , flag ) PINBOXPTR ptr ; INT flag ; do_left_pseudo_pins( ptr , channel , groupS_number ) PINBOXPTR ptr ; INT channel , groupS_number ; do_right_pseudo_pins( ptr , channel , groupS_number ) PINBOXPTR ptr ; INT channel , groupS_number ; do_left_vertical_channel( ptr ) PINBOXPTR ptr ; do_right_vertical_channel( ptr ) PINBOXPTR ptr ; do_bottom_channel( ptr ) PINBOXPTR ptr ; do_top_channel( ptr ) PINBOXPTR ptr ; DATE: Mar 27, 1989 REVISIONS: Thu Feb 7 00:10:27 EST 1991 - now also support old pin output format. Wed Mar 13 13:46:21 CST 1991 - made the new format the default. Thu Dec 5 21:58:34 EST 1991 - fixed problem with macro cell output pins. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) outpins.c (Yale) version 4.9 12/5/91" ; #endif #endif #include #include "standard.h" #include "groute.h" #include "main.h" #include "readpar.h" #include "pads.h" #include /* #define NSC */ /* global variables */ extern INT *root_G ; extern INT *count_G ; extern INT *stack_G ; extern INT *father_G ; extern INT Max_numPinsG ; extern BOOL new_row_formatG ; extern PINBOXPTR *vertex_G ; /* static definitions */ static INT vtxS ; static INT *hashS ; static INT *groupS ; static INT numpinS ; static INT *rite_edgeS ; static INT *left_edgeS ; static FILE *fpS ; static BOOL old_formatS = FALSE ; char *find_layer( /* pinname, layer */ ) ; static do_outpins(); static do_macropins(); static do_left_vertical_channel(); static do_right_vertical_channel(); static do_bottom_channel(); static do_top_channel(); outpins() { PINBOXPTR ptr1 , ptr2 , ptr ; CBOXPTR cellptr ; SEGBOXPTR seg ; PADBOXPTR pp1, pp2 ; char filename[64] ; INT i , a , b , net , row , padside ; INT upFlag , downFlag , groupS_index ; extern char *strtok() ; if( old_formatS ){ old_outpins() ; return ; } hashS = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; groupS = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( INT ) ) ; rite_edgeS = (INT *)Ysafe_malloc( numChansG * sizeof( INT ) ) ; left_edgeS = (INT *)Ysafe_malloc( numChansG * sizeof( INT ) ) ; for( row = 1 ; row <= numRowsG ; row++ ) { cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; rite_edgeS[row] = cellptr->cxcenter + cellptr->tileptr->right ; } for( row = 1 ; row <= numRowsG ; row++ ) { left_edgeS[row] = barrayG[row]->bxcenter + barrayG[row]->bleft ; } sprintf( filename , "%s.pin" , cktNameG ) ; fpS = TWOPEN ( filename , "w", ABORT ) ; groupS_index = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { vtxS = 0 ; for( ptr = netarrayG[net]->pins ; ptr ; ptr = ptr->next ) { vertex_G[ ++vtxS ] = ptr ; ptr->newy = vtxS ; } numpinS = vtxS ; // if( numpinS <= 1 ) { if( numpinS == 0 ) { continue ; } for( ptr = netarrayG[net]->pins ; ptr ; ptr = ptr->next ) { vertex_G[ ++vtxS ] = ptr ; } for( i = 1 ; i <= vtxS ; i++ ) { count_G[i] = 1 ; father_G[i] = 0 ; root_G[i] = i ; hashS[i] = 0 ; groupS[i] = 0 ; } for( seg = netsegHeadG[net]->next ; seg ; seg = seg->next ) { ptr1 = seg->pin1ptr ; ptr2 = seg->pin2ptr ; if( seg->switchvalue == swUP ) { a = find_set_name( ptr1->newy + numpinS ) ; b = find_set_name( ptr2->newy + numpinS ) ; } else if( seg->switchvalue == swDOWN ) { a = find_set_name( ptr1->newy ) ; b = find_set_name( ptr2->newy ) ; } else if( ptr1->row > ptr2->row ) { a = find_set_name( ptr1->newy ) ; b = find_set_name( ptr2->newy + numpinS ) ; } else if( ptr1->row < ptr2->row ) { a = find_set_name( ptr1->newy + numpinS ) ; b = find_set_name( ptr2->newy ) ; } else if( ptr1->row == 0 ) { a = find_set_name( ptr1->newy + numpinS ) ; b = find_set_name( ptr2->newy + numpinS ) ; } else if( ptr1->row == numChansG ) { a = find_set_name( ptr1->newy ) ; b = find_set_name( ptr2->newy ) ; } else if( (pp1 = carrayG[ptr1->cell]->padptr) && (pp2 = carrayG[ptr2->cell]->padptr) && pp1->padside && pp2->padside ) { a = find_set_name( ptr1->newy ) ; b = find_set_name( ptr2->newy ) ; } else if( seg->flag > ptr1->row ) { a = find_set_name( ptr1->newy + numpinS ) ; b = find_set_name( ptr2->newy + numpinS ) ; } else { a = find_set_name( ptr1->newy ) ; b = find_set_name( ptr2->newy ) ; } do_set_union( a , b ) ; } for( ptr = netarrayG[net]->pins ; ptr ; ptr = ptr->next ) { if( (pp1 = carrayG[ptr->cell]->padptr) && pp1->padside ) { a = find_set_name( ptr->newy + numpinS ) ; b = find_set_name( ptr->newy ) ; do_set_union( a , b ) ; } } for( i = 1 ; i <= vtxS ; i++ ) { a = find_set_name( i ) ; if( count_G[a] > 1 ) { if( hashS[a] == 0 ) { groupS[i] = ++groupS_index ; hashS[a] = groupS_index ; } else { groupS[i] = hashS[a] ; } } } for( ptr = netarrayG[net]->pins ; ptr ; ptr = ptr->next ) { a = find_set_name( ptr->newy + numpinS ) ; if( count_G[a] > 1 ) { upFlag = 1 ; } else { upFlag = 0 ; } b = find_set_name( ptr->newy ) ; if( count_G[b] > 1 ) { downFlag = 1 ; } else { downFlag = 0 ; } pp1 = carrayG[ ptr->cell ]->padptr ; if( pp1 ){ padside = pp1->padside ; } else { padside = 0 ; } switch( padside ){ case L: do_left_vertical_channel( ptr ) ; break ; case T: do_top_channel( ptr ) ; break ; case R: do_right_vertical_channel( ptr ) ; break ; case B: do_bottom_channel( ptr ) ; break ; case MMC: do_macropins( ptr ) ; break ; case 0: default: if( upFlag ) { do_outpins( ptr , 1 ) ; } if( downFlag ) { do_outpins( ptr , 0 ) ; } if( !upFlag && !downFlag ) { do_outpins( ptr, -1 ) ; // Handle singletons } break ; } /* end switch */ } /* the groupS index for vertex_G[i] = groupS[ find_groupS_name(i) ] */ } Ysafe_free( groupS ) ; groupS = NULL ; Ysafe_free( hashS ) ; hashS = NULL ; Ysafe_free( left_edgeS ) ; left_edgeS = NULL ; Ysafe_free( rite_edgeS ) ; rite_edgeS = NULL ; TWCLOSE( fpS ) ; } /*------------------------------------------------------------------ * * The nine field have to be written down to cktname.pin file are : * * 1. Name of net to which the pn belongs. * * 2. Group number of the pin. * * 3. Cell name to which the pin belongs * * 4. The name of the pin. * * 5. The x coordinate of the pin. * * 6. The y coordinate of the pin. * * 7. The channel to which the pin belong to. * * 8. Where the pin is at the top (1) , bottom (-1) or neither (0) * * 9. layer * *-------------------------------------------------------------------*/ static do_outpins( ptr , flag ) PINBOXPTR ptr ; INT flag ; { INT x , y , channel , pinloc , groupS_number , layer , i ; CBOXPTR cellptr ; PADBOXPTR pptr ; char *pinname , tmp_char[2] , *tmp_pinname ; INT length ; char master_name[128] , pin_id[128] , tmp_name[128] ; char instance_name[128] , p_name[128] , *tmp_string ; tmp_char[1] = EOS ; /* terminate string */ cellptr = carrayG[ ptr->cell ] ; if( flag == 1 ) { channel = ptr->row + 1 ; groupS_number = groupS[ ptr->newy + numpinS ] ; pinloc = -1 ; y = cellptr->cycenter + cellptr->tileptr->top ; } else if ( flag == 0 ) { channel = ptr->row ; groupS_number = groupS[ ptr->newy ] ; pinloc = 1 ; y = cellptr->cycenter + cellptr->tileptr->bottom ; } else { // Singleton channel = ptr->row ; groupS_number = groupS[ ptr->newy ] ; pinloc = 0 ; y = cellptr->cycenter + cellptr->tileptr->bottom ; } if( (pptr = cellptr->padptr) && pptr->padside ) { pinname = ptr->pinname ; x = ptr->xpos ; } else { if( ptr->eqptr ) { /* there is at least one equivalent pin */ if( cellptr->corient == 0 ) { if( flag ) { /* pin is on top side of the row */ if( ptr->eqptr->typos > 0 ) { /* equivalent pin is on top side of the row when the cell orientation is "0" */ pinname = ptr->eqptr->pinname ; x = ptr->xpos + ptr->eqptr->txoff ; } else { /* equivalent pin is on the bottom side of the row when the cell orientation is "0" */ pinname = ptr->pinname ; x = ptr->xpos ; } } else { /* pin is on bottom side of the row */ if( ptr->eqptr->typos < 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos + ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } } else if( cellptr->corient == 1 ) { /* mirror about x-axis */ if( flag ) { if( ptr->eqptr->typos < 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos + ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } else { if( ptr->eqptr->typos > 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos + ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } } else if( cellptr->corient == 2 ) { /* mirror about y-axis */ if( flag ) { if( ptr->eqptr->typos > 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos - ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } else { if( ptr->eqptr->typos < 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos - ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } } else { /* 180 degree rotation w.r.t orientation 0 */ if( flag ) { if( ptr->eqptr->typos < 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos - ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } else { if( ptr->eqptr->typos > 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos - ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } } } else { pinname = ptr->pinname ; x = ptr->xpos ; } } tmp_pinname = find_layer( pinname, &layer ) ; #ifdef NSC length = strcspn( tmp_pinname , ":" ) ; if( length < strlen( tmp_pinname ) ) { tmp_string = strtok( tmp_pinname , ":" ) ; sprintf( p_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( pin_id , "%s" , tmp_string ) ; } else { sprintf( p_name , "%s" , tmp_pinname ) ; sprintf( pin_id , "%s" , "0" ) ; } strcpy( tmp_name , carrayG[ptr->cell]->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; sprintf( master_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( master_name , "%s" , tmp_name ) ; sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpS,"%s %d %s %s %d %d %d %d %d %s %s\n" , netarrayG[ptr->net]->name , groupS_number , instance_name , p_name , x , y , channel , pinloc , layer , master_name , pin_id ); #else fprintf(fpS,"%s %d %s %s %d %d %d %d %d\n" , netarrayG[ptr->net]->name , groupS_number , carrayG[ptr->cell]->cname , tmp_pinname , x , y , channel , pinloc , layer ); #endif return ; } static do_macropins( ptr ) PINBOXPTR ptr ; { INT x , y , channel , pinloc , groupS_number , layer , i ; CBOXPTR cellptr ; PADBOXPTR pptr ; char *pinname , tmp_char[2] , *tmp_pinname ; INT length ; char master_name[128] , pin_id[128] , tmp_name[128] ; char instance_name[128] , p_name[128] , *tmp_string ; tmp_char[1] = EOS ; /* terminate string */ cellptr = carrayG[ ptr->cell ] ; channel = ptr->row ; groupS_number = groupS[ ptr->newy ] ; pinloc = 0 ; pinname = ptr->pinname ; x = ptr->xpos ; y = ptr->ypos ; tmp_pinname = find_layer( pinname, &layer ) ; #ifdef NSC length = strcspn( tmp_pinname , ":" ) ; if( length < strlen( tmp_pinname ) ) { tmp_string = strtok( tmp_pinname , ":" ) ; sprintf( p_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( pin_id , "%s" , tmp_string ) ; } else { sprintf( p_name , "%s" , tmp_pinname ) ; sprintf( pin_id , "%s" , "0" ) ; } strcpy( tmp_name , carrayG[ptr->cell]->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; sprintf( master_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( master_name , "%s" , tmp_name ) ; sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpS,"%s %d %s %s %d %d %d %d %d %s %s\n" , netarrayG[ptr->net]->name , groupS_number , instance_name , p_name , x , y , channel , pinloc , layer , master_name , pin_id ); #else fprintf(fpS,"%s %d %s %s %d %d %d %d %d\n" , netarrayG[ptr->net]->name , groupS_number , carrayG[ptr->cell]->cname , tmp_pinname , x , y , channel , pinloc , layer ); #endif return ; } static do_left_pseudo_pins( ptr , channel , groupS_number ) PINBOXPTR ptr ; INT channel , groupS_number ; { INT x , y ; if( channel <= numRowsG ) { y = barrayG[channel]->bycenter - rowHeightG ; } else { y = barrayG[ numRowsG ]->bycenter + rowHeightG ; } if( channel == 1 ) { x = left_edgeS[1] ; } else if( channel == numChansG ) { x = left_edgeS[numRowsG] ; } else { if( left_edgeS[channel] <= left_edgeS[channel-1] ) { x = left_edgeS[channel] ; } else { x = left_edgeS[channel-1] ; } } #ifdef NSC fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d -2 0 0 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y , channel ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -1 -1 0 0 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y ) ; #else fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d -2 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y , channel ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -1 -1 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y ) ; #endif } static do_right_pseudo_pins( ptr , channel , groupS_number ) PINBOXPTR ptr ; INT channel , groupS_number ; { INT x , y ; if( channel == 1 ) { y = barrayG[1]->bycenter - rowHeightG ; x = rite_edgeS[1] ; } else if( channel <= numRowsG ) { y = barrayG[channel]->bycenter - rowHeightG ; if( rite_edgeS[channel] < rite_edgeS[channel-1] ) { x = rite_edgeS[channel] ; } else { x = rite_edgeS[channel-1] ; } } else { y = barrayG[numRowsG]->bycenter + rowHeightG ; x = rite_edgeS[numRowsG] ; } #ifdef NSC fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d 2 0 0 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y , channel ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -2 -1 0 0 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y ) ; #else fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d 2 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y , channel ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -2 -1 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y ) ; #endif } static do_left_vertical_channel( ptr ) PINBOXPTR ptr ; { PINBOXPTR core_ptr ; SEGBOXPTR segptr ; ADJASEG *adj ; PADBOXPTR pptr ; INT groupS_number , layer , i ; char tmp_char[2] , tmp_pinname[1024] ; INT length ; char master_name[128] , pin_id[128] , tmp_name[128] ; char instance_name[128] , p_name[128] , *tmp_string ; groupS_number = groupS[ ptr->newy ] ; strcpy( tmp_pinname , ptr->pinname ) ; if( pin_layers_givenG != 0 ) { if( strncmp( ptr->pinname, "]", 1 ) == 0 ) { strncpy( tmp_char , tmp_pinname + 1 , 1 ) ; tmp_char[1] = '\0' ; layer = atoi( tmp_char ) ; for( i = 0 ; ; i++ ) { tmp_pinname[i] = tmp_pinname[i+2] ; if( tmp_pinname[i] == '\0' ) { break ; } } } else { layer = feedLayerG ; } } else { layer = 0 ; } #ifdef NSC length = strcspn( tmp_pinname , ":" ) ; if( length < strlen( tmp_pinname ) ) { tmp_string = strtok( tmp_pinname , ":" ) ; sprintf( p_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( pin_id , "%s" , tmp_string ) ; } else { sprintf( p_name , "%s" , tmp_pinname ) ; sprintf( pin_id , "%s" , "0" ) ; } strcpy( tmp_name , carrayG[ptr->cell]->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; sprintf( master_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( master_name , "%s" , tmp_name ) ; sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpS,"%s %d %s %s %d %d -1 1 %d %s %s\n" , netarrayG[ptr->net]->name , groupS_number , instance_name , p_name , ptr->xpos , ptr->ypos , layer , master_name , pin_id ); #else fprintf(fpS,"%s %d %s %s %d %d -1 1 %d\n" , netarrayG[ptr->net]->name , groupS_number , carrayG[ptr->cell]->cname , tmp_pinname , ptr->xpos , ptr->ypos , layer ) ; #endif for( adj = ptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( ptr == segptr->pin1ptr ) { core_ptr = segptr->pin2ptr ; } else { core_ptr = segptr->pin1ptr ; } if( !(pptr = carrayG[core_ptr->cell]->padptr) || pptr->padside == MMC ) { do_left_pseudo_pins( ptr, segptr->flag , groupS_number ) ; } } } static do_right_vertical_channel( ptr ) PINBOXPTR ptr ; { PINBOXPTR core_ptr ; SEGBOXPTR segptr ; ADJASEG *adj ; PADBOXPTR pptr ; INT groupS_number , layer , i ; char tmp_char[2] , *tmp_pinname ; INT length ; char master_name[128] , pin_id[128] , tmp_name[128] ; char instance_name[128] , p_name[128] , *tmp_string ; groupS_number = groupS[ ptr->newy ] ; tmp_pinname = find_layer( ptr->pinname, &layer ) ; #ifdef NSC length = strcspn( tmp_pinname , ":" ) ; if( length < strlen( tmp_pinname ) ) { tmp_string = strtok( tmp_pinname , ":" ) ; sprintf( p_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( pin_id , "%s" , tmp_string ) ; } else { sprintf( p_name , "%s" , tmp_pinname ) ; sprintf( pin_id , "%s" , "0" ) ; } strcpy( tmp_name , carrayG[ptr->cell]->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; sprintf( master_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( master_name , "%s" , tmp_name ) ; sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpS,"%s %d %s %s %d %d -2 1 %d %s %s\n" , netarrayG[ptr->net]->name , groupS_number , instance_name , p_name , ptr->xpos , ptr->ypos , layer , master_name , pin_id ); #else fprintf(fpS,"%s %d %s %s %d %d -2 1 %d\n" , netarrayG[ptr->net]->name , groupS_number , carrayG[ptr->cell]->cname, tmp_pinname , ptr->xpos , ptr->ypos , layer ) ; #endif for( adj = ptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( ptr == segptr->pin1ptr ) { core_ptr = segptr->pin2ptr ; } else { core_ptr = segptr->pin1ptr ; } if( !(pptr = carrayG[core_ptr->cell]->padptr) || pptr->padside == MMC ) { do_right_pseudo_pins( ptr, segptr->flag , groupS_number) ; } } } static do_bottom_channel( ptr ) PINBOXPTR ptr ; { INT x , y , groupS_number , layer , i ; char tmp_char[2] , *tmp_pinname ; ADJASEG *adj ; SEGBOXPTR segptr ; PINBOXPTR core_ptr ; PADBOXPTR pptr ; INT length ; INT padside ; char master_name[128] , pin_id[128] , *tmp_name ; char instance_name[128] , p_name[128] , *tmp_string ; groupS_number = groupS[ ptr->newy ] ; tmp_pinname = find_layer( ptr->pinname, &layer ) ; #ifdef NSC length = strcspn( tmp_pinname , ":" ) ; if( length < strlen( tmp_pinname ) ) { tmp_string = strtok( tmp_pinname , ":" ) ; sprintf( p_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( pin_id , "%s" , tmp_string ) ; } else { sprintf( p_name , "%s" , tmp_pinname ) ; sprintf( pin_id , "%s" , "0" ) ; } strcpy( tmp_name , carrayG[ptr->cell]->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; sprintf( master_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( master_name , "%s" , tmp_name ) ; sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpS,"%s %d %s %s %d %d -3 -1 %d %s %s\n" , netarrayG[ptr->net]->name , groupS_number , instance_name , p_name , ptr->xpos , ptr->ypos , layer , master_name , pin_id ); #else fprintf(fpS,"%s %d %s %s %d %d -3 -1 %d\n" , netarrayG[ptr->net]->name , groupS_number , carrayG[ptr->cell]->cname , tmp_pinname , ptr->xpos , ptr->ypos , layer ); #endif y = barrayG[1]->bycenter + barrayG[1]->bbottom - 1 ; for( adj = ptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( ptr == segptr->pin1ptr ) { core_ptr = segptr->pin2ptr ; } else { core_ptr = segptr->pin1ptr ; } if( pptr = carrayG[core_ptr->cell]->padptr ){ padside = pptr->padside ; } else { padside = 0 ; } if( padside || core_ptr->row > 1 ) { continue ; } else { x = core_ptr->xpos ; #ifdef NSC fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d 1 -1 0 0 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -3 1 0 0 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y ) ; #else fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d 1 -1 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -3 1 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y ) ; #endif } } } static do_top_channel( ptr ) PINBOXPTR ptr ; { INT x , y , groupS_number , layer , i ; char tmp_char[2] , *tmp_pinname ; ADJASEG *adj ; SEGBOXPTR segptr ; PINBOXPTR core_ptr ; PADBOXPTR pptr ; INT length ; INT padside ; char master_name[128] , pin_id[128] , *tmp_name[128] ; char instance_name[128] , p_name[128] , *tmp_string ; groupS_number = groupS[ ptr->newy ] ; tmp_pinname = find_layer( ptr->pinname, &layer ) ; #ifdef NSC length = strcspn( tmp_pinname , ":" ) ; if( length < strlen( tmp_pinname ) ) { tmp_string = strtok( tmp_pinname , ":" ) ; sprintf( p_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( pin_id , "%s" , tmp_string ) ; } else { sprintf( p_name , "%s" , tmp_pinname ) ; sprintf( pin_id , "%s" , "0" ) ; } strcpy( tmp_name , carrayG[ptr->cell]->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; sprintf( master_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( master_name , "%s" , tmp_name ) ; sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpS,"%s %d %s %s %d %d -4 1 %d %s %s\n" , netarrayG[ptr->net]->name , groupS_number , instance_name , p_name , ptr->xpos , ptr->ypos , layer , master_name , pin_id ); #else fprintf(fpS,"%s %d %s %s %d %d -4 1 %d\n" , netarrayG[ptr->net]->name , groupS_number , carrayG[ptr->cell]->cname , tmp_pinname , ptr->xpos , ptr->ypos , layer ); #endif y = barrayG[numRowsG]->bycenter + barrayG[numRowsG]->btop + 1 ; for( adj = ptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( ptr == segptr->pin1ptr ) { core_ptr = segptr->pin2ptr ; } else { core_ptr = segptr->pin1ptr ; } if( pptr = carrayG[core_ptr->cell]->padptr ){ padside = pptr->padside ; } else { padside = 0 ; } if( padside || core_ptr->row < numRowsG ) { continue ; } else { x = core_ptr->xpos ; #ifdef NSC fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d 1 0 0 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y , numChansG ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -4 -1 0 0 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y ) ; #else fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d 1 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y , numChansG ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -4 -1 0\n" , netarrayG[ptr->net]->name , groupS_number , x , y ) ; #endif } } } char *find_layer( pinname, layer ) char *pinname ; INT *layer ; { static char pinbufL[LRECL] ; char layer_buffer[2] ; ASSERTNRETURN( pinname,"find_layer", "pinname is NULL" ) ; if( pin_layers_givenG ) { /* transform "]2name" --> "name" and layer = 2 */ if( pinname && *pinname == ']' ){ layer_buffer[0] = pinname[1] ; layer_buffer[1] = EOS ; *layer = atoi( layer_buffer ) ; strcpy( pinbufL, &(pinname[2]) ) ; } else { *layer = feedLayerG ; strcpy( pinbufL, pinname ) ; } } else { *layer = 0 ; strcpy( pinbufL, pinname ) ; } return( pinbufL ) ; } /* end find_layer */ set_pin_format( flag ) BOOL flag ; { old_formatS = flag ; } /* end set_pin_format */ graywolf-0.1.4+20170307gite1bf319/src/twsc/outpins1.c000066400000000000000000000650251305746555600214710ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * Copyright (C) 2015 Staf Verhaegen * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: outpins.c DESCRIPTION:output the pin (global route) information. CONTENTS: outpins() do_outpins( ptr , flag ) PINBOXPTR ptr ; int flag ; do_left_pseudo_pins( ptr , channel , group_number ) PINBOXPTR ptr ; int channel , group_number ; do_right_pseudo_pins( ptr , channel , group_number ) PINBOXPTR ptr ; int channel , group_number ; do_left_vertical_channel( ptr ) PINBOXPTR ptr ; do_right_vertical_channel( ptr ) PINBOXPTR ptr ; do_bottom_channel( ptr ) PINBOXPTR ptr ; do_top_channel( ptr ) PINBOXPTR ptr ; DATE: Mar 27, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) outpins1.c (Yale) version 1.3 4/18/91" ; #endif #endif #include #include "standard.h" #include "groute.h" #include "main.h" #include "readpar.h" #include "pads.h" #include /* #define NSC */ char *strtok() ; /* global variables */ extern INT *root_G ; extern INT *count_G ; extern INT *stack_G ; extern INT *father_G ; extern INT Max_numPinsG ; extern BOOL new_row_formatG ; extern PINBOXPTR *vertex_G ; extern char *find_layer() ; /* static definitions */ static INT vtxS ; static INT *hashS ; static INT *groupS ; static INT numpinS ; static INT *rite_edgeS ; static INT *left_edgeS ; static FILE *fpS ; static do_outpins(); static do_vertical_channel(); static do_left_vertical_channel(); static do_right_vertical_channel(); static do_bottom_channel(); static do_top_channel(); old_outpins() { PINBOXPTR ptr1 , ptr2 , ptr ; CBOXPTR cellptr ; SEGBOXPTR seg ; PADBOXPTR pp1, pp2 ; char filename[64] ; int i , a , b , net , row , padside ; int upFlag , downFlag , group_index ; hashS = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( int ) ) ; groupS = (INT *)Ysafe_malloc( 2 * Max_numPinsG * sizeof( int ) ) ; rite_edgeS = (INT *)Ysafe_malloc( numChansG * sizeof( int ) ) ; left_edgeS = (INT *)Ysafe_malloc( numChansG * sizeof( int ) ) ; for( row = 1 ; row <= numRowsG ; row++ ) { cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; rite_edgeS[row] = cellptr->cxcenter + cellptr->tileptr->right ; } for( row = 1 ; row <= numRowsG ; row++ ) { left_edgeS[row] = barrayG[row]->bxcenter + barrayG[row]->bleft ; } sprintf( filename , "%s.pin" , cktNameG ) ; fpS = TWOPEN ( filename , "w", ABORT ) ; group_index = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { vtxS = 0 ; for( ptr = netarrayG[net]->pins ; ptr ; ptr = ptr->next ) { vertex_G[ ++vtxS ] = ptr ; ptr->newy = vtxS ; } numpinS = vtxS ; if( numpinS <= 1 ) { continue ; } for( ptr = netarrayG[net]->pins ; ptr ; ptr = ptr->next ) { vertex_G[ ++vtxS ] = ptr ; } for( i = 1 ; i <= vtxS ; i++ ) { count_G[i] = 1 ; father_G[i] = 0 ; root_G[i] = i ; hashS[i] = 0 ; groupS[i] = 0 ; } for( seg = netsegHeadG[net]->next ; seg ; seg = seg->next ) { ptr1 = seg->pin1ptr ; ptr2 = seg->pin2ptr ; if( seg->switchvalue == swUP ) { a = find_set_name( ptr1->newy + numpinS ) ; b = find_set_name( ptr2->newy + numpinS ) ; } else if( seg->switchvalue == swDOWN ) { a = find_set_name( ptr1->newy ) ; b = find_set_name( ptr2->newy ) ; } else if( ptr1->row > ptr2->row ) { a = find_set_name( ptr1->newy ) ; b = find_set_name( ptr2->newy + numpinS ) ; } else if( ptr1->row < ptr2->row ) { a = find_set_name( ptr1->newy + numpinS ) ; b = find_set_name( ptr2->newy ) ; } else if( ptr1->row == 0 ) { a = find_set_name( ptr1->newy + numpinS ) ; b = find_set_name( ptr2->newy + numpinS ) ; } else if( ptr1->row == numChansG ) { a = find_set_name( ptr1->newy ) ; b = find_set_name( ptr2->newy ) ; } else if( (pp1 = carrayG[ptr1->cell]->padptr) && pp1->padside && (pp2 = carrayG[ptr2->cell]->padptr) && pp2->padside ) { a = find_set_name( ptr1->newy ) ; b = find_set_name( ptr2->newy ) ; } else if( seg->flag > ptr1->row ) { a = find_set_name( ptr1->newy + numpinS ) ; b = find_set_name( ptr2->newy + numpinS ) ; } else { a = find_set_name( ptr1->newy ) ; b = find_set_name( ptr2->newy ) ; } do_set_union( a , b ) ; } for( ptr = netarrayG[net]->pins ; ptr ; ptr = ptr->next ) { if( (pp1 = carrayG[ptr->cell]->padptr) && pp1->padside ) { a = find_set_name( ptr->newy + numpinS ) ; b = find_set_name( ptr->newy ) ; do_set_union( a , b ) ; } } for( i = 1 ; i <= vtxS ; i++ ) { a = find_set_name( i ) ; if( count_G[a] > 1 ) { if( hashS[a] == 0 ) { groupS[i] = ++group_index ; hashS[a] = group_index ; } else { groupS[i] = hashS[a] ; } } } for( ptr = netarrayG[net]->pins ; ptr ; ptr = ptr->next ) { a = find_set_name( ptr->newy + numpinS ) ; if( count_G[a] > 1 ) { upFlag = 1 ; } else { upFlag = 0 ; } b = find_set_name( ptr->newy ) ; if( count_G[b] > 1 ) { downFlag = 1 ; } else { downFlag = 0 ; } pp1 = carrayG[ ptr->cell ]->padptr ; if( pp1 ){ padside = pp1->padside ; } else { padside = 0 ; } if( !padside ) { if( upFlag ) { do_outpins( ptr , 1 ) ; } if( downFlag ) { do_outpins( ptr , 0 ) ; } } else { if( ptr->row == 0 && padside != L && padside != R ) { if( rowsG == 0 && new_row_formatG == 0 ) { do_outpins( ptr , 1 ) ; } else { do_bottom_channel( ptr ) ; } } else if( ptr->row == numChansG && padside != L && padside != R ) { if( rowsG == 0 && new_row_formatG == 0 ) { do_outpins( ptr , 0 ) ; } else { do_top_channel( ptr ) ; } } else if( rowsG > 0 ) { do_vertical_channel( ptr ) ; } else if( ptr->xpos > rite_edgeS[ptr->row] || padside == R || padside == MR || padside == MUR || padside == MLR ) { do_right_vertical_channel( ptr ) ; } else { do_left_vertical_channel( ptr ) ; } } } /* the group index for vertex_G[i] = groupS[ find_group_name(i) ] */ } Ysafe_free( groupS ) ; groupS = NULL ; Ysafe_free( hashS ) ; hashS = NULL ; Ysafe_free( left_edgeS ) ; left_edgeS = NULL ; Ysafe_free( rite_edgeS ) ; rite_edgeS = NULL ; TWCLOSE( fpS ) ; } /*------------------------------------------------------------------ * * The nine field have to be written down to cktname.pin file are : * * 1. Name of net to which the pn belongs. * * 2. Group number of the pin. * * 3. Cell name to which the pin belongs * * 4. The name of the pin. * * 5. The x coordinate of the pin. * * 6. The y coordinate of the pin. * * 7. The channel to which the pin belong to. * * 8. Where the pin is at the top (1) , bottom (-1) or neither (0) * * 9. 0 * *-------------------------------------------------------------------*/ static do_outpins( ptr , flag ) PINBOXPTR ptr ; int flag ; { int x , y , channel , pinloc , group_number , layer , i ; CBOXPTR cellptr ; PADBOXPTR pptr ; char *pinname , *tmp_pinname ; int length ; char master_name[128] , pin_id[128] , tmp_name[128] ; char instance_name[128] , p_name[128] , *tmp_string ; cellptr = carrayG[ ptr->cell ] ; if( flag ) { channel = ptr->row + 1 ; group_number = groupS[ ptr->newy + numpinS ] ; pinloc = -1 ; y = cellptr->cycenter + cellptr->tileptr->top ; } else { channel = ptr->row ; group_number = groupS[ ptr->newy ] ; pinloc = 1 ; y = cellptr->cycenter + cellptr->tileptr->bottom ; } if( (pptr = cellptr->padptr) && pptr->padside ) { pinname = ptr->pinname ; x = ptr->xpos ; } else { if( ptr->eqptr ) { /* there is at least one equivalent pin */ if( cellptr->corient == 0 ) { if( flag ) { /* pin is on top side of the row */ if( ptr->eqptr->typos > 0 ) { /* equivalent pin is on top side of the row when the cell orientation is "0" */ pinname = ptr->eqptr->pinname ; x = ptr->xpos + ptr->eqptr->txoff ; } else { /* equivalent pin is on the bottom side of the row when the cell orientation is "0" */ pinname = ptr->pinname ; x = ptr->xpos ; } } else { /* pin is on bottom side of the row */ if( ptr->eqptr->typos < 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos + ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } } else if( cellptr->corient == 1 ) { /* mirror about x-axis */ if( flag ) { if( ptr->eqptr->typos < 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos + ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } else { if( ptr->eqptr->typos > 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos + ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } } else if( cellptr->corient == 2 ) { /* mirror about y-axis */ if( flag ) { if( ptr->eqptr->typos > 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos - ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } else { if( ptr->eqptr->typos < 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos - ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } } else { /* 180 degree rotation w.r.t orientation 0 */ if( flag ) { if( ptr->eqptr->typos < 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos - ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } else { if( ptr->eqptr->typos > 0 ) { pinname = ptr->eqptr->pinname ; x = ptr->xpos - ptr->eqptr->txoff ; } else { pinname = ptr->pinname ; x = ptr->xpos ; } } } } else { pinname = ptr->pinname ; x = ptr->xpos ; } } tmp_pinname = find_layer( pinname, &layer ) ; #ifdef NSC length = strcspn( tmp_pinname , ":" ) ; if( length < strlen( tmp_pinname ) ) { tmp_string = strtok( tmp_pinname , ":" ) ; sprintf( p_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( pin_id , "%s" , tmp_string ) ; } else { sprintf( p_name , "%s" , tmp_pinname ) ; sprintf( pin_id , "%s" , "0" ) ; } strcpy( tmp_name , carrayG[ptr->cell]->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; sprintf( master_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( master_name , "%s" , tmp_name ) ; sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpS,"%s %d %s %s %d %d %d %d %d %s %s\n" , netarrayG[ptr->net]->name , group_number , instance_name , p_name , x , y , channel , pinloc , layer , master_name , pin_id ); #else fprintf(fpS,"%s %d %s %s %d %d %d %d %d\n" , netarrayG[ptr->net]->name , group_number , carrayG[ptr->cell]->cname , tmp_pinname , x , y , channel , pinloc , layer ); #endif return ; } static do_pseudo_pins( ptr , channel , group_number ) PINBOXPTR ptr ; int channel , group_number ; { int x , y , x_1 , x_2 , y_middle , top_row , bot_row , exit_end ; /* outer-channel-bounding box */ int outer_ch_bb_llx ; int outer_ch_bb_lly ; int outer_ch_bb_urx ; int outer_ch_bb_ury ; if( channel == numRowsG + 1 ) { outer_ch_bb_llx = barrayG[numRowsG]->bxcenter + barrayG[numRowsG]->bleft ; outer_ch_bb_urx = barrayG[numRowsG]->bxcenter + barrayG[numRowsG]->bright ; outer_ch_bb_lly = barrayG[numRowsG]->bycenter + barrayG[numRowsG]->btop ; outer_ch_bb_ury = outer_ch_bb_lly + 1 ; y_middle = outer_ch_bb_lly ; } else if( channel == 1 ) { outer_ch_bb_llx = barrayG[1]->bxcenter + barrayG[1]->bleft ; outer_ch_bb_urx = barrayG[1]->bxcenter + barrayG[1]->bright ; outer_ch_bb_ury = barrayG[1]->bycenter + barrayG[1]->bbottom ; outer_ch_bb_lly = outer_ch_bb_ury - 1 ; y_middle = outer_ch_bb_ury + 1 ; } else { top_row = channel ; bot_row = channel - 1 ; x_1 = barrayG[bot_row]->bxcenter + barrayG[bot_row]->bleft ; x_2 = barrayG[top_row]->bxcenter + barrayG[top_row]->bleft ; if( x_1 < x_2 ) { outer_ch_bb_llx = x_1 ; } else { outer_ch_bb_llx = x_2 ; } x_1 = barrayG[bot_row]->bxcenter + barrayG[bot_row]->bright ; x_2 = barrayG[top_row]->bxcenter + barrayG[top_row]->bright ; if( x_1 > x_2 ) { outer_ch_bb_urx = x_1 ; } else { outer_ch_bb_urx = x_2 ; } outer_ch_bb_ury = barrayG[top_row]->bycenter + barrayG[top_row]->bbottom ; outer_ch_bb_lly = barrayG[bot_row]->bycenter + barrayG[bot_row]->btop ; y_middle = (outer_ch_bb_lly + outer_ch_bb_ury) / 2 ; } /* we have to set exit_end to -2 for exit left (or 2 for exit right) */ /* OR: /* we have to set exit_end to -1 for bottom (or 1 for top of channel) */ if( ptr->xpos >= outer_ch_bb_llx && ptr->xpos <= outer_ch_bb_urx ) { /* exit_end will be either 1 or -1 */ if( ptr->ypos > y_middle ) { exit_end = 1 ; x = ptr->xpos ; y = outer_ch_bb_ury ; } else { exit_end = -1 ; x = ptr->xpos ; y = outer_ch_bb_lly ; } } else if( ptr->xpos < outer_ch_bb_llx ) { exit_end = -2 ; x = outer_ch_bb_llx ; y = y_middle ; } else { exit_end = 2 ; x = outer_ch_bb_urx ; y = y_middle ; } #ifdef NSC fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d %d 0 0 0\n" , netarrayG[ptr->net]->name , group_number , x , y , channel, exit_end ) ; #else fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d %d 0\n" , netarrayG[ptr->net]->name , group_number , x , y , channel, exit_end ) ; #endif } static do_left_pseudo_pins( ptr , channel , group_number ) PINBOXPTR ptr ; int channel , group_number ; { int x , y ; if( channel <= numRowsG ) { y = barrayG[channel]->bycenter - rowHeightG ; } else { y = barrayG[ numRowsG ]->bycenter + rowHeightG ; } if( channel == 1 ) { x = left_edgeS[1] ; } else if( channel == numChansG ) { x = left_edgeS[numRowsG] ; } else { if( left_edgeS[channel] <= left_edgeS[channel-1] ) { x = left_edgeS[channel] ; } else { x = left_edgeS[channel-1] ; } } #ifdef NSC fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d -2 0 0 0\n" , netarrayG[ptr->net]->name , group_number , x , y , channel ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -1 -1 0 0 0\n" , netarrayG[ptr->net]->name , group_number , x , y ) ; #else fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d -2 0\n" , netarrayG[ptr->net]->name , group_number , x , y , channel ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -1 -1 0\n" , netarrayG[ptr->net]->name , group_number , x , y ) ; #endif } static do_right_pseudo_pins( ptr , channel , group_number ) PINBOXPTR ptr ; int channel , group_number ; { int x , y ; if( channel == 1 ) { y = barrayG[1]->bycenter - rowHeightG ; x = rite_edgeS[1] ; } else if( channel <= numRowsG ) { y = barrayG[channel]->bycenter - rowHeightG ; if( rite_edgeS[channel] < rite_edgeS[channel-1] ) { x = rite_edgeS[channel] ; } else { x = rite_edgeS[channel-1] ; } } else { y = barrayG[numRowsG]->bycenter + rowHeightG ; x = rite_edgeS[numRowsG] ; } #ifdef NSC fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d 2 0 0 0\n" , netarrayG[ptr->net]->name , group_number , x , y , channel ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -2 -1 0 0 0\n" , netarrayG[ptr->net]->name , group_number , x , y ) ; #else fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d 2 0\n" , netarrayG[ptr->net]->name , group_number , x , y , channel ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -2 -1 0\n" , netarrayG[ptr->net]->name , group_number , x , y ) ; #endif } static do_vertical_channel( ptr ) PINBOXPTR ptr ; { PINBOXPTR core_ptr ; SEGBOXPTR segptr ; ADJASEG *adj ; PADBOXPTR pptr ; int group_number , i , padside ; group_number = groupS[ ptr->newy ] ; for( adj = ptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( ptr == segptr->pin1ptr ) { core_ptr = segptr->pin2ptr ; } else { core_ptr = segptr->pin1ptr ; } pptr = carrayG[core_ptr->cell]->padptr ; if( pptr ){ padside = pptr->padside ; } else { padside = 0 ; } if( !padside ){ do_pseudo_pins( ptr, segptr->flag , group_number ) ; /* **** */ } else { if( ptr->xpos > rite_edgeS[ptr->row] || padside == R || padside == MR || padside == MUR || padside == MLR ) { do_right_vertical_channel( ptr ) ; } else { do_left_vertical_channel( ptr ) ; } } /* **** */ } } static do_left_vertical_channel( ptr ) PINBOXPTR ptr ; { PINBOXPTR core_ptr ; SEGBOXPTR segptr ; ADJASEG *adj ; PADBOXPTR pptr ; int group_number , layer , i ; int length ; char *tmp_pinname ; char master_name[128] , pin_id[128] , tmp_name[128] ; char instance_name[128] , p_name[128] , *tmp_string ; group_number = groupS[ ptr->newy ] ; tmp_pinname = find_layer( ptr->pinname, &layer ) ; #ifdef NSC length = strcspn( tmp_pinname , ":" ) ; if( length < strlen( tmp_pinname ) ) { tmp_string = strtok( tmp_pinname , ":" ) ; sprintf( p_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( pin_id , "%s" , tmp_string ) ; } else { sprintf( p_name , "%s" , tmp_pinname ) ; sprintf( pin_id , "%s" , "0" ) ; } strcpy( tmp_name , carrayG[ptr->cell]->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; sprintf( master_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( master_name , "%s" , tmp_name ) ; sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpS,"%s %d %s %s %d %d -1 1 %d %s %s\n" , netarrayG[ptr->net]->name , group_number , instance_name , p_name , ptr->xpos , ptr->ypos , layer , master_name , pin_id ); #else fprintf(fpS,"%s %d %s %s %d %d -1 1 %d\n" , netarrayG[ptr->net]->name , group_number , carrayG[ptr->cell]->cname , tmp_pinname , ptr->xpos , ptr->ypos , layer ) ; #endif for( adj = ptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( ptr == segptr->pin1ptr ) { core_ptr = segptr->pin2ptr ; } else { core_ptr = segptr->pin1ptr ; } pptr = carrayG[core_ptr->cell]->padptr ; if( !pptr || pptr->padside == 0 ){ do_left_pseudo_pins( ptr, segptr->flag , group_number ) ; } } } static do_right_vertical_channel( ptr ) PINBOXPTR ptr ; { PINBOXPTR core_ptr ; SEGBOXPTR segptr ; ADJASEG *adj ; PADBOXPTR pptr ; int a , group_number , layer , i ; char *tmp_pinname ; int length ; char master_name[128] , pin_id[128] , tmp_name[128] ; char instance_name[128] , p_name[128] , *tmp_string ; group_number = groupS[ ptr->newy ] ; tmp_pinname = find_layer( ptr->pinname, &layer ) ; #ifdef NSC length = strcspn( tmp_pinname , ":" ) ; if( length < strlen( tmp_pinname ) ) { tmp_string = strtok( tmp_pinname , ":" ) ; sprintf( p_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( pin_id , "%s" , tmp_string ) ; } else { sprintf( p_name , "%s" , tmp_pinname ) ; sprintf( pin_id , "%s" , "0" ) ; } strcpy( tmp_name , carrayG[ptr->cell]->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; sprintf( master_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( master_name , "%s" , tmp_name ) ; sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpS,"%s %d %s %s %d %d -2 1 %d %s %s\n" , netarrayG[ptr->net]->name , group_number , instance_name , p_name , ptr->xpos , ptr->ypos , layer , master_name , pin_id ); #else fprintf(fpS,"%s %d %s %s %d %d -2 1 %d\n" , netarrayG[ptr->net]->name , group_number , carrayG[ptr->cell]->cname, tmp_pinname , ptr->xpos , ptr->ypos , layer ) ; #endif for( adj = ptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( ptr == segptr->pin1ptr ) { core_ptr = segptr->pin2ptr ; } else { core_ptr = segptr->pin1ptr ; } pptr = carrayG[core_ptr->cell]->padptr ; if( !pptr || pptr->padside == 0 ){ do_right_pseudo_pins( ptr, segptr->flag , group_number) ; } } } static do_bottom_channel( ptr ) PINBOXPTR ptr ; { int x , y , group_number , layer , i ; char *tmp_pinname ; ADJASEG *adj ; SEGBOXPTR segptr ; PINBOXPTR core_ptr ; PADBOXPTR pptr ; int length ; char master_name[128] , pin_id[128] , tmp_name[128] ; char instance_name[128] , p_name[128] , *tmp_string ; group_number = groupS[ ptr->newy ] ; tmp_pinname = find_layer( ptr->pinname, &layer ) ; strcpy( tmp_pinname , ptr->pinname ) ; #ifdef NSC length = strcspn( tmp_pinname , ":" ) ; if( length < strlen( tmp_pinname ) ) { tmp_string = strtok( tmp_pinname , ":" ) ; sprintf( p_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( pin_id , "%s" , tmp_string ) ; } else { sprintf( p_name , "%s" , tmp_pinname ) ; sprintf( pin_id , "%s" , "0" ) ; } strcpy( tmp_name , carrayG[ptr->cell]->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; sprintf( master_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( master_name , "%s" , tmp_name ) ; sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpS,"%s %d %s %s %d %d -3 -1 %d %s %s\n" , netarrayG[ptr->net]->name , group_number , instance_name , p_name , ptr->xpos , ptr->ypos , layer , master_name , pin_id ); #else fprintf(fpS,"%s %d %s %s %d %d -3 -1 %d\n" , netarrayG[ptr->net]->name , group_number , carrayG[ptr->cell]->cname , tmp_pinname , ptr->xpos , ptr->ypos , layer ); #endif y = barrayG[1]->bycenter + barrayG[1]->bbottom - 1 ; for( adj = ptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( ptr == segptr->pin1ptr ) { core_ptr = segptr->pin2ptr ; } else { core_ptr = segptr->pin1ptr ; } pptr = carrayG[core_ptr->cell]->padptr ; if( pptr && pptr->padside || core_ptr->row > 1 ) { continue ; } else { x = core_ptr->xpos ; #ifdef NSC fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d 1 -1 0 0 0\n" , netarrayG[ptr->net]->name , group_number , x , y ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -3 1 0 0 0\n" , netarrayG[ptr->net]->name , group_number , x , y ) ; #else fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d 1 -1 0\n" , netarrayG[ptr->net]->name , group_number , x , y ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -3 1 0\n" , netarrayG[ptr->net]->name , group_number , x , y ) ; #endif } } } static do_top_channel( ptr ) PINBOXPTR ptr ; { int x , y , group_number , layer , i ; char *tmp_pinname ; ADJASEG *adj ; SEGBOXPTR segptr ; PINBOXPTR core_ptr ; PADBOXPTR pptr ; int length ; char master_name[128] , pin_id[128] , tmp_name[128] ; char instance_name[128] , p_name[128] , *tmp_string ; group_number = groupS[ ptr->newy ] ; tmp_pinname = find_layer( ptr->pinname, &layer ) ; #ifdef NSC length = strcspn( tmp_pinname , ":" ) ; if( length < strlen( tmp_pinname ) ) { tmp_string = strtok( tmp_pinname , ":" ) ; sprintf( p_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( pin_id , "%s" , tmp_string ) ; } else { sprintf( p_name , "%s" , tmp_pinname ) ; sprintf( pin_id , "%s" , "0" ) ; } strcpy( tmp_name , carrayG[ptr->cell]->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; sprintf( master_name , "%s" , tmp_string ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( master_name , "%s" , tmp_name ) ; sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpS,"%s %d %s %s %d %d -4 1 %d %s %s\n" , netarrayG[ptr->net]->name , group_number , instance_name , p_name , ptr->xpos , ptr->ypos , layer , master_name , pin_id ); #else fprintf(fpS,"%s %d %s %s %d %d -4 1 %d\n" , netarrayG[ptr->net]->name , group_number , carrayG[ptr->cell]->cname , tmp_pinname , ptr->xpos , ptr->ypos , layer ); #endif y = barrayG[numRowsG]->bycenter + barrayG[numRowsG]->btop + 1 ; for( adj = ptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( ptr == segptr->pin1ptr ) { core_ptr = segptr->pin2ptr ; } else { core_ptr = segptr->pin1ptr ; } pptr = carrayG[core_ptr->cell]->padptr ; if( pptr && pptr->padside || core_ptr->row < numRowsG ) { continue ; } else { x = core_ptr->xpos ; #ifdef NSC fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d 1 0 0 0\n" , netarrayG[ptr->net]->name , group_number , x , y , numChansG ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -4 -1 0 0 0\n" , netarrayG[ptr->net]->name , group_number , x , y ) ; #else fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d %d 1 0\n" , netarrayG[ptr->net]->name , group_number , x , y , numChansG ) ; fprintf(fpS,"%s %d PSEUDO_CELL PSEUDO_PIN %d %d -4 -1 0\n" , netarrayG[ptr->net]->name , group_number , x , y ) ; #endif } } } graywolf-0.1.4+20170307gite1bf319/src/twsc/output.c000066400000000000000000000365171305746555600212530ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: output.c DESCRIPTION:output the placement information. CONTENTS: output() final_free_up() create_cel_file() DATE: Mar 27, 1989 REVISIONS: July 15, 1989 Oct 2, 1990 - removed elim_unused feeds and added check for clength == 0. Wed Jan 16 14:25:22 PST 1991 - commented out free of pairArrayG. Wed Jan 23 02:43:33 PST 1991 - output at density. Sat May 4 13:47:58 EDT 1991 - now output row field similar to global routing definition. Tue Aug 13 12:47:54 CDT 1991 - fixed create new cell file. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) output.c (Yale) version 4.14 9/23/91" ; #endif #endif /* #define DEC */ /* added on 06/01/90 Sury */ /* #define NSC */ #include "standard.h" #include "groute.h" #include "main.h" #include "readpar.h" #include "config.h" #include "pads.h" #include #include #include /* external functions */ char *strtok(); /* added 06/01/90 sury */ INT comparex() ; /* global variables */ extern INT spacer_widthG ; extern INT actual_feed_thru_cells_addedG ; extern BOOL output_at_densityG ; extern BOOL create_new_cel_fileG ; extern BOOL unused_feed_name_twspacerG ; extern BOOL stand_cell_as_gate_arrayG ; /* static definitions */ static char a_lineS[LRECL] ; output() { FILE *fpp1 , *fpp2 ; INT locx , locy , height , width ; INT xloc , i , cell , block , orient ; INT num ; INT xloc2 , yloc2 , yloc ; INT *array , desire , k , limit ; INT left , right , bottom , top , end ; INT *deleted_feeds ; INT eliminated_feeds ; char filename[LRECL] , ctmp[32] ; CBOXPTR cellptr ; TIBOXPTR tptr ; PADBOXPTR pptr ; /* added on 06/01/90 Sury */ INT length; INT row ; char instance_name[LRECL], tmp_name[LRECL], *tmp_string; deleted_feeds = (INT *) Ysafe_malloc( numcellsG * sizeof(INT) ) ; eliminated_feeds = 0 ; sprintf( filename , "%s.pl1" , cktNameG ) ; fpp1 = TWOPEN( filename , "w", ABORT ) ; sprintf( filename , "%s.pl2" , cktNameG ) ; fpp2 = TWOPEN( filename , "w", ABORT ) ; for( block = 1 ; block <= numRowsG ; block++ ) { left = barrayG[block]->bxcenter + barrayG[block]->bleft ; right = barrayG[block]->bxcenter + barrayG[block]->bright ; bottom = barrayG[block]->bycenter + barrayG[block]->bbottom ; top = barrayG[block]->bycenter + barrayG[block]->btop ; if( restartG == 0 && costonlyG == 1 ) { desire = barrayG[block]->desire ; } else { if( pairArrayG[block][0] > 0 ) { cell = pairArrayG[block][ pairArrayG[block][0] ] ; end = carrayG[cell]->cxcenter + carrayG[cell]->tileptr ->right ; desire = end - left ; } else { desire = 0 ; } } if( barrayG[block]->borient > 0 ) { fprintf(fpp2,"%d %d %d %d %d 0 0\n", block , left, bottom, left + desire, top ) ; } else { fprintf(fpp2,"%d %d %d %d %d 0 0\n", block , left, bottom, right, bottom + desire ) ; } num = pairArrayG[block][0] ; if( num == 0 ) { continue ; } array = pairArrayG[block] + 1 ; for( i = 0 ; i < num ; i++ ) { cell = array[ i ] ; cellptr = carrayG[ cell ] ; if( cellptr->clength == 0 ){ continue ; } if( strcmp( cellptr->cname , "TW_EXCEPT" ) == 0 ) { continue ; } if( stand_cell_as_gate_arrayG ) { if( strcmp( cellptr->cname , "GATE_ARRAY_SPACER" ) == 0 ) { continue ; } } if( unused_feed_name_twspacerG ) { if( strncmp(cellptr->cname,"twfeed",6) == STRINGEQ ) { if( tearrayG[cellptr->imptr->terminal] == NULL ) { strcpy( ctmp , cellptr->cname ) ; cellptr->cname = (char *) Ysafe_realloc( cellptr->cname, (strlen(cellptr->cname)+3) * sizeof(char) ) ; sprintf( cellptr->cname , "%s%s" , "twspacer", strpbrk(ctmp, "0123456789") ) ; } } } orient = cellptr->corient ; xloc = cellptr->cxcenter + cellptr->tileptr->left ; yloc = cellptr->cycenter + cellptr->tileptr->bottom ; xloc2 = cellptr->tileptr->right - cellptr->tileptr->left ; yloc2 = cellptr->tileptr->top - cellptr->tileptr->bottom ; /* The following code was added on 06/01/90 Sury */ #ifdef NSC strcpy( tmp_name , cellptr->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpp1,"%s %d %d %d %d %d %d\n", instance_name, xloc, yloc, xloc + xloc2, yloc + yloc2, orient, block ) ; #else fprintf(fpp1,"%s %d %d %d %d %d %d\n", cellptr->cname , xloc, yloc, xloc + xloc2, yloc + yloc2, orient, block ) ; #endif } } if( deleted_feeds[0] > 0 ) { fprintf(fpoG,"Confirming number of eliminated feeds:%d\n", eliminated_feeds ) ; } /* now output the pads and macros */ for( i = numcellsG + 1 ; i <= lastpadG ; i++ ) { cellptr = carrayG[ i ] ; orient = cellptr->corient ; tptr = cellptr->tileptr ; left = tptr->left ; right = tptr->right ; bottom = tptr->bottom ; top = tptr->top ; YtranslateT( &left, &bottom, &right, &top, orient ) ; locx = cellptr->cxcenter + left ; locy = cellptr->cycenter + bottom ; height = top - bottom ; width = right - left ; /* determine row */ pptr = cellptr->padptr ; if( pptr->macroNotPad ){ row = 0 ; } else { switch( pptr->padside ){ case L: row = - 1 ; break ; case T: row = -4 ; break ; case R: row = - 2 ; break ; case B: row = - 3 ; break ; default: M(ERRMSG,"output", "Unknown padside\n" ) ; } } #ifndef DEC /* The following code was added on 06/01/90 Sury */ #ifdef NSC strcpy( tmp_name , cellptr->cname ) ; length = strcspn( tmp_name , ":" ) ; if( length < strlen( tmp_name ) ) { tmp_string = strtok( tmp_name , ":" ) ; tmp_string = strtok( NULL , ":" ) ; sprintf( instance_name, "%s" , tmp_string ) ; } else { sprintf( instance_name , "%s" , tmp_name ) ; } fprintf(fpp1,"%s %d %d %d %d %d %d\n", instance_name, locx, locy, locx + width, locy + height, orient, row ) ; fprintf(fpp2,"%s %d %d %d %d %d %d\n", instance_name, locx, locy, locx + width, locy + height, orient, row ) ; #else /* normal case */ fprintf(fpp1,"%s %d %d %d %d %d %d\n", cellptr->cname , locx, locy, locx + width, locy + height, orient, row ) ; fprintf(fpp2,"%s %d %d %d %d %d %d\n", cellptr->cname , locx, locy, locx + width, locy + height, orient, row ) ; #endif #else /* DEC case */ fprintf(fpp1,"%s %d %d %d %d %d %d\n", cellptr->cname , locx, locy, locx + width, locy + height, orient, -cellptr->padside ) ; fprintf(fpp2,"%s %d %d %d %d %d %d\n", cellptr->cname , locx, locy, locx + width, locy + height, orient, -cellptr->padside ) ; #endif } TWCLOSE( fpp1 ) ; TWCLOSE( fpp2 ) ; if( create_new_cel_fileG ) { create_cel_file() ; } Ysafe_free( deleted_feeds ) ; return ; } final_free_up() { INT i, j, k, row, pin, net, cell, chan, track ; CBOXPTR cellptr ; DBOXPTR dimptr ; PINBOXPTR ptr, nextptr ; ADJASEGPTR adj, nextadj ; SEGBOXPTR segptr, nextseg ; CHANGRDPTR gdptr, nextgrd ; DENSITYPTR *hdptr ; IPBOXPTR imptr ; FEED_DATA *feedptr ; Ysafe_free( FeedInRowG ) ; for( row = 1 ; row <= numRowsG ; row++ ) { Ysafe_free( impFeedsG[row] ) ; } Ysafe_free( impFeedsG ) ; for( i = 1 ; i <= numRowsG ; i++ ) { feedptr = feedpptrG[i] ; for( j = 1 ; j <= chan_node_noG ; j++ ) { Ysafe_free( feedptr[j] ) ; } Ysafe_free( feedpptrG[i] ) ; } Ysafe_free( feedpptrG ) ; k = max_tdensityG + 100 ; for( chan = 1 ; chan <= numChansG ; chan++ ) { Ysafe_free( BeginG[chan]->netptr ) ; Ysafe_free( EndG[chan]->netptr ) ; for( gdptr = BeginG[chan] ; gdptr ; gdptr = nextgrd ) { nextgrd = gdptr->nextgrd ; Ysafe_free( gdptr->dptr ) ; Ysafe_free( gdptr ) ; } hdptr = DboxHeadG[chan] ; for( track = 0 ; track <= k ; track++ ) { Ysafe_free( hdptr[track] ) ; } Ysafe_free( DboxHeadG[chan] ) ; } Ysafe_free( BeginG ) ; Ysafe_free( EndG ) ; Ysafe_free( DboxHeadG ) ; Ysafe_free( maxTrackG ) ; Ysafe_free( nmaxTrackG ) ; k = maxtermG + 2 * numChansG ; for( pin = 1 ; pin <= k ; pin++ ) { Ysafe_free( TgridG[pin] ) ; } Ysafe_free( TgridG ) ; /* Not needed as this is done in findunlap.c for( i = 1 ; i <= numRowsG ; i++ ) { Ysafe_free( pairArrayG[i] ) ; } Ysafe_free( pairArrayG ) ; pairArrayG = NULL ; */ for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = carrayG[cell] ; imptr = cellptr->imptr ; if( imptr ) { for( ; imptr->next; imptr = imptr->next ) { if( imptr->next->cell != cell ) break ; } imptr->next = NULL ; } } fprintf( fpoG,"Actual # of Feed Cells Added:\t%d\n\n\n", actual_feed_thru_cells_addedG ) ; k = numcellsG + numtermsG + actual_feed_thru_cells_addedG ; for( cell = numcellsG + numtermsG + 1 ; cell <= k ; cell++ ) { cellptr = carrayG[cell] ; cellptr->imptr->next = NULL ; Ysafe_free( cellptr->cname ) ; Ysafe_free( cellptr->tileptr ) ; Ysafe_free( cellptr->imptr->pinname ) ; Ysafe_free( cellptr->imptr->eqpinname ) ; Ysafe_free( cellptr->imptr ) ; Ysafe_free( carrayG[cell] ) ; carrayG[cell] = NULL ; } actual_feed_thru_cells_addedG = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { for( segptr = netsegHeadG[net] ; segptr ; segptr = nextseg ) { nextseg = segptr->next ; Ysafe_free( segptr ) ; } dimptr = netarrayG[net] ; if( !dimptr->pins ) { continue ; } if( dimptr->pins->terminal > TotRegPinsG ) { for( ptr = dimptr->pins ; ptr ; ptr = nextptr ) { nextptr = ptr->next ; for( adj = ptr->adjptr ; adj ; adj = nextadj ) { nextadj = adj->next ; Ysafe_free( adj ) ; } Ysafe_free( ptr->eqptr ) ; if( nextptr->terminal <= TotRegPinsG ) break ; } dimptr->pins = nextptr ; } for( ptr = dimptr->pins ; ptr ; ptr = ptr->next ) { for( adj = ptr->adjptr->next ; adj ; adj = nextadj ) { nextadj = adj->next ; Ysafe_free( adj ) ; } ptr->adjptr->next = NULL ; } } Ysafe_free( netsegHeadG ) ; } create_cel_file() { FILE *fpoG2 , *fp ; char *token , fixed_string[32] , filename[256] ; char cell_name[32] ; INT ignore_line , block , offset , test , carrayG_index , is_a_cell ; if( rowsG > 0 ) { sprintf( filename , "%s.scel" , cktNameG ) ; fp = TWOPEN( filename, "r" , ABORT ) ; } else { sprintf( filename , "%s.cel" , cktNameG ) ; fp = TWOPEN( filename, "r" , ABORT ) ; } sprintf( filename , "%s.ncel" , cktNameG ) ; fpoG2 = TWOPEN( filename, "w" , ABORT ) ; strcpy( fixed_string , "" ) ; carrayG_index = 0 ; while( load_a_lineS(fp) ) { ignore_line = 0 ; if( (token = strtok( a_lineS , " " )) != NULL ) { if( strcmp( token , "cell" ) == 0 ) { is_a_cell = 1 ; fprintf(fpoG2, "%s ", token ) ; token = strtok( NULL , " " ) ; fprintf(fpoG2, "%s ", token ) ; strcpy( cell_name , strtok( NULL , " " ) ) ; fprintf(fpoG2, "%s ", cell_name ) ; do { test = strcmp( carrayG[ ++carrayG_index ]->cname, cell_name ) ; } while( test != 0 ) ; } else if( strcmp( token , "left" ) == 0 ) { if( is_a_cell ) { block = carrayG[carrayG_index]->cblock ; offset = carrayG[carrayG_index]->cxcenter + carrayG[carrayG_index]->tileptr->left - (barrayG[block]->bxcenter + barrayG[block]->bleft) ; if( strcmp( fixed_string , "" ) != 0 ) { add_new_line( offset , block , fixed_string , fpoG2 ) ; strcpy( fixed_string , "" ) ; } else { add_new_line( offset , block , "nonfixed" , fpoG2 ) ; } } fprintf(fpoG2, "%s ", token ) ; is_a_cell = 0 ; } else if( strcmp( token , "initially" ) == 0 ) { ignore_line = 1 ; strcpy( fixed_string , strtok( NULL , " " ) ) ; } else if( strcmp( token , "\n" ) != 0 ) { fprintf(fpoG2, "%s ", token ) ; } while( (token = strtok( NULL , " " )) != NULL ) { if( !ignore_line ) { fprintf(fpoG2, "%s ", token ) ; } } } if( !ignore_line ) { fprintf(fpoG2, "\n"); } } TWCLOSE(fp) ; TWCLOSE(fpoG2) ; } add_new_line( x_rel , block , fixed_ptr , fp ) INT x_rel , block ; char *fixed_ptr ; FILE *fp ; { fprintf(fp, "initially %s %d from left of block %d\n", fixed_ptr , x_rel , block ) ; return ; } load_a_lineS(fp) FILE *fp ; { INT i ; char tmp ; if( (int) (tmp = fgetc(fp)) != EOF ) { a_lineS[0] = tmp ; i = 1 ; if( tmp != '\n' ) { while( (a_lineS[i] = fgetc(fp)) != '\n' ) { i++ ; } } a_lineS[i] = '\0' ; return(1) ; } else { return(0) ; } } /* ******************************************************************** */ density() { /* set all the cells at density */ INT row ; INT cell ; INT block ; INT rowtop ; INT corient ; INT rowcenter ; CBOXPTR cellptr ; PINBOXPTR pin ; /* first update all the y coordinates of rows */ if (maxTrackG){ /* only perform if global routing is performed */ for( row = 1 ; row <= numRowsG ; row++ ) { if( row == 1 ){ rowcenter = barrayG[1]->bheight / 2 + maxTrackG[1]*track_pitchG + route2actG ; } else { rowcenter = rowtop + barrayG[row]->bheight / 2 + maxTrackG[row]*track_pitchG + route2actG ; } rowtop = rowcenter + barrayG[row]->bheight - barrayG[row]->bheight / 2; D( "twsc/buildDensityArray", fprintf( stderr, "row:%d oldy:%d newy:%d tracks:%d\n", row, barrayG[row]->bycenter, rowcenter, maxTrackG[row] ) ; ) ; barrayG[row]->bycenter = rowcenter ; } } else { return ; } for( cell = 1; cell <= numcellsG; cell++ ){ cellptr = carrayG[cell] ; block = cellptr->cblock ; corient = cellptr->corient ; if( block != 0 ){ cellptr->cycenter = barrayG[block]->bycenter ; /* update the y positions on this cell */ for( pin = cellptr->pins;pin;pin=pin->nextpin ) { pin->ypos = pin->typos[corient%2] + cellptr->cycenter; } } } } /* end density */ graywolf-0.1.4+20170307gite1bf319/src/twsc/overlap.c000066400000000000000000000262531305746555600213570ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: clean.c DESCRIPTION:overlap calculations. CONTENTS: new_old( c ) INT c ; old_assgnto_new1( alobin , ahibin , anewlobin , anewhibin ) INT alobin , ahibin , anewlobin , anewhibin ; new_assgnto_old1( alobin , ahibin , anewlobin , anewhibin ) INT alobin , ahibin , anewlobin , anewhibin ; old_assgnto_new2( a1lobin , a1hibin , a2lobin , a2hibin , b1lobin , b1hibin , b2lobin , b2hibin ) INT a1lobin , a1hibin , a2lobin , a2hibin ; INT b1lobin , b1hibin , b2lobin , b2hibin ; new_assgnto_old2( a1lobin , a1hibin , a2lobin , a2hibin , b1lobin , b1hibin , b2lobin , b2hibin ) INT a1lobin , a1hibin , a2lobin , a2hibin ; INT b1lobin , b1hibin , b2lobin , b2hibin ; sub_penal( startx , endx , block , LoBin , HiBin ) INT startx , endx , block , LoBin , HiBin ; add_penal( startx , endx , block , LoBin , HiBin ) INT startx , endx , block , LoBin , HiBin ; term_newpos( antrmptr , xcenter , ycenter , newaor ) TEBOXPTR antrmptr ; INT xcenter , ycenter , newaor ; DATE: Mar 27, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) overlap.c (Yale) version 4.3 9/7/90" ; #endif #endif #include "ucxxglb.h" new_old( c ) INT c ; { INT old, new ; if( ablockG != bblockG ) { barrayG[ablockG]->newsize = barrayG[ablockG]->oldsize + c ; barrayG[bblockG]->newsize = barrayG[bblockG]->oldsize - c ; old = ABS(barrayG[ablockG]->oldsize - barrayG[ablockG]->desire) + ABS(barrayG[bblockG]->oldsize - barrayG[bblockG]->desire) ; new = ABS(barrayG[ablockG]->newsize - barrayG[ablockG]->desire) + ABS(barrayG[bblockG]->newsize - barrayG[bblockG]->desire) ; newrowpenalG += (new - old) ; /* old = new = 0 ; if( ABS( ablockG - bblockG ) >= 3 ) { for( block = ablockG - 2 ; block <= ablockG ; block++ ) { if( block < 1 || block > numblock - 2 ) { continue ; } old_size = new_size = desired = 0 ; for( blk = block ; blk <= block + 2 ; blk++ ) { old_size += barrayG[blk]->oldsize ; desired += barrayG[blk]->desire ; if( blk == ablockG || blk == bblockG ) { new_size += barrayG[blk]->newsize ; } else { new_size += barrayG[blk]->oldsize ; } } old += ABS(old_size - desired) ; new += ABS(new_size - desired) ; } for( block = bblockG - 2 ; block <= bblockG ; block++ ) { if( block < 1 || block > numblock - 2 ) { continue ; } old_size = new_size = desired = 0 ; for( blk = block ; blk <= block + 2 ; blk++ ) { old_size += barrayG[blk]->oldsize ; desired += barrayG[blk]->desire ; if( blk == ablockG || blk == bblockG ) { new_size += barrayG[blk]->newsize ; } else { new_size += barrayG[blk]->oldsize ; } } old += ABS(old_size - desired) ; new += ABS(new_size - desired) ; } } else { mini = (ablockG < bblockG) ? ablockG - 2 : bblockG - 2 ; maxi = (ablockG > bblockG) ? ablockG : bblockG ; for( block = mini ; block <= maxi ; block++ ) { if( block < 1 || block > numblock - 2 ) { continue ; } old_size = new_size = desired = 0 ; for( blk = block ; blk <= block + 2 ; blk++ ) { old_size += barrayG[blk]->oldsize ; desired += barrayG[blk]->desire ; if( blk == ablockG || blk == bblockG ) { new_size += barrayG[blk]->newsize ; } else { new_size += barrayG[blk]->oldsize ; } } old += ABS(old_size - desired) ; new += ABS(new_size - desired) ; } } newrowpenalG += (new - old) ; */ } return ; } /* new_old( c ) INT c ; { INT old , new ; if( ablockG != bblockG ) { barrayG[ablockG]->newsize = barrayG[ablockG]->oldsize + c ; barrayG[bblockG]->newsize = barrayG[bblockG]->oldsize - c ; old = ABS(barrayG[ablockG]->oldsize - barrayG[ablockG]->desire) + ABS(barrayG[bblockG]->oldsize - barrayG[bblockG]->desire) ; new = ABS(barrayG[ablockG]->newsize - barrayG[ablockG]->desire) + ABS(barrayG[bblockG]->newsize - barrayG[bblockG]->desire) ; newrowpenalG += (new - old) ; } } */ old_assgnto_new1( alobin , ahibin , anewlobin , anewhibin ) INT alobin , ahibin , anewlobin , anewhibin ; { INT bin , lobin , hibin ; if( ablockG == bblockG ) { lobin = ( alobin <= anewlobin ) ? alobin : anewlobin ; hibin = ( ahibin >= anewhibin ) ? ahibin : anewhibin ; for( bin = lobin ; bin <= hibin ; bin++ ) { binptrG[ablockG][bin]->nupenalty = binptrG[ablockG][bin]->penalty ; } } else { for( bin = alobin ; bin <= ahibin ; bin++ ) { binptrG[ablockG][bin]->nupenalty = binptrG[ablockG][bin]->penalty ; } for( bin = anewlobin ; bin <= anewhibin ; bin++ ) { binptrG[bblockG][bin]->nupenalty = binptrG[bblockG][bin]->penalty ; } } } new_assgnto_old1( alobin , ahibin , anewlobin , anewhibin ) INT alobin , ahibin , anewlobin , anewhibin ; { INT bin , lobin , hibin ; if( ablockG == bblockG ) { lobin = ( alobin <= anewlobin ) ? alobin : anewlobin ; hibin = ( ahibin >= anewhibin ) ? ahibin : anewhibin ; for( bin = lobin ; bin <= hibin ; bin++ ) { binptrG[ablockG][bin]->penalty = binptrG[ablockG][bin]->nupenalty ; } } else { for( bin = alobin ; bin <= ahibin ; bin++ ) { binptrG[ablockG][bin]->penalty = binptrG[ablockG][bin]->nupenalty ; } for( bin = anewlobin ; bin <= anewhibin ; bin++ ) { binptrG[bblockG][bin]->penalty = binptrG[bblockG][bin]->nupenalty ; } } } old_assgnto_new2( a1lobin , a1hibin , a2lobin , a2hibin , b1lobin , b1hibin , b2lobin , b2hibin ) INT a1lobin , a1hibin , a2lobin , a2hibin ; INT b1lobin , b1hibin , b2lobin , b2hibin ; { INT clobin , chibin , dlobin , dhibin ; INT lobin , hibin , bin ; clobin = ( a1lobin <= b2lobin ) ? a1lobin : b2lobin ; chibin = ( a1hibin >= b2hibin ) ? a1hibin : b2hibin ; dlobin = ( a2lobin <= b1lobin ) ? a2lobin : b1lobin ; dhibin = ( a2hibin >= b1hibin ) ? a2hibin : b1hibin ; if( ablockG == bblockG ) { lobin = ( clobin <= dlobin ) ? clobin : dlobin ; hibin = ( chibin >= dhibin ) ? chibin : dhibin ; for( bin = lobin ; bin <= hibin ; bin++ ) { binptrG[ablockG][bin]->nupenalty = binptrG[ablockG][bin]->penalty ; } } else { for( bin = clobin ; bin <= chibin ; bin++ ) { binptrG[ablockG][bin]->nupenalty = binptrG[ablockG][bin]->penalty ; } for( bin = dlobin ; bin <= dhibin ; bin++ ) { binptrG[bblockG][bin]->nupenalty = binptrG[bblockG][bin]->penalty ; } } } new_assgnto_old2( a1lobin , a1hibin , a2lobin , a2hibin , b1lobin , b1hibin , b2lobin , b2hibin ) INT a1lobin , a1hibin , a2lobin , a2hibin ; INT b1lobin , b1hibin , b2lobin , b2hibin ; { INT clobin , chibin , dlobin , dhibin ; INT lobin , hibin , bin ; clobin = ( a1lobin <= b2lobin ) ? a1lobin : b2lobin ; chibin = ( a1hibin >= b2hibin ) ? a1hibin : b2hibin ; dlobin = ( a2lobin <= b1lobin ) ? a2lobin : b1lobin ; dhibin = ( a2hibin >= b1hibin ) ? a2hibin : b1hibin ; if( ablockG == bblockG ) { lobin = ( clobin <= dlobin ) ? clobin : dlobin ; hibin = ( chibin >= dhibin ) ? chibin : dhibin ; for( bin = lobin ; bin <= hibin ; bin++ ) { binptrG[ablockG][bin]->penalty = binptrG[ablockG][bin]->nupenalty ; } } else { for( bin = clobin ; bin <= chibin ; bin++ ) { binptrG[ablockG][bin]->penalty = binptrG[ablockG][bin]->nupenalty ; } for( bin = dlobin ; bin <= dhibin ; bin++ ) { binptrG[bblockG][bin]->penalty = binptrG[bblockG][bin]->nupenalty ; } } } sub_penal( startx , endx , block , LoBin , HiBin ) INT startx , endx , block , LoBin , HiBin ; { BINPTR bptr ; INT bin ; if( LoBin == HiBin ) { bptr = binptrG[block][LoBin] ; newbinpenalG -= ABS( bptr->nupenalty ) ; bptr->nupenalty -= endx - startx ; newbinpenalG += ABS( bptr->nupenalty ) ; } else { for( bin = LoBin ; bin <= HiBin ; bin++ ) { bptr = binptrG[block][bin] ; if( bin == LoBin ) { newbinpenalG -= ABS( bptr->nupenalty ) ; bptr->nupenalty -= bptr->right - startx ; newbinpenalG += ABS( bptr->nupenalty ) ; } else if( bin == HiBin ) { newbinpenalG -= ABS( bptr->nupenalty ) ; bptr->nupenalty -= endx - bptr->left ; newbinpenalG += ABS( bptr->nupenalty ) ; } else { newbinpenalG -= ABS( bptr->nupenalty ) ; bptr->nupenalty -= binWidthG ; newbinpenalG += ABS( bptr->nupenalty ) ; } } } } add_penal( startx , endx , block , LoBin , HiBin ) INT startx , endx , block , LoBin , HiBin ; { BINPTR bptr ; INT bin ; if( LoBin == HiBin ) { bptr = binptrG[block][LoBin] ; newbinpenalG -= ABS( bptr->nupenalty ) ; bptr->nupenalty += endx - startx ; newbinpenalG += ABS( bptr->nupenalty ) ; } else { for( bin = LoBin ; bin <= HiBin ; bin++ ) { bptr = binptrG[block][bin] ; if( bin == LoBin ) { newbinpenalG -= ABS( bptr->nupenalty ) ; bptr->nupenalty += bptr->right - startx ; newbinpenalG += ABS( bptr->nupenalty ) ; } else if( bin == HiBin ) { newbinpenalG -= ABS( bptr->nupenalty ) ; bptr->nupenalty += endx - bptr->left ; newbinpenalG += ABS( bptr->nupenalty ) ; } else { newbinpenalG -= ABS( bptr->nupenalty ) ; bptr->nupenalty += binWidthG ; newbinpenalG += ABS( bptr->nupenalty ) ; } } } } term_newpos( antrmptr , xcenter , ycenter , newaor ) PINBOXPTR antrmptr ; INT xcenter , ycenter , newaor ; { register PINBOXPTR pinptr ; for( pinptr = antrmptr ; pinptr; pinptr = pinptr->nextpin ) { netarrayG[ pinptr->net ]->dflag = 1 ; pinptr->flag = 1 ; pinptr->newx = pinptr->txpos[ newaor/2 ] + xcenter ; pinptr->newy = pinptr->typos[ newaor%2 ] + ycenter ; } } graywolf-0.1.4+20170307gite1bf319/src/twsc/pads.h000066400000000000000000000071471305746555600206440ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: pads.h CONTENTS: definitions for pad placement code. DATE: Aug 03, 1990 REVISIONS: Nov 23, 1990 - added fields for drawing rectilinear cells properly. Thu Feb 14 02:42:57 EST 1991 - modified for new pad placement algorithm. Fri Feb 15 01:38:42 EST 1991 - added lo_pos and hi_pos fields for the VARIABLE_PADS case. Sun Feb 17 21:09:24 EST 1991 - added new global variables so that pad placement code will work with macros. ----------------------------------------------------------------- */ /* ***************************************************************** "@(#) pads.h (Yale) version 4.6 2/17/91" ***************************************************************** */ #ifndef PADS_H #define PADS_H /* control for pad spacing */ #define UNIFORM_PADS 0 #define VARIABLE_PADS 1 #define ABUT_PADS 2 #define EXACT_PADS 3 /* pad sides */ #define ALL 0 #define L 1 #define T 2 #define R 3 #define B 4 /* macro sides */ #define MUL 7 #define MUR 8 #define MLL 9 #define MLR 10 #define ML 11 #define MR 12 #define MB 13 #define MT 14 #define MM 15 #define MTT 16 #define MBB 17 #define MMC 18 /* from MC */ #define MINI 0 #define MAXI 1 #define X 0 #define Y 1 #define HOWMANY 0 #define LARGE 100000 #define PINFINITY INT_MAX / 8 #define PICK_INT(l,u) (((l)<(u)) ? ((RAND % ((u)-(l)+1))+(l)) : (l)) /* pad type */ #define NONE 0 #define LEAF 1 #define SUBROOT 2 #define ROOT 3 typedef struct pad_rec { INT cellnum ; /* index in carray */ INT length ; INT height ; INT *xpoints ; /* xcoordinates of pad/macro */ INT *ypoints ; /* xcoordinates of pad/macro */ INT position ; /* linear placement position for a side */ INT tiebreak ; /* ideal location to place the pad */ INT numcorners ; /* number of corners */ INT *children ; /* added for pad code */ INT padside ; /* current side */ INT padtype ; /* type of pad - pad or padgroup */ INT hierarchy ; /* type of pad - root, lead, pad, etc */ INT lo_pos ; /* low valid position -1 if every valid */ INT hi_pos ; /* hi valid position PINFINITY if valid */ BOOL ordered ; /* whether a pad is ordered in a group */ BOOL oldformat ; /* true if old format */ BOOL permute ; /* whether rank is to be enforced */ BOOL macroNotPad ; /* true if macro false if pad */ BOOL fixed ; /* whether pad is fixed on a side */ BOOL valid_side[5] ; /* valid side a pad may be placed */ DOUBLE lowerbound ; DOUBLE upperbound ; } PADBOX, *PADBOXPTR ; /* ############# global variables defined for pad code ############## */ #ifdef PAD_VARS #define EXTERN #else #define EXTERN extern #endif EXTERN INT padspacingG ; EXTERN BOOL contiguousG ; EXTERN INT min_pad_spacingG ; EXTERN INT coreG[2][2] ; EXTERN INT perdimG[2] ; EXTERN INT numpadsG ; /* number of leaf pads + simple pads */ EXTERN INT numMacroG ; /* total number of macros */ EXTERN INT totalpadsG ; /* pads + padgroups */ /* DATA GLOBAL VARIABLES */ EXTERN PADBOXPTR *padarrayG ; /* array of all the pads and padgroups */ EXTERN PADBOXPTR *sortarrayG ; /* the sorted array of pads */ EXTERN PADBOXPTR *placearrayG ; /* array where the pads will be placed */ #undef EXTERN #endif /* PADS_H */ graywolf-0.1.4+20170307gite1bf319/src/twsc/parser.c000066400000000000000000002000731305746555600211750ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * Copyright (C) 2015 Tim Edwards * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: parser.c DESCRIPTION:syntax checker. CONTENTS: parser( fp ) FILE *fp ; DATE: Mar 27, 1989 REVISIONS: Mon Nov 19 04:04:18 EST 1990 - added temperature schedule initialization. Nov 23, 1990 - added correct drawing for rectilinear cells. Dec 8, 1990 - make hash table more efficient for nets. Dec 11, 1990 - fixed problem with output orientations for macro cells in new format. Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. Wed Jan 2 10:52:13 CST 1991 - removed extraneous code from initial placement phase. Mon Jan 7 18:32:58 CST 1991 - fixed pad translation problem and overlap check. Tue Jan 15 20:22:37 PST 1991 - fixed problem with fix_placement due to fixed_type and fixed_loc bug. Fri Jan 25 18:54:39 PST 1991 - fixed declaration of rowsG and fixed eqptr problem. Now also allow layer 0. Tue Feb 5 18:57:49 EST 1991 - fixed problem with pads with no side restrictions. Thu Feb 14 02:43:43 EST 1991 - modified for new pad placement algorithm. Fri Feb 15 15:18:54 EST 1991 - fixed overwrite of placearrayG. Sun Feb 17 21:08:19 EST 1991 - fixed pad placement code in the presence of macro cells. Thu Mar 14 16:17:10 CST 1991 - now handle both views for the pads. Fri Mar 15 18:34:08 CST 1991 - fixed problem with macros and padgroups using the old .blk format. Thu Apr 18 01:51:24 EDT 1991 - added initial orient feature and renamed to the new library names. Wed Jul 24 17:53:44 CDT 1991 - removed problem with excepts. Thu Aug 22 22:15:03 CDT 1991 - fixed some error checking. Thu Aug 22 22:34:00 CDT 1991 - Carl added some missing lines for fences and rigidly fixed cells. Wed Aug 28 15:02:02 EDT 1991 - fixed problem with missing unequiv switch. Wed Sep 11 11:21:42 CDT 1991 - fixed for new global router feed problem. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) parser.c (Yale) version 4.40 5/15/92" ; #endif /* #define MITLL */ #define PARSER_VARS #include #include "standard.h" #include "groute.h" #include "parser.h" #include "main.h" #include "readblck.h" #include "readpar.h" #include "config.h" #include "feeds.h" #include "pads.h" #include #include #include #include #include #include /* global variables */ INT ECOs_existG = 0 ; INT orig_max_row_lengthG ; extern INT totalRG ; extern INT spacer_widthG ; extern INT *spacer_feedsG ; extern INT uniform_rowsG ; extern INT total_row_lengthG ; extern INT total_except_widthG ; extern INT approximately_fixed_factorG ; extern BOOL fences_existG ; extern BOOL turn_off_checksG ; extern BOOL spacer_name_twfeedG ; extern BOOL rigidly_fixed_cellsG ; extern BOOL stand_cell_as_gate_arrayG ; /* below is what we expect to be a typical standard cell input */ /* user may change parameters if they wish. Subject to change */ #define EXPECTEDNUMCELLS 3500 #define EXPECTEDNUMNETS 1000 #define EXPECTEDSWAPGROUPS 10 #define EXPECTEDNUMPADS 10 #define E 0 /* ERRORABORT is a macro which forces routines not to do any work */ /* when we find a syntax error in the input routine. */ #define ERRORABORT() \ { \ if( abortS ){ \ return ; /* don't do any work for errors */ \ } \ } \ /* ########################## STATIC definitions ########################### */ static INT curCellTypeS ; /* current cell type - ie, stdcell,pad etc. */ static INT curNetS ; /* current net number */ static INT netAllocS ; /* current space in netarray */ static INT cellAllocS ; /* current space in cellarray */ static INT ptAllocS ; /* current space in point arrays */ static INT swapAllocS ; /* current space in swap_group_listG */ static INT totalCellS ; /* current cell number and running total */ static INT swap_groupS ; /* current swap group number from hashtable */ static INT swap_nextS ; /* next swap group number to assign */ static INT pin_typeS ; /* current pin type */ static INT numchildrenS ; /* # of children in current padgroup */ static INT childAllocS ; /* current space in current pptr->children */ static INT minxS, maxxS ; /* X bounding box for cell or pad */ static INT minyS, maxyS ; /* Y bounding box for cell or pad */ static char *curCellNameS ; /* current cell name */ static BOOL abortS = FALSE ; /* switch allow us to find multiple errors */ static INT pin_group_light_is_onS;/* currently in a pin group at position cnt */ static BOOL need_swap_groupS; /* pin_group called without swap_group */ static BOOL old_pad_formatS = FALSE;/* we need to do more work if old format */ static CBOXPTR ptrS ; /* pointer to current cell box */ static PINBOXPTR pinptrS ; /* the current pin */ static PADBOXPTR pptrS ; /* the current pad box record */ static IPBOXPTR imptrS ; /* current implicit feed ptr */ static YHASHPTR net_hash_tableS ; /* hash table for cross referencing nets */ static YHASHPTR swap_hash_tableS ;/* hash table for referencing swap_groups */ static INT transTableS[5][8] = { /* translate from old pad format */ { E, E, E, E, E, E, E, E }, /* error state */ { 6, 5, 4, 7, 1, 2, 3, 0 }, /* PADL state */ { 1, 0, 3, 2, 6, 7, 4, 5 }, /* PADT state */ { 7, 4, 5, 6, 2, 1, 0, 3 }, /* PADR state */ { 0, 1, 2, 3, 4, 5, 7, 6 } /* PADB state */ } ; static layer_test(); static check_pin(); /* ###################### END STATIC definitions ############################ */ static get_stat_hints() { FILE *fp ; /* current file */ char buffer[LRECL] ; /* temp storage */ char *bufferptr ; /* pointer to start of the line */ char **tokens ; /* tokenized line */ INT numtokens ; /* number of tokens on the line */ sprintf( buffer, "%s.stat", cktNameG ) ; if( fp = TWOPEN( buffer, "r", NOABORT ) ){ /* parse the hints */ cellAllocS = 0 ; while( bufferptr = fgets( buffer, LRECL, fp )){ tokens = Ystrparser( bufferptr, ":\t\n", &numtokens ) ; if( numtokens != 2 ){ continue ; } else if( strcmp( tokens[0],"num_stdcells") == STRINGEQ ){ cellAllocS += atoi( tokens[1] ) ; if( cellAllocS <= 0 ){ /* reset if bogus */ cellAllocS = EXPECTEDNUMCELLS ; } } else if( strcmp( tokens[0],"num_nets") == STRINGEQ ){ netAllocS = atoi( tokens[1] ) ; if( netAllocS <= 0 ){ /* reset if bogus */ netAllocS = EXPECTEDNUMNETS ; } /* look for macros and pads normally - ports if new format */ } else if( strcmp( tokens[0],"num_macros") == STRINGEQ ){ if( rowsG == 0 ){ cellAllocS += atoi( tokens[1] ) ; } } else if( strcmp( tokens[0],"num_pads") == STRINGEQ ){ if( rowsG == 0 ){ cellAllocS += atoi( tokens[1] ) ; } } else if( strcmp( tokens[0],"num_ports") == STRINGEQ ){ if( rowsG != 0 ){ cellAllocS += atoi( tokens[1] ) ; } } } M( MSG, NULL, "\n" ) ; sprintf( YmsgG, "Found hints in <%s.stat> file\n", cktNameG ) ; M( MSG, "get_stat_hints", YmsgG ) ; /* add +1 afterward to account for the 0 record */ sprintf( YmsgG, "Total cells:%d Number of nets:%d\n\n",cellAllocS++,netAllocS++) ; M( MSG, "get_stat_hints", YmsgG ) ; } else { cellAllocS = EXPECTEDNUMCELLS ; netAllocS = EXPECTEDNUMNETS ; } /* now allocate the data structures */ netarrayG = (DBOXPTR *) Ysafe_malloc( netAllocS * sizeof( DBOXPTR ) ) ; carrayG = (CBOXPTR *) Ysafe_malloc( cellAllocS * sizeof( CBOXPTR ) ) ; swap_group_listG = (SWAPBOX *) Ysafe_calloc( 1, sizeof(SWAPBOX) ) ; } /* end get_stat_hints */ set_error_flag() { abortS = TRUE ; } /* set_error_flag */ initialize_parser() { INT except ; /* counter */ INT width ; /* width of exception */ INT height ; /* height of exception */ EXCEPTPTR exceptptr ; /* current exception */ numcellsG = 0 ; numtermsG = 0 ; numpadgrpsG = 0 ; numMacroG = 0 ; TotRegPinsG = 0 ; numnetsG = 0 ; implicit_feed_countG = 0 ; totalCellS = 0 ; swap_groupS = 0 ; swap_nextS = 0 ; pin_group_light_is_onS = 0 ; need_swap_groupS = FALSE ; fixLRBTG = (INT *) Ysafe_malloc( 4 * sizeof( INT ) ) ; fixLRBTG[0] = 0 ; fixLRBTG[1] = 0 ; fixLRBTG[2] = 0 ; fixLRBTG[3] = 0 ; /* set the initial datastructure sizes */ get_stat_hints() ; net_hash_tableS = Yhash_table_create( 2 * netAllocS ) ; swap_hash_tableS = Yhash_table_create( TW_PRIME2 ) ; if( num_exceptsG > 0 ) { rigidly_fixed_cellsG = TRUE ; } /* add exceptionsG into carrayG at this time */ for( except = 1 ; except <= num_exceptsG ; except++ ) { addCell( Ystrclone("TW_EXCEPT"), EXCEPTTYPE ) ; exceptptr = &(exceptionsG[except]) ; /* now override the defaults */ ptrS->cclass = -5 ; ptrS->orflag = 0 ; ptrS->cblock = exceptptr->row ; ptrS->cxcenter = exceptptr->ll_x - (barrayG[ ptrS->cblock ]->bxcenter + barrayG[ ptrS->cblock ]->bleft) ; ptrS->cycenter = 1 ; width = exceptptr->ur_x - exceptptr->ll_x ; height = exceptptr->ur_y - exceptptr->ll_y ; ptrS->border = exceptptr->ll_x - (barrayG[ ptrS->cblock ]->bxcenter + barrayG[ ptrS->cblock ]->bleft) ; /* add_tile( left, bottom, right, top */ add_tile( -width/2, -height/2, width-width/2, height-height/2 ) ; } Ysafe_free( exceptionsG ) ; } /* initialize_parser */ addCell( cellname, celltype ) char *cellname ; INT celltype ; { /* save current cell name and type for error messages */ curCellNameS = cellname ; curCellTypeS = celltype ; /* Undefine pin and swap groups, if used in the last cell */ pin_group_light_is_onS = 0 ; need_swap_groupS = FALSE ; totalCellS++ ; ERRORABORT() ; /* make sure allocation is ok */ if( totalCellS >= cellAllocS ){ cellAllocS += EXPECTEDNUMCELLS ; carrayG = (CBOXPTR *) Ysafe_realloc( carrayG, cellAllocS * sizeof( CBOXPTR ) ) ; } ptrS = carrayG[totalCellS] = (CBOXPTR) Ysafe_malloc( sizeof(CBOX) ) ; /* now initialize the data */ ptrS->cname = cellname ; /* allocated previously in lex */ ptrS->cxcenter = 0 ; ptrS->cycenter = 0 ; ptrS->cheight = 0 ; ptrS->clength = 0 ; ptrS->cblock = 0 ; ptrS->border = 0 ; ptrS->ECO_flag = 0 ; ptrS->cclass = 0 ; ptrS->orflag = 1 ; ptrS->cbclass[0] = 0 ; ptrS->cbclass[1] = 0 ; ptrS->cbclass[2] = 0 ; ptrS->cbclass[3] = 0 ; ptrS->cbclass[4] = 0 ; ptrS->cbclass[5] = 0 ; ptrS->cbclass[6] = 0 ; ptrS->cbclass[7] = 0 ; ptrS->corient = 0 ; ptrS->numterms = 0 ; ptrS->num_swap_group = 0 ; ptrS->swapgroups = NULL ; ptrS->fence = NULL ; ptrS->paths = NULL ; ptrS->tileptr = TILENULL ; ptrS->imptr = NULL ; ptrS->pins = NULL ; ptrS->padptr = NULL ; if( celltype == STDCELLTYPE || celltype == EXCEPTTYPE ){ numcellsG++ ; } else if( celltype == PADTYPE || celltype == PORTTYPE || celltype == PADGROUPTYPE || celltype == HARDCELLTYPE ){ ptrS->cclass = 0 ; ptrS->orflag = 0 ; numtermsG++ ; pptrS = ptrS->padptr = (PADBOXPTR) Ysafe_calloc( 1, sizeof(PADBOX) ) ; pptrS->fixed = FALSE ; pptrS->padside = ALL ; pptrS->permute = FALSE ; pptrS->ordered = FALSE ; pptrS->oldformat = FALSE ; pptrS->lowerbound = 0.0 ; pptrS->upperbound = 1.0 ; pptrS->macroNotPad = FALSE ; /* assume a pad */ pptrS->numcorners = 0 ; pptrS->padtype = celltype ; pptrS->cellnum = totalCellS ; pptrS->valid_side[0] = TRUE ; pptrS->valid_side[1] = FALSE ; pptrS->valid_side[2] = FALSE ; pptrS->valid_side[3] = FALSE ; pptrS->valid_side[4] = FALSE ; if( celltype == PADGROUPTYPE ){ numpadgrpsG++ ; numchildrenS = 0 ; childAllocS = EXPECTEDNUMPADS ; pptrS->children = (INT *) Ysafe_malloc((childAllocS)*sizeof(INT)); pptrS->hierarchy = ROOT; } else { /* PADTYPE or PORTTYPE */ pptrS->children = NULL; pptrS->hierarchy = NONE; } if( celltype == HARDCELLTYPE ){ /* set the padside to MMC to avoid processing in placepads */ pptrS->padside = MMC ; pptrS->macroNotPad = TRUE ; numMacroG++ ; } } } /* end addCell */ add_tile( left, bottom, right, top ) INT left, bottom, right, top ; { INT width ; /* width of tile */ INT height ; /* height of tile */ TIBOXPTR tile ; /* current tile */ if( (right + left != 0 && right + left != 1) || left > 0 ) { M( ERRMSG, "add_tile", "The given center of the cell "); M( ERRMSG, NULL, "is not (right + left) div 2\n"); M( ERRMSG, NULL, "Where the remainder is truncated - "); sprintf( YmsgG, "Current cell number:%d Name:<%s>\n\n", totalCellS , curCellNameS ) ; M( ERRMSG, NULL, YmsgG ) ; abortS = TRUE ; } if( (top + bottom != 0 && top + bottom != 1) || bottom > 0 ) { M( ERRMSG, "add_tile", "The given center of the cell "); M( ERRMSG, NULL, "is not (top + bottom) div 2\n"); M( ERRMSG, NULL, "Where the remainder is truncated - "); sprintf( YmsgG, "current cell number:%d Name:<%s>\n\n", totalCellS , curCellNameS ) ; M( ERRMSG, NULL, YmsgG ) ; abortS = TRUE ; } ERRORABORT() ; /* add tile to datastructures */ tile = ptrS->tileptr = (TIBOXPTR) Ysafe_malloc( sizeof(TIBOX) ) ; tile->left = left ; tile->right = right ; tile->bottom = bottom ; tile->top = top ; width = right - left ; height = top - bottom ; ptrS->cheight = height ; ptrS->clength = width ; if( curCellTypeS == STDCELLTYPE ){ celllenG += width ; } if( gate_arrayG ){ if( curCellTypeS == STDCELLTYPE || curCellTypeS == EXCEPTTYPE || curCellTypeS == EXTRATYPE ) { if( width % spacer_widthG != 0 ) { sprintf( YmsgG, "the width of cell <%s> is not a multiple of the spacer_width\n", ptrS->cname ) ; M( ERRMSG, "add_tile", YmsgG ) ; abortS = TRUE ; } } } } /* end add_tile */ add_initial_orient( orient ) INT orient ; { ERRORABORT() ; if( orient >= 0 && orient <= 3 ){ ptrS->corient = orient ; } else { sprintf( YmsgG, "initial orientation is not in the range [0..3] for cell <%s>\n", ptrS->cname ) ; M( ERRMSG, "add_initial_orient", YmsgG ) ; abortS = TRUE ; } } /* end add_initial_orient */ static char *add_swap_func() { INT *data ; /* pointer to allocated space for swap_group record */ ERRORABORT() ; /* how to add the data to the hash table */ /* create space for data */ data = (INT *) Ysafe_malloc( sizeof(INT) ) ; /* if data is not found in hash table update swap_groupS */ *data = ++swap_nextS ; return( (char *) data ) ; } /* end add_swap_func */ add_swap_group( swap_name ) char *swap_name ; { INT i ; /* counter */ INT *groupptr ; /* the return group from searching in hash table */ INT oldalloc ; /* allocation before expanding the array */ BOOL newflag ; /* TRUE if this item has been added to hash table */ SWAPBOX *swapptr ; /* pointer to the current swap group list */ SGLIST *sglistptr ; ERRORABORT() ; swappable_gates_existG = TRUE ; groupptr = (INT *)Yhash_add( swap_hash_tableS, swap_name, add_swap_func, &newflag ) ; /* check to make sure all is well. newflag is set if swap_name wasn't in hashtable */ if(!(groupptr) || (*groupptr <= 0)) { sprintf(YmsgG, "Problem with swap hash table for group <%s>\n", swap_name ); M( ERRMSG, "add_swap_group", YmsgG ) ; abortS = TRUE ; } swap_groupS = *groupptr; /* Check if swapgroups exists. Create it if not. */ if (ptrS->swapgroups == NULL) { ptrS->swapgroups = (SGLIST *) Ysafe_malloc( sizeof( SGLIST ) ) ; ptrS->num_swap_group = 1; sglistptr = ptrS->swapgroups; sglistptr->num_pin_group = 0; sglistptr->swap_group = swap_groupS; } else { /* Does this swap group already exist in the list? If */ /* so, then ignore it, otherwise add it to the list. */ for (i = 0; i < ptrS->num_swap_group; i++) { sglistptr = ptrS->swapgroups + i; if (sglistptr->swap_group == swap_groupS) break; } if (i == ptrS->num_swap_group) { ptrS->num_swap_group++; ptrS->swapgroups = (SGLIST *) Ysafe_realloc( ptrS->swapgroups, ptrS->num_swap_group * sizeof( SGLIST ) ) ; sglistptr = ptrS->swapgroups + i; sglistptr->swap_group = swap_groupS; sglistptr->num_pin_group = 0; } } if (newflag && need_swap_groupS) { sprintf(YmsgG, "Implicit swap group <%s> created\n", swap_name ); M( MSG, "add_swap_group", YmsgG ) ; } if( newflag && swap_groupS >= swapAllocS ){ oldalloc = swapAllocS ; swapAllocS += EXPECTEDSWAPGROUPS ; swap_group_listG = (SWAPBOX *) Ysafe_realloc( swap_group_listG, swapAllocS * sizeof( SWAPBOX ) ) ; for( i = oldalloc; i < swapAllocS; i++ ){ swapptr = &(swap_group_listG[i]) ; swapptr->num_pin_grps = 0 ; swapptr->pin_grp_hash = Yhash_table_create( TW_PRIME2 ); } } } /* end add_swap_group */ add_pingroup() { INT i ; /* counter */ INT j ; /* counter */ SGLIST *sglistptr = NULL; ERRORABORT() ; /* Find the swap group in the cell record */ for (i = 0; i < ptrS->num_swap_group; i++) { sglistptr = ptrS->swapgroups + i; if (sglistptr->swap_group == swap_groupS) break; } if (i == ptrS->num_swap_group) { // If no swap group was defined for the cell, then // each pin_group will implicitly define a swap // group with the name of the first pin before the // slash character. need_swap_groupS = TRUE; return; } sglistptr->num_pin_group++ ; pin_group_light_is_onS = 1 ; } /* end add_pingroup */ end_pingroup() { pin_group_light_is_onS = 0 ; // Reset the swap_group if each pin group defines its own // swap group (enabled by not having a "swap_group" line in // the cell options). if (need_swap_groupS == TRUE) swap_groupS = 0; } /* end end_pingroup */ static add_implicit_feed( pin_name, signal, layer, xpos, ypos ) char *pin_name, *signal ; INT layer, xpos, ypos ; { ERRORABORT() ; imptrS = ( IPBOXPTR )Ysafe_malloc( sizeof( IPBOX ) ) ; /* now fill in data */ if( pin_layers_givenG ) { layer_test( layer ) ; imptrS->pinname = (char *) Ysafe_malloc( (strlen( pin_name ) + 3 ) * sizeof( char ) ) ; sprintf( imptrS->pinname , "]%1d%s" , layer, pin_name ) ; Ysafe_free( pin_name ) ; } else { imptrS->pinname = pin_name ; } imptrS->txpos = xpos ; imptrS->cell = totalCellS ; imptrS->terminal = 0 ; /* wait till later to fill in */ imptrS->next = ptrS->imptr ; ptrS->imptr = imptrS ; if( one_pin_feedthruG ) { if( pin_layers_givenG ) { imptrS->eqpinname = (char *) Ysafe_malloc( (strlen(pin_name) + 3 ) * sizeof( char ) ) ; sprintf(imptrS->eqpinname,"]%1d%s", layer, pin_name ) ; } else { imptrS->eqpinname = Ystrclone( pin_name ) ; } } } /* end add_implicit_feed */ static char *add_net_func() { INT *data ; /* pointer to allocated space for net record in hashtable */ ERRORABORT() ; /* how to add the data to the hash table */ /* create space for data */ data = (INT *) Ysafe_malloc( sizeof(INT) ) ; /* if data is not found in hash table update numnetsG */ *data = ++numnetsG ; return( (char *) data ) ; } /* end add_swap_func */ static char *add_pin_func() { INT *data ; /* pointer to allocated space for pin_grp_hash record */ ERRORABORT() ; /* how to add the data to the hash table */ /* create space for data */ data = (PINLIST *) Ysafe_malloc( sizeof(PINLIST) ) ; return( (char *) data ) ; } /* end add_swap_func */ add_pin( pin_name, signal, layer, xpos, ypos ) char *pin_name, *signal ; INT layer, xpos, ypos ; { INT *netreturn ; /* net number found in hash table */ INT newflag ; BOOL notInTable ; /* net added to table if true */ DBOXPTR nptr ; /* the current net record */ PINLISTPTR pin_ptr ; /* pointer to current pinlistgroup */ PINLISTPTR new_pin_ptr ; /* pointer to new pinlistgroup */ static PINBOXPTR botpinL = NULL ; /* save the last pinptr */ ERRORABORT() ; // If a swap group was not defined for this cell in the // traditional way (with "swap_group" in cell options list), // but pin_group was called, then we generate an implicit // swap_group with the name of the pin before the slash. if (need_swap_groupS) { char *slashptr = strrchr(pin_name, '/'); if (slashptr != NULL) { *slashptr = '\0'; add_swap_group(pin_name); *slashptr = '/'; add_pingroup(); } /* In case of error this is just a normal pin, not */ /* swappable, which may result in non-optimal */ /* placement but does not invalidate the netlist. */ } if( curCellTypeS == PADTYPE || curCellTypeS == HARDCELLTYPE ){ /* these types may have global pin positions */ /* subtract off cell center */ xpos -= ptrS->cxcenter ; ypos -= ptrS->cycenter ; } check_pin( xpos, ypos, pin_name ) ; if( strcmp( signal, "TW_PASS_THRU" ) == STRINGEQ ){ pin_typeS = PASS_THRU ; implicit_feed_countG++ ; add_implicit_feed( pin_name, signal, layer, xpos, ypos ) ; return ; } else if( strcmp( signal, "TW_SWAP_PASS_THRU" ) == STRINGEQ ){ pin_typeS = SWAP_PASS ; implicit_feed_countG++ ; } else { pin_typeS = PINTYPE ; } ptrS->numterms++ ; /* add to netlist */ netreturn = (INT *)Yhash_add( net_hash_tableS, signal, add_net_func, ¬InTable ) ; /* check to make sure all is well. notInTable is set if signal wasn't in hashtable */ if(!(netreturn)){ sprintf( YmsgG, "Trouble adding signal:%s to hash table\n", signal ) ; M(ERRMSG,"add_pin",YmsgG ) ; abortS = TRUE ; return ; } curNetS = *netreturn ; /* check memory of netarray */ if( numnetsG >= netAllocS ){ netAllocS += EXPECTEDNUMNETS ; netarrayG = (DBOXPTR *) Ysafe_realloc( netarrayG, netAllocS * sizeof(DBOX) ) ; } /* see if this is the first time for this signal */ if( notInTable ){ nptr = netarrayG[curNetS] = (DBOXPTR) Ysafe_malloc( sizeof( DBOX ) ) ; nptr->pins = PINNULL ; nptr->name = signal ; nptr->paths = NULL ; nptr->dflag = 0 ; nptr->xmin = 0 ; nptr->newxmin = 0 ; nptr->xmax = 0 ; nptr->newxmax = 0 ; nptr->ymin = 0 ; nptr->newymin = 0 ; nptr->ymax = 0 ; nptr->newymax = 0 ; nptr->feedflag = 0 ; nptr->ignore = 0 ; } else { Ysafe_free( signal ) ; /* no need to keep this copy */ nptr = netarrayG[curNetS] ; } /* create list of pins on the net */ pinptrS = (PINBOXPTR) Ysafe_malloc( sizeof(PINBOX) ); pinptrS->next = nptr->pins ; nptr->pins = pinptrS ; /* create a list of pins for this cell in order as given */ if( ptrS->pins ){ /* list has already been started */ botpinL->nextpin = pinptrS ; } else { /* start new list */ ptrS->pins = pinptrS ; } pinptrS->nextpin = NULL ; botpinL = pinptrS ; /* now initialize data */ pinptrS->terminal = ++TotRegPinsG ; pinptrS->net = curNetS ; pinptrS->xpos = 0 ; pinptrS->ypos = 0 ; pinptrS->newx = 0 ; pinptrS->newy = 0 ; pinptrS->flag = 0 ; pinptrS->row = (SHORT) 0 ; pinptrS->cell = totalCellS ; pinptrS->eqptr = NULL ; pinptrS->adjptr = (ADJASEGPTR)Ysafe_calloc( 1, sizeof(ADJASEG) ) ; if( pin_layers_givenG ) { layer_test( layer ) ; pinptrS->pinname = (char *) Ysafe_malloc( (strlen( pin_name ) + 3 ) * sizeof( char ) ) ; sprintf( pinptrS->pinname , "]%1d%s" , layer, pin_name ) ; Ysafe_free( pin_name ) ; } else { pinptrS->pinname = pin_name ; } pinptrS->txpos[0] = xpos ; pinptrS->typos[0] = ypos ; if( pin_group_light_is_onS > 0 ) { pin_ptr = (PINLISTPTR) Yhash_add( swap_group_listG[swap_groupS].pin_grp_hash, ptrS->cname, add_pin_func, &newflag ) ; if (newflag) { /* This is the first pin group for this swap group in this cell */ pin_ptr->swap_pin = pinptrS; pin_ptr->next = NULL; pin_ptr->next_grp = NULL; } else { if (pin_group_light_is_onS == 1) { /* Additional pin group for this swap group in this cell */ while (pin_ptr->next_grp) pin_ptr = pin_ptr->next_grp; new_pin_ptr = (PINLISTPTR) Ysafe_malloc( sizeof(PINLIST) ) ; pin_ptr->next_grp = new_pin_ptr; } else { /* Additional pins in this pin group */ while (pin_ptr->next) pin_ptr = pin_ptr->next; new_pin_ptr = (PINLISTPTR) Ysafe_malloc( sizeof(PINLIST) ) ; pin_ptr->next = new_pin_ptr; } new_pin_ptr->swap_pin = pinptrS; new_pin_ptr->next = NULL; new_pin_ptr->next_grp = NULL; } if( pin_typeS == SWAP_PASS ){ swap_netG = curNetS ; netarrayG[curNetS]->ignore = 1 ; } pin_group_light_is_onS++; } /* pin location determination */ if( curCellTypeS == PADTYPE ) { if( pptrS->padside == L ) { pinptrS->pinloc = TOPCELL ; } else if( pptrS->padside == R ) { pinptrS->pinloc = TOPCELL ; } else if( pptrS->padside == MUL ) { pinptrS->pinloc = BOTCELL ; } else if( pptrS->padside == MUR ) { pinptrS->pinloc = BOTCELL ; } else if( pptrS->padside == MLL ) { pinptrS->pinloc = TOPCELL ; } else if( pptrS->padside == MLR ) { pinptrS->pinloc = TOPCELL ; } else if( pptrS->padside == ML ) { pinptrS->pinloc = TOPCELL ; } else if( pptrS->padside == MR ) { pinptrS->pinloc = TOPCELL ; } else { pinptrS->pinloc = NEITHER ; } } else if( curCellTypeS == PORTTYPE || curCellTypeS == HARDCELLTYPE ) { pinptrS->pinloc = NEITHER ; } else if( ypos > 0 ) { pinptrS->pinloc = TOPCELL ; } else { pinptrS->pinloc = BOTCELL ; } } /* end add_pin */ static check_pin( xpos, ypos, pinname ) INT xpos, ypos ; char *pinname ; { INT layer ; char *find_layer() ; TIBOXPTR tptr ; /* current tileptr */ ERRORABORT() ; tptr = ptrS->tileptr ; if( !turn_off_checksG ) { if( xpos < tptr->left || xpos > tptr->right || ypos < tptr->bottom || ypos > tptr->top ) { pinname = find_layer( pinname, &layer ) ; sprintf( YmsgG, "the pin <%s> assigned to cell <%s> is\n", pinname, curCellNameS ) ; M( ERRMSG, "check_pin", YmsgG ) ; M( ERRMSG, NULL, "outside the cell's bounding box:\n" ) ; sprintf( YmsgG, "\tcell l:%d r:%d b:%d t:%d pin x:%d y:%d\n", tptr->left, tptr->right, tptr->bottom, tptr->top, xpos, ypos ) ; M( ERRMSG, NULL, YmsgG ) ; abortS = TRUE ; } } } /* end check_pin */ add_equiv( equiv_name, layer, eq_xpos, eq_ypos, unequiv_flag ) char *equiv_name ; INT layer, eq_xpos, eq_ypos ; BOOL unequiv_flag ; { INT xpos ; /* position of pin */ INT ypos ; /* position of pin */ char *pname ; /* temp for swapping names */ static EQ_NBOXPTR eqptrL ; /* current equivalent pointer */ if( curCellTypeS == PADTYPE || curCellTypeS == HARDCELLTYPE ){ /* these types may have global pin positions */ /* subtract off cell center */ eq_xpos -= ptrS->cxcenter ; eq_ypos -= ptrS->cycenter ; } check_pin( eq_xpos, eq_ypos, equiv_name ) ; ERRORABORT() ; if( unequiv_flag ){ case_unequiv_pinG = TRUE ; } if( pin_typeS != PASS_THRU ){ xpos = pinptrS->txpos[0] ; ypos = pinptrS->typos[0] ; if(!(pinptrS->eqptr)){ /* the first equivalent pin */ if( ( ypos > 0 && eq_ypos < 0 ) || ( ypos < 0 && eq_ypos > 0 ) ) { pinptrS->pinloc = NEITHER ; pinptrS->typos[0] = 0 ; eqptrL = (EQ_NBOXPTR)Ysafe_malloc( sizeof(EQ_NBOX) ); netarrayG[curNetS]->pins->eqptr = eqptrL ; eqptrL->unequiv = unequiv_flag ; eqptrL->txoff = eq_xpos - xpos ; eqptrL->typos = eq_ypos ; if( pin_layers_givenG != 0 ) { eqptrL->pinname = (char *) Ysafe_malloc( (strlen(equiv_name) + 3 ) * sizeof( char ) ) ; sprintf( eqptrL->pinname , "]%1d%s", layer, equiv_name ) ; Ysafe_free( equiv_name ) ; } else { eqptrL->pinname = equiv_name ; } } } else { /* more than one equiv pin */ if( ( ypos > 0 && eq_ypos < 0 ) || ( ypos < 0 && eq_ypos > 0 ) ) { pinptrS->pinloc = NEITHER ; if( ABS( eq_xpos - xpos ) < ABS( eqptrL->txoff ) ) { eqptrL->txoff = eq_xpos - xpos ; eqptrL->typos = eq_ypos ; if( pin_layers_givenG ) { eqptrL->pinname = (char *) Ysafe_realloc( eqptrL->pinname, (strlen(equiv_name) + 3 ) * sizeof(char)); sprintf( eqptrL->pinname , "]%1d%s", layer, equiv_name ) ; } else { (char *) Ysafe_realloc( eqptrL->pinname , (strlen(equiv_name) + 1 ) * sizeof(char)); sprintf(eqptrL->pinname,"%s", equiv_name ) ; } Ysafe_free( equiv_name ) ; } } } } else { /* PASS_THRU CASE */ if( pin_layers_givenG ) { imptrS->eqpinname = (char *) Ysafe_malloc( (strlen( equiv_name ) + 3 ) * sizeof( char ) ) ; sprintf( imptrS->eqpinname , "]%1d%s" , layer, equiv_name ) ; Ysafe_free( equiv_name ) ; } else { imptrS->eqpinname = equiv_name ; } if( eq_ypos > 0 ) { /* swap the pinnames */ pname = imptrS->pinname ; imptrS->pinname = imptrS->eqpinname ; imptrS->eqpinname = pname ; } } } /* end add_equiv */ add_port( portname, signal, layer, xpos, ypos ) char *portname, *signal ; INT xpos, ypos ; { ERRORABORT() ; addCell( portname, PORTTYPE ) ; add_tile( 0, 0, 0, 0 ) ; /* now perform overrides */ ptrS->cxcenter = xpos ; ptrS->cycenter = ypos ; add_pin( portname, signal, layer, 0, 0 ) ; if( ypos > top_of_top_rowG ) { pptrS->padside = T ; } else if( ypos < bot_of_bot_rowG ) { pptrS->padside = B ; } } /* end add_port */ static layer_test( layer ) INT layer ; { if( layer != 0 && layer != 1 && layer != 2 && layer != 3 ) { M( ERRMSG, "layer_test", "Currently, a layer number "); M( ERRMSG, NULL,"in the .cel file must be either 0, 1, 2,\n"); M( ERRMSG, NULL, "or 3. \n") ; sprintf( YmsgG, "Current cell number:%d Name:<%s>\n", totalCellS - num_exceptsG, curCellNameS ) ; M( ERRMSG, NULL, YmsgG ) ; abortS = TRUE ; } } /* end layer_test */ init_legal_blocks( numblocks ) INT numblocks ; { ERRORABORT() ; ptrS->cclass = 0 ; } /* end init_legal_blocks */ add_legal_blocks( block_class ) INT block_class ; { INT row ; /* row counter */ INT shift ; /* used to calculate bit class */ INT index ; /* used to calculate class */ INT bit_class ; /* used to calculate class */ BOOL found ; /* used to search for row */ if( block_class > 256 ) { M( ERRMSG, "add_legal_blocks","cannot handle more than 256 block classes\n"); abortS = TRUE ; } ERRORABORT() ; found = FALSE ; for( row = 1 ; row <= numRowsG ; row++ ) { if( block_class == barrayG[row]->bclass ) { found = TRUE ; } } if( !found ) { sprintf( YmsgG,"block class specified for cell <%s> was\n", curCellNameS ) ; M( ERRMSG, "add_legal_blocks", YmsgG ) ; M( ERRMSG, NULL,"not specified in the .blk file\n"); abortS = TRUE ; } ptrS->cclass = 1 ; /* this field must be set > 0 */ bit_class = 1 ; index = (block_class-1) / 32 ; shift = block_class - 32 * index ; bit_class <<= (shift - 1) ; ptrS->cbclass[index] += bit_class ; } /* end add_legal_blocks */ set_mirror_flag() { ERRORABORT() ; /* this is for the current cell */ ptrS->orflag = 0 ; } /* end set_mirror_flag */ add_orient( orient ) INT orient ; { ERRORABORT() ; /* this is for the current cell */ ptrS->corient = orient ; } /* end add_orient */ fix_placement( fixed_type, from, fixed_loc, block ) char *fixed_type, *fixed_loc ; INT from, block; { FENCEBOXPTR fence ; /* current fence */ BOOL approx_fixed = FALSE ; ERRORABORT() ; if( strcmp( fixed_type, "fixed" ) == STRINGEQ ) { ptrS->cclass = -1 ; ptrS->orflag = 0 ; fences_existG = TRUE ; approx_fixed = TRUE ; } else if( strcmp( fixed_type , "rigidly_fixed" ) == STRINGEQ ) { if( !gate_arrayG ) { M(ERRMSG,"fix_placement","if you use rigidly_fixed cells, you must run\n"); M(ERRMSG,NULL,"the circuit as a \"gate array\", that is, specifying \n"); M(ERRMSG,NULL,"the \"spacer_width\" parameter in the .par file\n"); M(ERRMSG,NULL,"Please refer to the manual\n"); abortS = TRUE ; } rigidly_fixed_cellsG = TRUE ; ptrS->cclass = -5 ; ptrS->orflag = 0 ; } else if( strcmp( fixed_type, "approximately_fixed" ) == STRINGEQ ) { fences_existG = TRUE ; approx_fixed = TRUE ; } else if( strcmp( fixed_type, "nonfixed" ) != STRINGEQ ){ sprintf( YmsgG, "Unknown fixed type:%s\n", fixed_type ) ; M(ERRMSG,"fix_placement", YmsgG ) ; abortS = TRUE ; } Ysafe_free(fixed_type) ; /* fixed_loc "left" or "right" */ if( strcmp( fixed_loc, "left" ) == STRINGEQ ) { ptrS->cxcenter = from ; ptrS->cycenter = 1 ; ptrS->border = from ; } else if( strcmp( fixed_loc, "right" ) == STRINGEQ ) { ptrS->cxcenter = -from ; ptrS->cycenter = -1 ; if( from != 0 ) { ptrS->border = -from ; } else { ptrS->border = -1 ; } } else { sprintf( YmsgG, "Invalid fixed_location:%s\n", fixed_loc ) ; M(ERRMSG,"fix_placement", YmsgG ) ; abortS = TRUE ; } Ysafe_free(fixed_loc) ; ptrS->cblock = block ; if( block > numRowsG || block < 1 ) { sprintf(YmsgG, "block assigned to cell <%s> was\n", curCellNameS ); M( ERRMSG, "fix_placement", YmsgG ) ; M( ERRMSG, NULL, "out of range as specified in the .blk file\n"); abortS = TRUE ; } if( approx_fixed ) { fence = ptrS->fence ; ptrS->fence = (FENCEBOXPTR) Ysafe_malloc( sizeof(FENCEBOX) ) ; ptrS->fence->next_fence = fence ; if( ptrS->cclass < 0 ) { ptrS->fence->min_block = block ; ptrS->fence->max_block = block ; } else { if( block > approximately_fixed_factorG ) { ptrS->fence->min_block = block - approximately_fixed_factorG ; } else { ptrS->fence->min_block = 1 ; } if( block + approximately_fixed_factorG <= numRowsG ) { ptrS->fence->max_block = block + approximately_fixed_factorG ; } else { ptrS->fence->max_block = numRowsG ; } } } } /* end fix_placement */ add_extra_cells() { INT row ; /* row counter */ INT pin ; /* pin counter */ INT slack ; /* excess row length */ INT target ; /* target total row length */ INT avg_width ; /* average except width */ char buffer[LRECL] ; /* temp buffer */ IPBOXPTR imptr ; /* current implicit feed ptr */ /* at this time if we get an error exit */ if( abortS ){ closegraphics() ; YexitPgm( PGMFAIL ) ; } if( gate_arrayG && !rigidly_fixed_cellsG && rowsG ) { target = (int) (1.3 * (DOUBLE) celllenG ) ; while( total_row_lengthG - barrayG[numRowsG]->blength >= target ) { total_row_lengthG -= barrayG[numRowsG]->blength ; numRowsG-- ; fprintf(fpoG,"The number of available rows in the gate_array \n"); fprintf(fpoG,"is being decremented in add_extra_cells()\n\n"); } } #ifndef MITLL if( gate_arrayG || rowsG > 0 ) { slack = total_row_lengthG - celllenG ; avg_width = (celllenG - total_except_widthG) / numcellsG ; if( slack < numRowsG * 2 * avg_width ) { slack = (numRowsG * 2 * avg_width - slack) / numRowsG ; while( slack % spacer_widthG != 0 ) { slack++ ; } total_row_lengthG += slack * numRowsG ; } slack = total_row_lengthG - celllenG ; numcellsG += extra_cellsG = (slack) / spacer_widthG ; sprintf(YmsgG,"Added %d spacer cells to the gate array\n", extra_cellsG); M( MSG, "add_extra_cells", YmsgG ) ; } else { extra_cellsG = 0 ; spacer_widthG = 0 ; } #else if( total_row_lengthG < celllenG ) { total_row_lengthG = celllenG ; } extra_cellsG = (total_row_lengthG - celllenG ) / spacer_widthG ; while( (extra_cellsG + numcellsG) % numRowsG != 0 ) { extra_cellsG++ ; } numcellsG += extra_cellsG ; sprintf(YmsgG,"Added %d spacer cells to the gate array\n", extra_cellsG); M( MSG, "add_extra_cells", YmsgG ) ; #endif /* at this point number numcellsG will have extra cells added but */ /* totalCellS will have the number of cells added so far */ /* loop until they are equal - addCell will increment totalCellS */ if( extra_cellsG > 0 ) { while( totalCellS < numcellsG ) { if( !spacer_name_twfeedG ) { addCell( Ystrclone( "GATE_ARRAY_SPACER"), EXTRATYPE ) ; } else { #ifdef FEED_INSTANCES sprintf( buffer, "twfeed%d", 100000 + totalCellS ) ; #else sprintf( buffer, "twfeed" ) ; #endif addCell( Ystrclone( buffer), EXTRATYPE ) ; } ptrS->cheight = barrayG[1]->bheight ; ptrS->clength = spacer_widthG ; ptrS->orflag = 0 ; ptrS->cycenter = GATE_ARRAY_MAGIC_CONSTANT ; add_tile( - spacer_widthG / 2, - barrayG[1]->bheight / 2, spacer_widthG - spacer_widthG / 2, barrayG[1]->bheight - barrayG[1]->bheight / 2 ) ; #ifdef OLD_WAY for( pin = 1 ; pin <= spacer_feedsG[0] ; pin++ ) { imptr = ( IPBOXPTR )Ysafe_malloc( sizeof( IPBOX ) ) ; if( pin_layers_givenG ) { sprintf( buffer,"]%1d%s%d",feedLayerG,"SPACER_FEED_TOP_", pin ) ; } else { sprintf( buffer, "%s%d" , "SPACER_FEED_TOP_" , pin ) ; } imptr->pinname = Ystrclone( buffer ) ; imptr->txpos = spacer_feedsG[pin] - spacer_widthG / 2 ; imptr->cell = totalCellS ; imptr->terminal = -1 ; /* to be set later */ imptr->next = ptrS->imptr ; ptrS->imptr = imptr ; if( pin_layers_givenG != 0 ) { sprintf( buffer, "]%1d%s%d",feedLayerG,"SPACER_FEED_BOTTOM_",pin ); } else { sprintf( buffer, "%s%d" , "SPACER_FEED_BOTTOM_" , pin ); } imptr->eqpinname = Ystrclone( buffer ) ; } #endif /* OLD_WAY */ } } } /* end add_extra_cells */ static INT free_swap_data( data ) INT *data ; { Ysafe_free( data ) ; } /* free_swap_data */ static trans_tile( ptr, orient ) CBOXPTR ptr ; INT orient ; { INT l,r,b,t ; /* needed for orientation calc. */ TIBOXPTR tptr ; /* tilebox ptr */ /* rotate the tiles to proper orientation */ tptr = ptr->tileptr ; /* need to assign to variable since tileptr values are short */ l = (INT) tptr->left ; r = (INT) tptr->right ; b = (INT) tptr->bottom ; t = (INT) tptr->top ; YtranslateT( &l, &b, &r, &t, orient ) ; tptr->left = (SHORT) l ; tptr->right = (SHORT) r ; tptr->bottom = (SHORT) b ; tptr->top = (SHORT) t ; ptr->clength = r - l ; ptr->cheight = t - b ; } /* end trans_tile */ static build_pad_group( side, sidename, padgroupname ) INT side ; char *sidename, *padgroupname ; { INT cell ; /* cell counter */ BOOL build_padgroup ; /* whether to build group or not */ CBOXPTR ptr ; /* current cell pointer */ /* see if we need to first build left padgroup */ build_padgroup = FALSE ; for( cell=numcellsG+1;cell<=lastpadG;cell++ ){ ptr = carrayG[cell] ; if( ptr->padptr->padside == side && pptrS->lowerbound <= 0.0 && pptrS->upperbound >= 1.0 ){ build_padgroup = TRUE ; } } if( build_padgroup ){ addCell( padgroupname, PADGROUPTYPE ) ; setPermutation( FALSE ) ; add_tile( 0,0,0,0 ) ; add_padside( sidename ) ; for( cell=numcellsG+1;cell<=lastpadG;cell++ ){ ptr = carrayG[cell] ; if( ptr->padptr->padside == side && pptrS->lowerbound <= 0.0 && pptrS->upperbound >= 1.0 ){ add2padgroup( ptr->cname, TRUE ) ; /* fixed */ } } end_padgroup() ; } } /* end build_pad_group() */ cleanup_readcells() { INT trl ; /* total_row_length */ INT row ; /* row counter */ INT cell ; /* cell counter */ INT cell1 ; /* look for match */ INT cell2 ; /* look for match */ INT xpos ; /* temp for pin calc */ INT ypos ; /* temp for pin calc */ INT block ; /* block counter */ INT orient ; /* current orientation */ INT impcount ; /* count implicit feeds */ INT inverse ; /* inv. orient to get back to bottom */ INT b1, l1, r1, t1 ; /* coordinates of pads */ INT b2, l2, r2, t2 ; /* coordinates of pads */ INT total_desire ; INT deviate_by_row ; BOOL bogus_rows; /* true if we have bogus rows */ BOOL xFlag ; /* true if unsymmetric in x */ BOOL yFlag ; /* true if unsymmetric in y */ DOUBLE fraction ; /* check row length sanity */ CBOXPTR ptr ; /* current cell pointer */ TIBOXPTR tptr ; /* current tile */ PINBOXPTR pinptr ; /* current pin */ PADBOXPTR padptr ; /* current pad information */ IPBOXPTR imptr ; /* current implicit feed ptr */ /* at this time if we get an error exit */ if( abortS ){ closegraphics() ; YexitPgm( PGMFAIL ) ; } if( old_pad_formatS ){ /* add the old pads to a padgroup */ lastpadG = numcellsG + numtermsG ; /* see if we need to first build left padgroup */ build_pad_group( L, "L", "left_pads" ) ; build_pad_group( T, "T", "top_pads" ) ; build_pad_group( R, "R", "right_pads" ) ; build_pad_group( B, "B", "bottom_pads" ) ; if( abortS ){ closegraphics() ; YexitPgm( PGMFAIL ) ; } } /* cleanup the memory at this time this should shrink the memory */ carrayG = (CBOXPTR *) Ysafe_realloc( carrayG, (totalCellS+1) * sizeof( CBOXPTR ) ) ; netarrayG = (DBOXPTR *) Ysafe_realloc( netarrayG, (numnetsG+1) * sizeof(DBOX) ) ; /* This is for the TW_SWAP_PASS_THRU feature */ maxtermG = implicit_feed_countG + TotRegPinsG ; tearrayG = (PINBOXPTR *) Ysafe_calloc( maxtermG + 1, sizeof(PINBOXPTR) ) ; /* now load the pins in tearray */ last_pin_numberG = maxtermG ; impcount = TotRegPinsG ; lastpadG = numcellsG + numtermsG - numpadgrpsG ; init_acceptance_rate() ; for( cell = 1 ; cell <= totalCellS ; cell++ ) { ptr = carrayG[cell] ; /* first the given pins - they should already be numbered */ for( pinptr = ptr->pins; pinptr ; pinptr = pinptr->nextpin ){ if( pinptr->terminal <= 0 || pinptr->terminal > TotRegPinsG ){ sprintf( YmsgG, "Problem with pin %s\n", pinptr->pinname ) ; M( ERRMSG, "cleanup_readcells", YmsgG ) ; abortS = TRUE ; } tearrayG[pinptr->terminal] = pinptr ; } /* now due the implicit feeds they haven't been numbered */ /* pins labeled with terminal -1 are not to be added to tearray ??? */ for( imptr = ptr->imptr; imptr ; imptr = imptr->next ){ if( imptr->terminal == -1 ){ imptr->terminal = ++last_pin_numberG ; } else { imptr->terminal = ++impcount ; } } } /* NOW WE HAVE TO LOAD IN THE OTHER CONFIGURATIONS */ for( cell = 1 ; cell <= numcellsG ; cell++ ) { if( carrayG[cell]->orflag == 1 ) { if( maxCellOG == 0 ) { maxCellOG = 2 ; } else if( maxCellOG == 1 ) { maxCellOG = 3 ; } break ; } } for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { ptr = carrayG[ cell ] ; if( ptr->clength %2 != 0 ) { xFlag = TRUE ; } else { xFlag = FALSE ; } if( ptr->cheight %2 != 0 ) { yFlag = TRUE ; } else { yFlag = FALSE ; } for( pinptr = ptr->pins ; pinptr; pinptr = pinptr->nextpin ) { if( xFlag ) { pinptr->txpos[1] = -pinptr->txpos[0] + 1 ; } else { pinptr->txpos[1] = -pinptr->txpos[0] ; } if( yFlag && pinptr->typos[0] != 0 ) { pinptr->typos[1] = -pinptr->typos[0] + 1 ; } else { pinptr->typos[1] = -pinptr->typos[0] ; } } } /* end processing core cells */ numpadsG = 0 ; /* now the pad cells and macro cells */ for( cell = numcellsG + 1 ; cell <= lastpadG; cell++ ) { ptr = carrayG[ cell ] ; padptr = ptr->padptr ; tptr = ptr->tileptr ; orient = ptr->corient ; inverse = 0 ; if(!(padptr->macroNotPad)){ numpadsG++ ; } if( padptr->oldformat ){ /* calculate effective orientation to pad B */ inverse = transTableS[padptr->padside][orient] ; } else if( padptr->padside == MMC ){ /* calculate effective orientation for hardcell. */ /* Normal inverse use side B */ inverse = transTableS[B][orient] ; } else { /* the new pad format */ if( orient ){ /* ************** INITIAL ORIENTATION NOT ZERO ************ */ /* normally user inputs pads in orientation 0. However, MC will */ /* output the pad with the orientation set to the appropriate side */ /* rotate to orientation 0 perform the inverse operation if */ /* necessary */ switch (padptr->padside) { case L: /* rotate 270 | -90 */ inverse = 6 ; break; case T: /* rotate 180 */ inverse = 3 ; break; case R: /* rotate 90 */ inverse = 7 ; break; case ALL: /* this is the case of no restriction */ /* and we came from floorplanning */ if( orient == 1 || orient == 3 ){ /* this is the top side */ inverse = orient ; break ; } else if( orient == 4 || orient == 6 ){ /* this is the right side */ if( orient == 6 ){ inverse = 7 ; } else { inverse = 4 ; } break ; } else if( orient == 5 || orient == 7 ){ /* this is the left side */ if( orient == 6 ){ inverse = 6 ; } else { inverse = 5 ; } break ; } else if( orient == 2 ){ /* this is the bottom side */ inverse = 2 ; break ; } case B: default: M( ERRMSG, "cleanup_readcell", "\nNON-PAD or PAD w/o valid side rotatation\n"); sprintf( YmsgG, "\tpad:%s is bogus\n", ptr->cname ) ; M( ERRMSG, NULL, YmsgG ) ; abortS = TRUE ; break; } } else { /* zero orientation means bottom side */ padptr->padside = B ; } } /* now translate the tile to correct orientation */ trans_tile( ptr, inverse ) ; if( (ptr->cheight % 2 != 0 && (inverse == 4 || inverse == 6))|| (ptr->clength % 2 != 0 && (inverse == 2 || inverse == 3))){ xFlag = TRUE ; } else { xFlag = FALSE ; } if( (ptr->cheight % 2 != 0 && (inverse == 1 || inverse == 3))|| (ptr->clength % 2 != 0 && (inverse == 4 || inverse == 7))){ yFlag = TRUE ; } else { yFlag = FALSE ; } /* calculate the txpos[1] and typos[1] fields which */ /* hold the cell relative pin position in current orientation */ for( pinptr = ptr->pins ; pinptr; pinptr = pinptr->nextpin ) { if( orient ){ /* if orientation is set and not a hardcell, it means */ /* we need to take the inverse first */ xpos = pinptr->txpos[0] ; ypos = pinptr->typos[0] ; REL_POS( inverse, pinptr->txpos[0], /* result */ pinptr->typos[0], /* result */ xpos, ypos, 0, 0 ) ; /* center */ } if( xFlag ) { xpos = pinptr->txpos[0] + 1 ; } else { xpos = pinptr->txpos[0] ; } if( yFlag && pinptr->typos[0] != 0 ) { ypos = pinptr->typos[0] + 1 ; } else { ypos = pinptr->typos[0] ; } REL_POS( ptr->corient, pinptr->txpos[1], pinptr->typos[1], /* result */ xpos, ypos, /* cell rel. */ 0, 0 ) ; /* make result cell relative */ } /* now set the length and height fields */ padptr->length = tptr->right - tptr->left ; padptr->height = tptr->top - tptr->bottom ; } /* * Configure the blocks, place the macro blocks and pads. * Also generate an initial placement of the standard cells */ totalpadsG = numpadsG + numpadgrpsG ; /* build the pad arrays */ /* now create sort array */ padarrayG = (PADBOXPTR *) Yvector_alloc(1,totalpadsG,sizeof(PADBOXPTR) ) ; sortarrayG = (PADBOXPTR *) Yvector_alloc(1,totalpadsG,sizeof(PADBOXPTR) ) ; placearrayG = (PADBOXPTR *) Yvector_alloc( 1,numpadsG,sizeof(PADBOXPTR) ) ; cell1 = 0 ; for( cell = 1; cell <= numtermsG; cell++ ){ ptr = carrayG[numcellsG + cell] ; padptr = ptr->padptr ; if( padptr->macroNotPad ){ continue ; } cell1++ ; sortarrayG[cell1] = padarrayG[cell1] = padptr ; if( padptr->padtype == PADTYPE ){ placearrayG[cell1] = padptr ; } } ASSERT( cell1 == totalpadsG, "cleanup_readcells", "Pad initialization problem" ) ; if( rowsG == 0 ) { configure() ; } else { total_desire = 0 ; bogus_rows = FALSE ; for( row = 1 ; row <= numRowsG ; row++ ) { total_desire += barrayG[row]->desire ; if( barrayG[row]->desire > celllenG && numRowsG > 1 ){ sprintf( YmsgG, "Unreasonable row length for row:%d. Please check\n", row ) ; M( ERRMSG, "cleanup_readcells", YmsgG ) ; bogus_rows = TRUE ; } } if( celllenG > 0 ){ fraction = (DOUBLE) total_desire / (DOUBLE) celllenG ; if( fraction < 0.70 || fraction > 1.30 ){ bogus_rows = TRUE ; } } else { bogus_rows = TRUE ; } if( bogus_rows ){ M( WARNMSG, "cleanup_readcells", "Cell length doesn't match row length\n" ) ; deviate_by_row = (celllenG - total_desire) / numRowsG ; for( row = 1 ; row <= numRowsG ; row++ ) { barrayG[row]->desire += deviate_by_row ; barrayG[row]->orig_desire += deviate_by_row ; barrayG[row]->blength += deviate_by_row ; barrayG[row]->bright += deviate_by_row ; } } random_placement() ; } /* now check for rigidly_fixed cells which may illegally overlap */ for( cell1 = 1 ; cell1 < numcellsG ; cell1++ ) { if( carrayG[cell1]->cclass != -5 ) { continue ; } row = carrayG[cell1]->cblock ; for( cell2 = cell1 + 1 ; cell2 <= numcellsG ; cell2++ ) { if( carrayG[cell2]->cclass != -5 ) { continue ; } if( row != carrayG[cell2]->cblock ) { continue ; } /* must conduct the overlap test */ if( carrayG[cell1]->cxcenter + carrayG[cell1]->tileptr->left >= carrayG[cell2]->cxcenter + carrayG[cell2]->tileptr->right ){ continue ; } if( carrayG[cell2]->cxcenter + carrayG[cell2]->tileptr->left >= carrayG[cell1]->cxcenter + carrayG[cell1]->tileptr->right ){ continue ; } sprintf( YmsgG, "\nFATAL -- rigidly_fixed cells <%s> and <%s> overlap\n", carrayG[cell1]->cname , carrayG[cell2]->cname ) ; M( ERRMSG, "cleanup_readcells", YmsgG ) ; abortS = TRUE ; } } /* now check for rigidly_fixed pads which may illegally overlap */ if( padspacingG == EXACT_PADS ){ for( cell1 = numcellsG + 1 ; cell1 < lastpadG; cell1++ ) { ptr = carrayG[ cell1 ] ; orient = ptr->corient ; tptr = ptr->tileptr ; l1 = tptr->left ; r1 = tptr->right ; b1 = tptr->bottom ; t1 = tptr->top ; YtranslateT( &l1, &b1, &r1, &t1, orient ) ; l1 += ptr->cxcenter ; r1 += ptr->cxcenter ; b1 += ptr->cycenter ; t1 += ptr->cycenter ; for( cell2 = cell1 + 1 ; cell2 <= lastpadG ; cell2++ ) { ptr = carrayG[ cell2 ] ; orient = ptr->corient ; tptr = ptr->tileptr ; l2 = tptr->left ; r2 = tptr->right ; b2 = tptr->bottom ; t2 = tptr->top ; YtranslateT( &l2, &b2, &r2, &t2, orient ) ; l2 += ptr->cxcenter ; r2 += ptr->cxcenter ; b2 += ptr->cycenter ; t2 += ptr->cycenter ; /* must conduct the overlap test */ if( l1 >= r2 ){ continue ; } if( l2 >= r1 ){ continue ; } if( b1 >= t2 ){ continue ; } if( b2 >= t1 ){ continue ; } /* the only case that would be fatal is two macro's overlapping */ if( carrayG[cell1]->padptr->macroNotPad && ptr->padptr->macroNotPad ){ sprintf( YmsgG, "\nmacros <%s> and <%s> overlap -- FATAL\n", carrayG[cell1]->cname , carrayG[cell2]->cname ) ; M( ERRMSG, "cleanup_readcells", YmsgG ) ; abortS = TRUE ; } else { sprintf( YmsgG, "\npads (or macros) <%s> and <%s> overlap -- NONFATAL\n", carrayG[cell1]->cname , carrayG[cell2]->cname ) ; M( ERRMSG, "cleanup_readcells", YmsgG ) ; M( ERRMSG, NULL, "Padspacing set to abut\n\n" ) ; padspacingG = ABUT_PADS ; } } } } /* check if position of fixed cells are within bounds of their rows */ for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( carrayG[cell]->cclass >= 0 ) { continue ; } if( ABS(carrayG[cell]->border) > barrayG[carrayG[cell]->cblock]->blength ) { sprintf( YmsgG, "initial placement assigned to cell <%s> is\n", carrayG[cell]->cname ); M( ERRMSG, "cleanup_readcells", YmsgG ) ; sprintf( YmsgG, "\toutside the length of its block (%d vs. %d)\n", ABS(carrayG[cell]->border), barrayG[carrayG[cell]->cblock]->blength ); M( ERRMSG, NULL, YmsgG ) ; abortS = TRUE ; } } if( abortS ){ M( ERRMSG, NULL,"\n\nFATAL errors exist in input\n" ); if(!(doGraphicsG)){ M( ERRMSG, NULL,"You are not running graphics.\n" ); M( ERRMSG, NULL,"Turn on graphics to see the problem!\n" ); } else { M( ERRMSG, NULL,"Entering process graphics to determine error\n" ) ; } G( init_heat_index() ) ; G( process_graphics() ) ; closegraphics() ; YexitPgm(PGMFAIL); } totallenG = 0; /* for Dick Davis at DEC */ orig_max_row_lengthG = 0 ; for( block = 1 ; block <= numRowsG ; block++ ) { totallenG += barrayG[ block ]->blength ; if( orig_max_row_lengthG < barrayG[block]->blength ) { orig_max_row_lengthG = barrayG[block]->blength ; } } fprintf( fpoG, "total cell length: %d\n", celllenG ) ; fprintf( fpoG, "total block length: %d\n", totallenG ) ; if( rowsG > 0 ) { totalRG = celllenG ; rowHeightG = barrayG[1]->btop - barrayG[1]->bbottom ; } if( swappable_gates_existG ) { Yhash_table_delete( swap_hash_tableS, free_swap_data ) ; } return ; } /* end cleanup_readcells */ not_supported( object ) char *object ; { sprintf( YmsgG, "%s is not supported -- sorry!\n", object ) ; M( ERRMSG, "not_supported", YmsgG ) ; abortS = TRUE ; } YHASHPTR get_net_table() { return( net_hash_tableS ) ; } /* end get_net_table */ add_eco() { ERRORABORT() ; ECOs_existG++ ; ptrS->ECO_flag = TRUE ; } /* end add_eco */ /* ***************************************************************** */ /* added below for pad capability */ init_corners() { minxS = INT_MAX ; maxxS = INT_MIN ; minyS = INT_MAX ; maxyS = INT_MIN ; ERRORABORT() ; /* assume a rectangle */ pptrS->xpoints = (INT *) Ysafe_malloc( 4 * sizeof(INT) ) ; pptrS->ypoints = (INT *) Ysafe_malloc( 4 * sizeof(INT) ) ; ptAllocS = 4 ; } /* end init_corners */ add_corner( x, y ) INT x, y ; { INT pt ; /* point counter */ minxS = MIN( x, minxS ) ; maxxS = MAX( x, maxxS ) ; minyS = MIN( y, minyS ) ; maxyS = MAX( y, maxyS ) ; ERRORABORT() ; pt = ++(pptrS->numcorners) ; if( pt >= ptAllocS ){ ptAllocS += 2 ; pptrS->xpoints = (INT *) Ysafe_realloc( pptrS->xpoints, ptAllocS * sizeof(INT) ) ; pptrS->ypoints = (INT *) Ysafe_realloc( pptrS->ypoints, ptAllocS * sizeof(INT) ) ; } /* store 0..numcorners-1 */ pptrS->xpoints[--pt] = x ; pptrS->ypoints[pt] = y ; } /* end add_corner */ process_corners() { INT xcenter ; /* center of cell */ INT ycenter ; /* center of cell */ INT pt ; /* point counter */ INT xsum ; /* sum of min and max in x */ INT ysum ; /* sum of min and max in y */ ERRORABORT() ; xsum = minxS + maxxS ; ysum = minyS + maxyS ; xcenter = ( minxS + maxxS ) / 2 ; ycenter = ( minyS + maxyS ) / 2 ; if( xsum < 0 && xsum % 2 ){ /* if cell is asymmetrical */ xcenter-- ; } if( ysum < 0 && ysum % 2 ){ /* if cell is asymmetrical */ ycenter-- ; } if( curCellTypeS == HARDCELLTYPE || curCellTypeS == PADTYPE ){ /* for hardcells and pads set the cell center location */ ptrS->cxcenter = xcenter ; ptrS->cycenter = ycenter ; } minxS -= xcenter ; maxxS -= xcenter ; minyS -= ycenter ; maxyS -= ycenter ; /* subtract off x and y center */ for( pt = 0; pt < pptrS->numcorners; pt++ ){ pptrS->xpoints[pt] -= xcenter ; pptrS->ypoints[pt] -= ycenter ; } add_tile( minxS, minyS, maxxS, maxyS ) ; } /* end process_corners */ add_padside( padside ) char *padside ; { INT numsides ; /* length of side restriction string */ INT i ; /* counter */ ERRORABORT() ; if( strcmp( padside , "MUL" ) == STRINGEQ ) { pptrS->padside = MUL ; pptrS->oldformat = TRUE ; pptrS->macroNotPad = TRUE ; numMacroG++ ; } else if( strcmp( padside , "MUR" ) == STRINGEQ ) { pptrS->padside = MUR ; pptrS->oldformat = TRUE ; pptrS->macroNotPad = TRUE ; numMacroG++ ; } else if( strcmp( padside , "MLL" ) == STRINGEQ ) { pptrS->padside = MLL ; pptrS->oldformat = TRUE ; pptrS->macroNotPad = TRUE ; numMacroG++ ; } else if( strcmp( padside , "MLR" ) == STRINGEQ ) { pptrS->padside = MLR ; pptrS->oldformat = TRUE ; pptrS->macroNotPad = TRUE ; numMacroG++ ; } else if( strcmp( padside , "ML" ) == STRINGEQ ) { pptrS->padside = ML ; pptrS->oldformat = TRUE ; numMacroG++ ; } else if( strcmp( padside , "MR" ) == STRINGEQ ) { pptrS->padside = MR ; pptrS->oldformat = TRUE ; pptrS->macroNotPad = TRUE ; numMacroG++ ; } else if( strcmp( padside , "MB" ) == STRINGEQ ) { not_supported("macro at position MB" ) ; } else if( strcmp( padside , "MT" ) == STRINGEQ ) { not_supported("macro at position MT"); } else if( strcmp( padside , "MM" ) == STRINGEQ ) { not_supported("macro at position MM"); } else if( strcmp( padside , "MTT" ) == STRINGEQ ) { pptrS->padside = MTT ; pptrS->oldformat = TRUE ; pptrS->macroNotPad = TRUE ; numMacroG++ ; } else if( strcmp( padside , "MBB" ) == STRINGEQ ) { pptrS->padside = MBB ; pptrS->oldformat = TRUE ; pptrS->macroNotPad = TRUE ; numMacroG++ ; } else { pptrS->valid_side[ALL] = FALSE ; numsides = strlen( padside ) ; for( i = 0 ; i < numsides; i++ ){ switch( padside[i] ){ case 'B' : pptrS->valid_side[B] = TRUE ; break ; case 'L' : pptrS->valid_side[L] = TRUE ; break ; case 'R' : pptrS->valid_side[R] = TRUE ; break ; case 'T' : pptrS->valid_side[T] = TRUE ; break ; default: sprintf( YmsgG, "side restriction not specified properly for pad:%s\n", curCellNameS ); M(ERRMSG,"add_padside",YmsgG ) ; abortS = TRUE ; } /* end switch */ } } } /* end add_padside */ add_sidespace( lower, upper ) DOUBLE lower, upper ; { ERRORABORT() ; if( pptrS->padside == L ) { fixLRBTG[0] = 1 ; } else if( pptrS->padside == R ) { fixLRBTG[1] = 1 ; } else if( pptrS->padside == B ) { fixLRBTG[2] = 1 ; } else if( pptrS->padside == T ) { fixLRBTG[3] = 1 ; } else { macspaceG[ pptrS->padside ] = (lower + upper) / 2.0 ; } pptrS->fixed = TRUE ; if( lower > 1.0 || upper > 1.0 ){ sprintf(YmsgG, "side space must be less or equal to 1.0 for pad: %s\n",curCellNameS ) ; M(ERRMSG,"add_sidespace",YmsgG ) ; abortS = TRUE ; } if( lower < 0.0 || upper < 0.0 ){ sprintf(YmsgG, "side space must be greater or equal to 0.0 for pad: %s\n",curCellNameS ) ; M(ERRMSG,"add_sidespace",YmsgG ) ; abortS = TRUE ; } if( lower > upper ){ sprintf(YmsgG, "side space upper bound must be greater or equal to lower bound for pad: %s\n",curCellNameS ) ; M(ERRMSG,"add_sidespace",YmsgG ) ; abortS = TRUE ; } pptrS->lowerbound = lower ; pptrS->upperbound = upper ; } /* end add_sidespace */ /* ***************************************************************** */ /* set whether a pad group can be permuted */ setPermutation( permuteFlag ) { ERRORABORT() ; pptrS->permute = permuteFlag ; } /* end setPermutation */ /* ***************************************************************** */ set_old_format( padside ) char *padside ; { ERRORABORT() ; if( strcmp( padside , "L" ) == STRINGEQ || strcmp( padside , "T" ) == STRINGEQ || strcmp( padside , "R" ) == STRINGEQ || strcmp( padside , "B" ) == STRINGEQ ){ pptrS->oldformat = TRUE ; /* set this switch to rotate pads */ old_pad_formatS = TRUE ; /* set this switch to add padgroups */ if( strcmp( padside , "L" ) == STRINGEQ ){ pptrS->padside = L ; } else if( strcmp( padside , "T" ) == STRINGEQ ){ pptrS->padside = T ; } else if( strcmp( padside , "R" ) == STRINGEQ ){ pptrS->padside = R ; } else if( strcmp( padside , "B" ) == STRINGEQ ){ pptrS->padside = B ; } } } /* set_old_format */ /* add this pad to the current pad group */ add2padgroup( padName, ordered ) char *padName ; BOOL ordered ; /* ordered flag is true if pad is fixed in padgroup */ { INT i, endofpads, endofgroups ; ERRORABORT() ; endofpads = numcellsG + numtermsG - numpadgrpsG ; /* check pads for correctness */ for (i = numcellsG + 1; i <= endofpads; i++) { if (strcmp(padName, carrayG[i]->cname) == STRINGEQ) { if (carrayG[i]->padptr->hierarchy == LEAF) { sprintf(YmsgG, "pad %s was included in more than 1 pad group\n", carrayG[i]->cname); M(ERRMSG,"add2padgroup",YmsgG ) ; abortS = TRUE ; return ; } /* check memory of pin array */ if( ++numchildrenS >= childAllocS ){ childAllocS += EXPECTEDNUMPADS ; pptrS->children = (INT *) Ysafe_realloc( pptrS->children, childAllocS * sizeof(INT) ) ; } pptrS->children[numchildrenS] = i - numcellsG - numMacroG ; carrayG[i]->padptr->hierarchy = LEAF ; carrayG[i]->padptr->ordered = ordered ; ptrS->numterms += carrayG[i]->numterms; return; } } /* if no match above must be subroot */ endofgroups = numcellsG + numtermsG ; for (i = endofpads; i <= endofgroups; i++ ) { if (strcmp(padName, carrayG[i]->cname) == STRINGEQ) { if (carrayG[i]->padptr->hierarchy == SUBROOT) { sprintf(YmsgG, "pad group %s was included in more than 1 pad group\n", curCellNameS ) ; M(ERRMSG,"add2padgroup",YmsgG ) ; abortS = TRUE ; return ; } /* check memory of pin array */ if( ++numchildrenS >= childAllocS ){ childAllocS += EXPECTEDNUMPADS ; pptrS->children = (INT *) Ysafe_realloc( pptrS->children, childAllocS * sizeof(INT) ) ; } pptrS->children[numchildrenS] = i - numcellsG - numMacroG ; carrayG[i]->padptr->hierarchy = SUBROOT ; carrayG[i]->padptr->ordered = ordered ; /* total pins of the leaves */ ptrS->numterms += carrayG[i]->numterms; return ; } } sprintf(YmsgG,"cannot find pad <%s> for pad_group <%s>\n", padName,ptrS->cname); M(ERRMSG,"add2padgroup",YmsgG ) ; return ; } /* end add2PadGroup */ end_padgroup() { ERRORABORT() ; /* realloc size of children array to final size */ pptrS->children = (INT *) Ysafe_realloc( pptrS->children,(numchildrenS+1) * sizeof(INT)); pptrS->children[HOWMANY] = numchildrenS ; // if( numchildrenS <= 1 ){ if( numchildrenS < 1 ){ M(ERRMSG,"end_padgroup", // "Must have at least 2 pads in a padgroup.\n"); "Must have at least 1 pad in a padgroup.\n"); sprintf( YmsgG, "\t%s only has %d pad\n", curCellNameS, numchildrenS ) ; abortS = TRUE ; M(ERRMSG, NULL, YmsgG ) ; } } /* end_padgroup */ /* ***************************************************************** */ graywolf-0.1.4+20170307gite1bf319/src/twsc/parser.h000066400000000000000000000022711305746555600212020ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) parser.h (Yale) version 4.5 9/7/90" FILE: parser.h DESCRIPTION:definitions for parsing. CONTENTS: DATE: Dec 8, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef PARSER_H #define PARSER_H #ifdef PARSER_VARS #define EXTERN #else #define EXTERN extern #endif /* cell types */ #define STDCELLTYPE 1 #define EXCEPTTYPE 2 #define PADTYPE 3 #define PORTTYPE 4 #define EXTRATYPE 5 #define PADGROUPTYPE 6 #define HARDCELLTYPE 7 /* pin types */ #define PINTYPE 1 #define PASS_THRU 2 #define SWAP_PASS 3 EXTERN SWAPBOX *swap_group_listG ; EXTERN BOOL one_pin_feedthruG ; EXTERN INT maxCellOG ; EXTERN INT case_unequiv_pinG ; EXTERN INT celllenG ; EXTERN INT cells_per_clusterG ; EXTERN INT cluster_widthG ; EXTERN INT extra_cellsG ; EXTERN INT *fixLRBTG ; EXTERN INT last_pin_numberG ; EXTERN INT num_clustersG ; EXTERN BOOL swappable_gates_existG ; EXTERN INT swap_netG ; EXTERN INT totallenG ; EXTERN DOUBLE *padspaceG ; #undef EXTERN #endif /* PARSER_H */ graywolf-0.1.4+20170307gite1bf319/src/twsc/paths.c000066400000000000000000000652531305746555600210310ustar00rootroot00000000000000/* * Copyright (C) 1988-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: paths.c DESCRIPTION:output length of paths CONTENTS: print_paths. INT calc_incr_time( cell ) INT cell ; update_time( cell ) INT cell ; INT calc_incr_time2( cella, cellb ) INT cella, cellb ; update_time2() init_path_set() add2path_set( path ) INT path ; PSETPTR enum_path_set() clear_path_set() init_net_set() add2net_set( net ) INT net ; BOOL member_net_set( net ) clear_net_set() INT dcalc_full_penalty(newtimepenal) INT dcalc_path_len(path_num) INT path_num ; DATE: Oct 22, 1988 REVISIONS: Dec 3, 1988 - completed timing driven code. Jan 29, 1989 - added \n's for pretty output. Mar 11, 1989 - added statistics to print_paths. - added wirelength to print_paths. Mar 13, 1989 - now output penalty in print_paths. Thu Dec 20 00:23:46 EST 1990 - removed += operator. Fri Jan 18 18:33:25 PST 1991 - updated output format. Thu Apr 18 01:52:21 EDT 1991 - added OOS for out of spec for easier searching. Sun Apr 21 21:25:12 EDT 1991 - added ignore keyword for analyze nets. Renamed for library stat function. Mon Aug 12 17:01:03 CDT 1991 - changed timing ASSERTIONS to D( ) constructs to speed execution time during debug mode. Fri Nov 8 01:08:41 EST 1991 - rewrote pad output file for easier understanding. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) paths.c version 4.12 4/2/92" ; #endif /* #define ZERO_CHECK */ #include "standard.h" #include "main.h" #include #include "readnets.h" #include #include /* global variables */ extern DOUBLE avg_timeG ;/* average random time penalty */ extern DOUBLE avg_funcG ;/* average random wirelength penalty */ /* forward declarations */ INT dcalc_min_path_len() ; INT dcalc_max_path_len() ; INT dcalc_path_len(INT, INT); static INT errorboundS = 0 ; print_paths( ) { char filename[LRECL] ; INT i, pathLength ; INT length ; INT above, really_above, really_below, below, in ; INT check, way_above, way_below ; INT really_way_above, really_way_below ; INT *stat ; INT xspan, yspan ; PATHPTR pptr, get_path_list() ; GLISTPTR net ; DBOXPTR nptr ; PINBOXPTR netptr ; FILE *fp ; DOUBLE mean ; DOUBLE paths ; INT num_paths ; INT penaltyS ; i = 0 ; above = 0 ; really_above = 0 ; way_above = 0 ; really_way_above = 0 ; below = 0 ; really_below = 0 ; way_below = 0 ; really_way_below = 0 ; in = 0 ; penaltyS = 0 ; /* get total number of paths in timing analysis */ num_paths = get_total_paths() ; /* allocate the an array for calculating statistics */ if( num_paths ){ stat = (INT *) Ysafe_malloc( num_paths * sizeof(INT) ) ; } sprintf(filename, "%s.pth" , cktNameG ) ; fp = TWOPEN( filename , "w", ABORT ) ; /* first the lengths of the nets */ fprintf( fp, "The paths:\n" ) ; fprintf( fp, "##############################################\n" ) ; for( pptr=get_path_list() ;pptr;pptr=pptr->next ){ pathLength = 0 ; xspan = 0 ; yspan = 0 ; /* get pathLength for path */ fprintf( fp, "\npath %3d:\n",++i ) ; for( net = pptr->nets ; net ; net = net->next ){ nptr = netarrayG[net->p.net] ; fprintf( fp, "\t\t%s\n", nptr->name ) ; length = (INT)(horizontal_path_weightG * (DOUBLE) nptr->halfPx) + (INT)(vertical_path_weightG * (DOUBLE) nptr->halfPy) ; pathLength += length ; xspan += nptr->halfPx ; yspan += nptr->halfPy ; } fprintf( fp, "\tpriority:%d lower_bound:%d upper_bound:%d\n", pptr->priority, pptr->lower_bound, pptr->upper_bound ) ; fprintf( fp,"\tweighted length:%d\n", pathLength ) ; fprintf( fp, "\txspan:%d yspan:%d length:%d ", xspan, yspan, xspan+yspan ) ; if( pptr->priority ){ ASSERT( pathLength == pptr->path_len,"print_paths", "pathLength does not equal incremental value " ) ; } check = FALSE ; for( net = pptr->nets ; net ; net = net->next ){ netptr = netarrayG[net->p.net]->pins ; for( ; netptr ; netptr = netptr->next ) { if( netptr->cell > numcellsG ) { check = TRUE ; break ; } } } if( pathLength < pptr->lower_bound ){ penaltyS += pptr->lower_bound - pathLength ; fprintf( fp, "*" ) ; if( check ) { fprintf( fp, " pad" ) ; } if( pathLength < (INT)( 0.90 * (DOUBLE) pptr->lower_bound) ){ below++ ; if( !check ) { really_below++ ; } } if( pathLength < (INT)( 0.80 * (DOUBLE) pptr->lower_bound) ){ way_below++ ; fprintf( fp, " OOS" ) ; if( !check ) { really_way_below++ ; } } } else if( pathLength > pptr->upper_bound ){ penaltyS += pathLength - pptr->upper_bound ; fprintf( fp, "*" ) ; check = FALSE ; for( net = pptr->nets ; net ; net = net->next ){ netptr = netarrayG[net->p.net]->pins ; for( ; netptr ; netptr = netptr->next ) { if( netptr->cell > numcellsG ) { check = TRUE ; break ; } } } if( check ) { fprintf( fp, " pad" ) ; } if( pathLength > (INT)( 1.10 * (DOUBLE) pptr->upper_bound) ){ above++ ; if( !check ) { really_above++ ; } } if( pathLength > (INT)( 1.20 * (DOUBLE) pptr->upper_bound) ){ way_above++ ; fprintf( fp, " OOS" ) ; if( !check ) { really_way_above++ ; } } } else { in++ ; } fprintf( fp, "\n" ) ; /* add pathlength to stat array */ stat[i-1] = pathLength ; } /* first the lengths of the nets */ fprintf( fp, "\nThe nets:\n" ) ; fprintf( fp, "##############################################\n" ) ; for( i=1;i<=numnetsG;i++ ){ nptr = netarrayG[i] ; fprintf( fp, "net %3d:%s xspan:%d yspan:%d length:%d numpins:%d", i, nptr->name, nptr->halfPx, nptr->halfPy, (INT)(horizontal_path_weightG * (DOUBLE) nptr->halfPx) + (INT)(vertical_path_weightG * (DOUBLE) nptr->halfPy), nptr->numpins ) ; if( nptr->ignore ){ fprintf( fp, " ignored\n" ) ; } else { fprintf( fp, "\n" ) ; } } /* avoid a divide by zero */ if( num_paths ){ paths = (DOUBLE) num_paths ; fprintf( fp, "\nSummary:\n" ) ; fprintf( fp, "Total wirelength :%5d\n", funccostG ) ; fprintf( fp, "Total time penalty :%5d\n", penaltyS ) ; fprintf( fp, "Number of paths :%5d\n", num_paths ) ; fprintf( fp, "Number of active paths :%5d\n", numpathsG ) ; fprintf( fp, "Number of paths 10%% below spec :%5d - %4.2f%%\n", below, 100.0 * (DOUBLE) below / paths ) ; fprintf( fp, "Number of paths 10%% above spec :%5d - %4.2f%%\n", above, 100.0 * (DOUBLE) above / paths ) ; fprintf( fp, "Number of paths within spec :%5d - %4.2f%%\n", in, 100.0 * (DOUBLE) in / paths ) ; fprintf( fp, "# of non-pad paths out of spec :%5d\n", really_above + really_below ) ; fprintf( fp, "Number of paths 20%% below spec :%5d - %4.2f%%\n", way_below, 100.0 * (DOUBLE) way_below / paths ) ; fprintf( fp, "Number of paths 20%% above spec :%5d - %4.2f%%\n", way_above, 100.0 * (DOUBLE) way_above / paths ) ; fprintf( fp, "# of non-pad paths out of spec :%5d\n", really_way_above + really_way_below ) ; fprintf( fp, "Min length :%4.2le\n", Ystat_min( stat, num_paths, sizeof(INT) ) ) ; fprintf( fp, "Max length :%4.2le\n", Ystat_max( stat, num_paths, sizeof(INT) ) ) ; mean = Ystat_mean( stat, num_paths, sizeof(INT) ) ; fprintf( fp, "Mean length :%4.2le\n", mean ) ; fprintf( fp, "Standard Dev. length :%4.2le\n", sqrt( Ystat_var( stat, num_paths, sizeof(INT),mean) ) ) ; Ysafe_free( stat ) ; } TWCLOSE( fp ) ; } /* end print_paths */ /* ----------------------------------------------------------------- The update path routines The incremental routines speed execution by looking at only those paths connected to the cells that are to be moved. In addition, only those nets which are modified by the move are updated. This gives us an incremental length which we add to old half perimeter to give us total lenght of this net. The penalty is based on this length. We calculate an incremental penalty based on the change in the penalty. ----------------------------------------------------------------- */ /* calculate the timing cost incrementally */ INT calc_incr_time( cell ) INT cell ; { INT newpenal ; /* proposed move's timing penalty delta */ INT oldpenal ; /* the old penalty of the nets that move */ INT path_num ; /* name of path */ INT net ; /* net of path */ INT length ; /* path length incremental */ GLISTPTR pptr ; /* pointer to paths of a cell */ GLISTPTR net_of_path ; PATHPTR path ; DBOXPTR dimptr ; newpenal = 0 ; oldpenal = 0 ; /* for all paths of the cell that has moved */ for( pptr = carrayG[cell]->paths; pptr ; pptr = pptr->next ) { length = 0 ; path_num = pptr->p.path ; ASSERTNCONT( path_num > 0 && path_num <= numpathsG, "calc_incr_time", "path is out of bounds" ) ; path = patharrayG[path_num] ; /* for all nets k of a path i */ for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ if( member_net_set( net ) ){ /* this half - perimeter has changed use update */ /* calculate total change on path */ length = length + (INT) (horizontal_path_weightG * (DOUBLE) dimptr->newhalfPx ) ; length = length - (INT) (horizontal_path_weightG * (DOUBLE) dimptr->halfPx ) ; length = length + (INT) (vertical_path_weightG * (DOUBLE) dimptr->newhalfPy ) ; length = length - (INT) (vertical_path_weightG * (DOUBLE) dimptr->halfPy ) ; } /* else this half - perimeter has not changed use old */ } /* save total result - change to total length */ path->new_path_len = length += path->path_len ; D( "twsc/check_timing", ASSERT( dcalc_path_len(path_num,length),"update_time", "length mismatch" ) ; ) ; /* calculate change in timing penalty */ /* no penalty if within target window */ /* lowerbound <= length <= upperbound */ if( length > path->upper_bound ){ newpenal += length - path->upper_bound ; } else if( length < path->lower_bound ){ newpenal += path->lower_bound - length ; } /* now the old penalty */ if( path->path_len > path->upper_bound ){ oldpenal += path->path_len - path->upper_bound ; } else if( path->path_len < path->lower_bound ){ oldpenal += path->lower_bound - path->path_len ; } } /* end loop on the paths of a cell */ /* return the change in penalty */ return( newpenal - oldpenal ) ; } /* end function calc_incr_time */ update_time( cell ) INT cell ; { INT path_num ; /* name of path */ GLISTPTR pptr ; /* pointer to paths of a cell */ PATHPTR path ; /* for all paths of the cell that has moved */ for( pptr = carrayG[cell]->paths; pptr ; pptr = pptr->next ) { path_num = pptr->p.path ; ASSERTNCONT( path_num > 0 && path_num <= numpathsG, "update_time", "path is out of bounds" ) ; path = patharrayG[path_num] ; /* keep result */ path->path_len = path->new_path_len ; } } /* end function update_time */ /* calculate the timing cost incrementally for two cells */ INT calc_incr_time2( cella, cellb ) INT cella ; INT cellb ; { INT newpenal ; /* proposed move's timing penalty delta */ INT oldpenal ; /* the old penalty of the nets that move */ INT path_num ; /* name of path */ INT net ; /* net of path */ INT length ; /* path length incremental */ GLISTPTR pptr ; /* pointer to paths of a cell */ GLISTPTR net_of_path ; PATHPTR path ; PSETPTR pathlist, enum_path_set() ; DBOXPTR dimptr ; newpenal = 0 ; oldpenal = 0 ; clear_path_set() ; /* use add2path_set to get union of paths from cella and cellb */ for( pptr = carrayG[cella]->paths; pptr ; pptr = pptr->next ) { add2path_set( pptr->p.path ) ; } for( pptr = carrayG[cellb]->paths; pptr ; pptr = pptr->next ) { add2path_set( pptr->p.path ) ; } /* now use UNIQUE list of the union of the two cell's paths */ for( pathlist=enum_path_set(); pathlist; pathlist=pathlist->next){ length = 0 ; path_num = pathlist->path ; ASSERTNCONT( path_num > 0 && path_num <= numpathsG, "calc_incr_time2", "path is out of bounds" ) ; path = patharrayG[path_num] ; /* for all nets k of a path i */ for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ if( member_net_set( net ) ){ /* this half - perimeter has changed use update */ /* calculate total change on path */ length = length + (INT) (horizontal_path_weightG * (DOUBLE) dimptr->newhalfPx ) ; length = length - (INT) (horizontal_path_weightG * (DOUBLE) dimptr->halfPx ) ; length = length + (INT) (vertical_path_weightG * (DOUBLE) dimptr->newhalfPy ) ; length = length - (INT) (vertical_path_weightG * (DOUBLE) dimptr->halfPy ) ; } /* else this half - perimeter has not changed use old */ } /* save total result - change to total length */ path->new_path_len = length += path->path_len ; D( "twsc/check_timing", ASSERT( dcalc_path_len(path_num,length),"update_time", "length mismatch" ) ; ) ; /* calculate change in timing penalty */ /* no penalty if within target window */ /* lowerbound <= length <= upperbound */ if( length > path->upper_bound ){ newpenal += length - path->upper_bound ; } else if( length < path->lower_bound ){ newpenal += path->lower_bound - length ; } /* now the old penalty */ if( path->path_len > path->upper_bound ){ oldpenal += path->path_len - path->upper_bound ; } else if( path->path_len < path->lower_bound ){ oldpenal += path->lower_bound - path->path_len ; } } /* end loop on paths */ /* return the change in penalty */ return( newpenal - oldpenal ) ; } /* end function calc_incr_time2 */ update_time2() { PATHPTR path ; PSETPTR pathlist, enum_path_set() ; /* now use UNIQUE list of the union of the two cell's paths */ for( pathlist=enum_path_set(); pathlist; pathlist=pathlist->next){ ASSERTNCONT( pathlist->path > 0 && pathlist->path <= numpathsG, "update_time2", "path is out of bounds" ) ; path = patharrayG[pathlist->path] ; /* keep result */ path->path_len = path->new_path_len ; } } /* end function update_time */ /* ----------------------------------------------------------------- The set required in the update path routines needs the following operations done efficiently : membership - O(1) add to set if unique - O(1) clear set - O(1) set enumeration - O( paths in set ) Below is a space hungry O( numpaths ) but time efficient implementation We combine two data structures to accomplish this goal. We use array for testing membership and uniqueness but use list for enumeration. By incrementing count we can reinitialize easily. Note: PSETBOX, PSETPTR definitions are in custom.h ----------------------------------------------------------------- */ static PSETPTR path_set_listS ; /* list is beginning of set as a list */ static PSETPTR *path_set_arrayS ; /* set is an array of path set boxes */ static INT path_set_countS ; /* current set count */ /* initialize set */ init_path_set() { INT i ; path_set_arrayS=(PSETPTR *)Ysafe_malloc((numpathsG+1)*sizeof(PSETPTR)); for( i=0;i<=numpathsG;i++ ){ path_set_arrayS[i] = (PSETPTR) Ysafe_calloc( 1, sizeof(PSETBOX) ) ; } path_set_countS = 1 ; path_set_listS = NULL ; } /* end initset */ /* add a path to the set if not already in set */ add2path_set( path ) INT path ; { PSETPTR temp, cpath ; if( path >= 1 && path <= numpathsG ){ cpath = path_set_arrayS[path] ; /* something is a member in set is counts match */ if( cpath->member != path_set_countS ){ /* new path to be added */ /* connect to the single linked list */ if( temp = path_set_listS ){ /* hook to old list */ path_set_listS = cpath ; cpath->next = temp ; } else { path_set_listS = cpath ; /* terminate new list */ cpath->next = NULL ; } cpath->path = path ; /* store data */ cpath->member = path_set_countS ; /* store membership */ } } else { M( ERRMSG, "ADD2SET","value of path is out of bounds of set\n" ) ; } } /* end add2path_set */ PSETPTR enum_path_set() { return( path_set_listS ) ; } clear_path_set() { path_set_countS ++ ; path_set_listS = NULL ; } /* end clear_path_set */ /* ----------------------------------------------------------------- Below is a second set of set routines required in the update path routines which operate on nets instead of paths. The following operations need to be done efficiently : membership - O(1) add to set if unique - O(1) clear set - O(1) Since we don't need to enumerate set we only need array to implement this set. ----------------------------------------------------------------- */ static INT *net_set_array ; /* set is an array of net set boxes */ static INT net_set_count ; /* current set count */ /* initialize set */ init_net_set() { net_set_array = (INT *) Ysafe_calloc((numnetsG+1), sizeof(INT) ); net_set_count = 1 ; } /* end initset */ /* add a net to the set if not already in set */ add2net_set( net ) INT net ; { if( net >= 1 || net <= numnetsG ){ /* current count make array member a valid member of set */ net_set_array[net] = net_set_count ; } else { M( ERRMSG, "ADD2SET", "value of path is out of bounds of set" ) ; } } /* end add2net_set */ BOOL member_net_set( net ) /* test for membership */ { if( net_set_array[net] == net_set_count ){ return( TRUE ) ; } else { return( FALSE ) ; } } /* end member_net_set */ clear_net_set() { /* to clear set we only need to increment net_set_count */ /* we can use this set up to 2 Gig times without any problem */ net_set_count ++ ; } /* end clear_path_set */ #ifdef DEBUG /* *************** DEBUG FUNCTIONS *************************** */ /* debug function to make sure calculation is correct */ INT dcalc_full_penalty( newtimepenal ) INT newtimepenal ; { INT timingpenal ; INT pathcount ; INT length ; /* path length incremental */ INT net ; /* net of path */ GLISTPTR net_of_path ; PATHPTR path ; DBOXPTR dimptr ; /* now calculate the penalties */ /* first the timing penalty */ timingpenal = 0 ; for( pathcount = 1 ; pathcount <= numpathsG ; pathcount++ ) { path = patharrayG[pathcount] ; ASSERTNCONT( path, "dcalc_full_penalty", "pointer to path is NULL" ) ; /* for all nets k of a path i */ length = 0 ; for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ if( member_net_set( net ) ){ /* this half - perimeter has changed use update */ /* calculate total change on path */ length = length + (INT) (horizontal_path_weightG * (DOUBLE) dimptr->newhalfPx ) ; length = length + (INT) (vertical_path_weightG * (DOUBLE) dimptr->newhalfPy) ; } else { /* old length */ length = length + (INT) (horizontal_path_weightG * (DOUBLE) dimptr->halfPx) ; length = length + (INT) (vertical_path_weightG * (DOUBLE) dimptr->halfPy ) ; } } /* calculate penalty */ /* no penalty if within target window */ /* lowerbound <= length <= upperbound */ if( length > path->upper_bound ){ timingpenal += length - path->upper_bound ; } else if( length < path->lower_bound ){ timingpenal += path->lower_bound - length ; } } if( ABS( timingpenal - newtimepenal ) > errorboundS ){ errorboundS = ABS( timingpenal - newtimepenal ) ; return( FALSE ) ; } else { return( TRUE ) ; } } INT dcalc_path_len(path_num,verify_length) INT path_num ; INT verify_length ; { INT net ; /* net of path */ INT length ; /* path length incremental */ GLISTPTR net_of_path ; PATHPTR path ; DBOXPTR dimptr ; path = patharrayG[path_num] ; /* for all nets k of a path i */ length = 0 ; for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ if( member_net_set( net ) ){ /* this half - perimeter has changed use update */ /* calculate total change on path */ length = length + (INT) (horizontal_path_weightG * (DOUBLE) dimptr->newhalfPx); length = length + (INT) (vertical_path_weightG * (DOUBLE) dimptr->newhalfPy) ; } else { /* old length */ length = length + (INT) (horizontal_path_weightG * (DOUBLE) dimptr->halfPx ) ; length = length + (INT) (vertical_path_weightG * (DOUBLE) dimptr->halfPy ) ; } } if( ABS( length - verify_length ) > errorboundS ){ errorboundS = ABS( length - verify_length ) ; return( FALSE ) ; } else { return( TRUE ) ; } } INT dpath_len( net_num, old_not_new ) INT net_num ; BOOL old_not_new ; { INT net ; /* net of path */ INT length ; /* path length incremental */ INT timingpenal ; GLISTPTR net_of_path ; PATHPTR path ; GLISTPTR pptr ; /* pointer to paths of a cell */ DBOXPTR dimptr ; timingpenal = 0 ; for( pptr = netarrayG[net_num]->paths; pptr ; pptr = pptr->next ) { path = patharrayG[pptr->p.path] ; /* for all nets k of a path i */ length = 0 ; for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; /* accumulate length of path */ if( old_not_new ){ /* old length */ length = length + (INT) (horizontal_path_weightG * (DOUBLE) dimptr->halfPx ) ; length = length + (INT) (vertical_path_weightG * (DOUBLE) dimptr->halfPy ) ; } else { /* this half - perimeter has changed use update */ /* calculate total change on path */ length = length + (INT) (horizontal_path_weightG * (DOUBLE) dimptr->newhalfPx); length = length + (INT) (vertical_path_weightG * (DOUBLE) dimptr->newhalfPy) ; } } /* calculate penalty */ /* no penalty if within target window */ /* lowerbound <= length <= upperbound */ if( length > path->upper_bound ){ timingpenal += length - path->upper_bound ; } else if( length < path->lower_bound ){ timingpenal += path->lower_bound - length ; } } /* end for( pptr = netarrayyG[net_num]->paths... */ return( timingpenal ) ; } /* end INT dpath_len() */ INT dprint_error() { sprintf( YmsgG, "\n\nWe found that the timing error was bound by :%d\n\n", errorboundS ) ; M( MSG, "dprint_error", YmsgG ) ; return( 0 ) ; } /* end dprint_error() */ dverify_nets() { INT net ; /* net of path */ INT per ; DBOXPTR dimptr ; for( net=1; net <= numnetsG; net++ ){ dimptr = netarrayG[net] ; per = dimptr->xmax - dimptr->xmin ; ASSERTNCONT( per == dimptr->halfPx, "dverify_nets", "problem") ; per = dimptr->ymax - dimptr->ymin ; ASSERTNCONT( per == dimptr->halfPy, "dverify_nets", "problem") ; } } /* end dverify_nets */ dprint_paths( cell ) { INT path_num ; /* name of path */ INT net ; /* net of path */ GLISTPTR pptr ; /* pointer to paths of a cell */ GLISTPTR net_of_path ; PATHPTR path ; DBOXPTR dimptr ; /* for all paths of the cell that has moved */ for( pptr = carrayG[cell]->paths; pptr ; pptr = pptr->next ) { path_num = pptr->p.path ; path = patharrayG[path_num] ; fprintf( stderr, "path:%d, cur_len:%d new_len:%d\n", path_num, path->path_len, path->new_path_len ) ; /* for all nets k of a path i */ for( net_of_path=path->nets;net_of_path;net_of_path=net_of_path->next ){ net = net_of_path->p.net ; dimptr = netarrayG[net] ; fprintf( stderr, " net:%4d Px:%6d nPx:%6d Py:%6d nPy:%6d ", net, dimptr->halfPx, dimptr->newhalfPx, dimptr->halfPy, dimptr->newhalfPy ) ; /* accumulate length of path */ if( member_net_set( net ) ){ fprintf( stderr, "*" ) ; } fprintf( stderr, "\n" ) ; } /* end for( net_of_path... */ } /* end for( pptr... */ } /* end dprint_paths() */ dprint_net_set() { INT net ; fprintf( stderr, "Current net set:\n" ) ; for( net = 1; net <= numnetsG; net++ ){ if( member_net_set( net ) ){ fprintf( stderr, "%d ", net ) ; } } fprintf( stderr, "\n" ) ; } /* end dprint_net_set() */ #endif /* DEBUG */ #define TIMEDAMPFACTOR 1.0 /* damping factor on time penalty */ DOUBLE calc_time_factor() { /* **** timing penalty controller **** */ #ifdef ZERO_CHECK timeFactorG = 0.0 ; #else if( avg_timeG == 0.0 ) { timeFactorG = 3.0 ; } else { timeFactorG = 3.0 * (DOUBLE) avg_funcG / (DOUBLE) avg_timeG ; } #endif return( timeFactorG ) ; } /* end function calc_time_penalty */ calc_init_timeFactor() { #ifdef ZERO_CHECK timeFactorG = 0.0 ; #else timeFactorG = 4.0 ; #endif fprintf(fpoG,"\n\nTIMING FACTOR (COMPUTED) : %f\n", timeFactorG ) ; } /* end calc_init_timeFactor */ graywolf-0.1.4+20170307gite1bf319/src/twsc/placepads.c000066400000000000000000000516421305746555600216430ustar00rootroot00000000000000/* * Copyright (C) 1988-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: placepads.c DESCRIPTION:This file contains the place pads routines. CONTENTS: placepads() find_core() setVirtualCore( flag ) BOOL flag ; find_core_boundry( left, right, bottom, top ) INT *left, *right, *bottom, *top ; get_global_pos( cell, l, b, r, t ) INT cell, *l, *r, *b, *t ; DATE: Aug 12, 1988 REVISIONS: Oct 24, 1988 - added virtual core switch to control pad placement. Jan 17, 1988 - add find_core_boundary for channel graph generation code - outgeo.c . Jan 20, 1989 - fixed problem when pad has no pin connected to it. Made sure softcells are using correct fields and coordinates are translated. Feb. 15, 1989 - added get_global_pos so that amount of duplicated code is reduced. Apr 30, 1989 - added bound to padcenter for non-virtual core placement. Modified putChildren to place padgroups with sidespace restriction. Oct 20, 1989 - Now pads are output with global routing density. Feb 7, 1990 - Updated placepad core coordinates to reflect new routing scheme. Sun Jan 20 21:47:52 PST 1991 - ported to AIX. Thu Feb 14 02:44:36 EST 1991 - new pad placement algorithm. Fri Feb 15 15:19:38 EST 1991 - modified for VARIABLE_PADS case. Sun Feb 17 21:07:39 EST 1991 - renamed globals. Wed Jun 5 16:39:11 CDT 1991 - added retain_side option and now pad pins correctly. Fri Sep 6 15:16:27 CDT 1991 - moved retain_side option so it works when no pad groups exist. Thu Sep 19 16:33:58 EDT 1991 - fixed problem with sidespace options when only a fraction of the pins to pads have connections to the core. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) placepads.c version 4.15 5/12/92" ; #endif #define PAD_VARS #include #include #include #include #include /* global references */ extern INT **pairArrayG ; /* ***************** STATIC FUNCTION DEFINITIONS ******************* */ static find_optimum_locations( P1(void) ) ; static place_pad( P2(PADBOXPTR pad,INT bestside ) ) ; static place_children( P5(PADBOXPTR pad,INT side,DOUBLE lb,DOUBLE ub,BOOL sr) ) ; static INT find_cost_for_a_side(P5(PADBOXPTR pad,INT side,DOUBLE lb,DOUBLE ub, BOOL spacing_restricted ) ) ; static find_core( P1(void) ) ; /* ***************** STATIC VARIABLE DEFINITIONS ******************* */ static BOOL virtualCoreS = FALSE ; static INT sumposS ; /* sum of the modified opt. pin pos. of pad pins */ static INT sumtieS ; /* sum of all the opt. pin pos. of pad pins */ static INT pin_countS ; /* number of pins found with valid connections */ static BOOL retain_sideS = FALSE ; /* during global routing side is set */ /*------------------------------------------------------------------- The placepads module tries to place the pads such that the distance between the pads and their nearest connected pins in the is minimized. It must also adhere to user-specified restrictions on side, position, spacing and ordering. ____________________________________________________________________*/ placepads() { if( padspacingG == EXACT_PADS ){ return ; } find_core(); /* GET THE UPDATED CORE'S DIMENSION */ D( "placepads/initially", print_pads( "pads initially\n", padarrayG, totalpadsG ) ; ) ; find_optimum_locations() ; D( "placepads/after_find_opt", print_pads( "pads after_cost\n", sortarrayG, totalpadsG ) ; ) ; sort_pads(); D( "placepads/after_sort", print_pads( "pads after sort\n", placearrayG, numpadsG ); ) ; align_pads(); D( "placepads/after_align", print_pads( "pads after align\n", placearrayG, numpadsG ) ; ) ; orient_pads(); D( "placepads/after_orient", print_pads( "pads after orient\n", placearrayG, numpadsG ) ; ) ; dimension_pads(); D( "placepads/after_dim", print_pads( "pads after dimension\n", placearrayG, numpadsG ) ; ) ; } /* end placepads */ /* ***************************************************************** */ static find_optimum_locations() { INT i ; /* pad counter */ INT side ; /* loop thru valid sides */ INT cost ; /* current cost */ INT bestpos ; /* best modified position for pad */ INT besttie ; /* best position for pad for tiebreak */ INT bestcost ; /* best cost for pad or padgroup */ INT bestside ; /* best side to place pad or padgroup */ PADBOXPTR pad ; /* current pad */ /** FIND OPTIMUM PLACE FOR PADS ACCORDING TO THE RESTRICTIONS **/ for( i = 1; i <= totalpadsG; i++ ){ /**** LEAVES AND SUBROOTS NEED TO BE PLACED ON THE SAME **** SIDE AS THEIR PARENT ROOT, HENCE WE PLACE THE ROOT **** FIRST, AND THEN PLACE ALL ITS CHILDREN **/ pad = padarrayG[i] ; if( pad->padtype == PADGROUPTYPE && pad->hierarchy == ROOT ){ /* the case of a padgroup root */ bestcost = INT_MAX ; bestside = 1 ; for (side = 1; side <= 4; side++ ) { if( pad->valid_side[ALL] || pad->valid_side[side] ){ cost = find_cost_for_a_side( pad,side, pad->lowerbound, pad->upperbound, pad->fixed ) ; if( cost < bestcost) { bestcost = cost; bestside = side ; } } } place_children( pad, bestside, pad->lowerbound, pad->upperbound, pad->fixed ) ; } else if( pad->padtype == PADTYPE && pad->hierarchy == NONE ) { /* the case of a pad that is not in a padgroup */ bestcost = INT_MAX ; bestpos = 0 ; besttie = 0 ; for (side = 1; side <= 4; side++ ) { if( pad->valid_side[ALL] || pad->valid_side[side] ){ cost = find_cost_for_a_side( pad,side, pad->lowerbound, pad->upperbound, pad->fixed ) ; if( cost < bestcost) { bestcost = cost; bestside = side ; bestpos = sumposS ; besttie = sumtieS ; } } } /* now use the best positions for the position */ sumposS = bestpos ; sumtieS = besttie ; place_pad( pad, bestside ) ; } /* end simple pad case */ } } /* end find_optimum */ /* ***************************************************************** */ static INT find_cost_for_a_side(pad,side,lb,ub,spacing_restricted) PADBOXPTR pad; INT side ; DOUBLE lb, ub ; BOOL spacing_restricted ; { INT i ; /* children counter */ INT pos ; /* current pos. of current core pin constrained*/ INT dist ; /* current distance from core pin to pad */ INT cost ; /* sum of the opt pad pins to closest core pin */ INT dist2 ; /* under restrictions dist from core pin to pad */ INT lowpos ; /* convert lower bound to a position */ INT uppos ; /* convert upper bound to a position */ INT bestpos ; /* best constrained pos for pad to core for 1 net */ INT besttie ; /* best position for pad to core for 1 net */ INT bestdist ; /* best distance for pad to core for 1 net */ INT tiebreak ; /* best place to put pad pin unconstrained */ BOOL pinFound ; /* true if we find a match on current net */ PINBOXPTR pinptr; /* current pin */ PINBOXPTR netterm;/* loop thru pins of a net */ PADBOXPTR child; /* go thru the children of the padgroup */ CBOXPTR cptr ; /* current cell */ PADBOXPTR padptr; /* use to check if pad */ /**** FOR NORMAL PADS AND LEAVES, JUST CALCULATE THE COST */ /*** AND POSITION. THE LEAF CASE IS THE RETURN CONDITION OF */ /*** THE RECURSION ON THE ROOT PADS ***/ if( retain_sideS && side != pad->padside ){ /* during global routing must retain the side */ return( PINFINITY ) ; } if( pad->hierarchy == LEAF || pad->hierarchy == SUBROOT ){ if( !(pad->valid_side[ALL]) && !(pad->valid_side[side]) ){ /* this is not a valid side return a huge cost */ return( PINFINITY ) ; } } /* At this point are guaranteed to have a valid side */ cost = 0 ; sumposS = 0 ; sumtieS = 0 ; /* determine spacing restrictions */ calc_constraints( pad, side, &lb, &ub, &spacing_restricted, &lowpos, &uppos ) ; if( pad->hierarchy == LEAF || pad->hierarchy == NONE ){ /**** FOR ALL PINS BELONGING TO THE SAME NET AS PINS ON THE PAD, FIND THE PIN CLOSEST TO THE SIDE IN padside. ****/ /**** ASSUME NO PIN WAS FOUND ***/ pin_countS = 0 ; for ( pinptr=carrayG[pad->cellnum]->pins;pinptr;pinptr=pinptr->nextpin) { bestdist = INT_MAX ; /*** GO TO FIRST TERMS OF THE NET TO MAKE SURE ALL TERMINALS ARE INCLUDED ***/ pinFound = FALSE ; netterm = netarrayG[pinptr->net]->pins; for( ;netterm ;netterm = netterm->next ) { /**** CALCULATE THE DISTANCE FROM CORE. **** pos IS THE POSITION OF THE PAD ON THIS SIDE **** WHICH RESULTS IN THE SHORTEST DISTANCE TO THE PIN. **** ONLY PINS ON CELLS ARE IN THIS CONTEST **/ cptr = carrayG[netterm->cell] ; if( (padptr = cptr->padptr) && !(padptr->macroNotPad)){ /* skip over this pad */ continue ; } switch (side) { case L: pos = netterm->ypos; dist = netterm->xpos - coreG[X][MINI]; break; case T: pos = netterm->xpos; dist = coreG[Y][MAXI] - netterm->ypos; break; case R: pos = netterm->ypos; dist = coreG[X][MAXI] - netterm->xpos; break; case B: pos = netterm->xpos; dist = netterm->ypos - coreG[Y][MINI]; break; default : pos = INT_MAX ; dist = INT_MAX ; } /* end switch on side */ tiebreak = pos ; /* save original spot */ if( spacing_restricted ){ /* the pad placement on the side has been */ /* restricted in some way */ if( lowpos <= pos && pos <= uppos ){ /* everythings cool do no extra distance */ dist2 = 0 ; } else if( lowpos > pos ){ dist2 = ABS( lowpos - pos ) ; pos = lowpos ; } else if( pos > uppos ){ dist2 = ABS( pos - uppos ) ; pos = uppos ; } /* modify the distance by it Manhattan length */ /* to the pad in the orthogonal direction */ /* since this pad is fixed at a point */ /* could modify this to be more accurate since we want matching padpin*/ dist += dist2 ; } if (dist < bestdist) { bestdist = dist; /*** UPDATE THE BEST DISTANCE */ bestpos = pos; /*** AND BEST POSITION */ besttie = tiebreak; /* save the original position */ pinFound = TRUE ; /* pin on this net was found */ } } /* for(;netterm... end looking at this net */ if( pinFound ){ /*** SUM UP THE BEST POSITION OF ALL PINS */ sumposS += bestpos ; sumtieS += besttie ; /*** KEEP TRACK OF THE TOTAL COST FOR THIS SIDE */ cost += bestdist; pin_countS++ ; } } /* end for loop on pins of the pad */ /*** IF NO PIN IS FOUND TO MATCH WITH PAD ARBITRARILY ***/ /*** SET best position to random number for THIS PAD ***/ if( pin_countS == 0 ){ if( spacing_restricted ){ /* average between constraints */ sumposS = (lowpos + uppos) / 2 ; } else { /* Randomly pick a cost to break ties in the case that this pad could go on any side. Small value will not effect padgroups */ cost = PICK_INT( 0, 3 ) ; switch (side) { case L: sumposS = PICK_INT( coreG[Y][MINI],coreG[Y][MAXI] ) ; break; case T: sumposS = PICK_INT( coreG[X][MINI],coreG[X][MAXI] ) ; break; case R: sumposS = PICK_INT( coreG[Y][MINI],coreG[Y][MAXI] ) ; break; case B: sumposS = PICK_INT( coreG[X][MINI],coreG[X][MAXI] ) ; break; default: break; } } sumtieS = sumposS ; } /* end pin_countS == 0 */ return( cost ) ; } else { /*** IF THE PAD IS A SUPERPAD, THEN SEARCH THROUGH ALL *** ITS CHILDREN AND SUM THE COST AND IDEAL POSITION *** RECURSIVELY. Use the spacing restrictions derived above. ***/ for( i = 1 ;i <= pad->children[HOWMANY]; i++ ){ child = padarrayG[pad->children[i]]; cost += find_cost_for_a_side( child, side, lb, ub, spacing_restricted ) ; } return( cost ); } } /* end find_cost_for_a_side */ /* ***************************************************************** */ /**** SET POSITION OF THE PAD. POS IS THE SUM OF THE OPTIMAL POSITION **** FOR ALL TERMINALS OF THE PAD. WE DIVIDE BY THE NUMBER OF TERMINAL **** TO GET THE AVERAGE. Place_pad must be performed immediately **** after a find_cost_for_a_side since sumposS and sumtieS **** are set in those routines. Otherwise set sumposS and sumtieS **** to their proper values. ***/ static place_pad( pad, bestside ) PADBOXPTR pad ; INT bestside ; { /* use the number of pins with valid connections */ /* pin_countS is set inf find_cost_for_a_side */ if( pin_countS == 0 ){ /*** SET PAD TO RANDOM POSITION DETERMINED IN find_cost_for_side*/ pad->position = sumposS ; pad->tiebreak = sumtieS ; } else { pad->position = sumposS / pin_countS ; pad->tiebreak = sumtieS / pin_countS ; } /* now bound pad center to current core boundary for normal case */ pad->padside = bestside ; #ifdef LATER switch( bestside ){ case L: case R: pad->position = MAX( pad->position, coreG[Y][MINI] ) ; pad->position = MIN( pad->position, coreG[Y][MAXI] ) ; break; case T: case B: pad->position = MAX( pad->position, coreG[X][MINI] ) ; pad->position = MIN( pad->position, coreG[X][MAXI] ) ; } /* end bound of pad position */ #endif } /* end place_pad */ /* ***************************************************************** */ /**** RECURSIVELY SET THE PADSIDE OF ALL CHILDREN OF THE ROOT PAD TO THE **** PADSIDE OF THE PARENT. GIVEN THAT SIDE, SET THE OPTIMAL CXCENTER */ static place_children( pad, side, lb, ub, spacing_restricted ) PADBOXPTR pad ; INT side ; DOUBLE lb, ub ; BOOL spacing_restricted ; { INT i ; /* pad counter */ INT pos ; /* position of last placed pad */ INT min_pos ; /* min position of the last padgroup */ INT max_pos ; /* max position of the last padgroup */ DOUBLE lowbound ; /* lower bound for pad or pad group */ DOUBLE hibound ; /* upper bound for pad or pad group */ PADBOXPTR child; /* go thru the children of the padgroup */ /* DETERMINE SPACING RESTRICTIONS */ lowbound = 0.0 ; hibound = 1.0 ; if( spacing_restricted ){ /* this is the case that the spacing has been restricted */ if( pad->fixed ){ /* if the padgroup bounds have been fixed, */ /* force position to be within bound */ /* assume we are ok and then correct it */ lowbound = pad->lowerbound ; if( lowbound < lb ){ lowbound = lb ; } if( lowbound > ub ){ lowbound = ub ; } hibound = pad->upperbound ; if( hibound < lb ){ hibound = lb ; } if( hibound > ub ){ hibound = ub ; } } else { /* this pad is not fixed use the given ub and lb */ lowbound = lb ; hibound = ub ; } } else { if( pad->fixed ){ /* the padgroup bounds have not been fixed */ /* just take the pad's restricted position */ lowbound = pad->lowerbound; hibound = pad->upperbound; spacing_restricted = TRUE ; } } /* **** END spacing restriction calculations *** */ if( pad->hierarchy == LEAF ){ find_cost_for_a_side( pad, side, lowbound, hibound, spacing_restricted ) ; place_pad( pad, side ) ; return ; } else { pos = 0 ; min_pos = INT_MAX ; max_pos = INT_MIN ; for( i = 1; i <= pad->children[HOWMANY]; i++ ){ child = padarrayG[pad->children[i]]; place_children( child, side, lowbound, hibound, spacing_restricted ) ; pos += child->position ; min_pos = MIN( child->position, min_pos ) ; max_pos = MAX( child->position, max_pos ) ; } if( pad->children[HOWMANY] ){ pad->position = pos /= pad->children[HOWMANY] ; } else { pad->position = pos ; } /* for tiebreak use the bounds of the padgroup and average them. */ /* set the side of the pad */ pad->padside = side ; pad->tiebreak = (min_pos + max_pos ) / 2 ; return ; } } /* end place_children */ /* ***************************************************************** */ /* ***************************************************************** */ #ifdef DEBUG print_pads( message, array, howmany ) char *message ; PADBOXPTR *array ; INT howmany ; { INT i ; PADBOXPTR ptr ; CBOXPTR cptr ; fprintf( stderr, "\n%s\n", message ) ; /* now print them out */ for( i = 1 ; i <= howmany; i++ ){ ptr = array[i] ; cptr = carrayG[ ptr->cellnum ] ; fprintf( stderr, "pad:%s x:%d y:%d type:%d side:%d pos:%d tie:%d orient:%d\n", cptr->cname, cptr->cxcenter, cptr->cycenter, ptr->hierarchy, ptr->padside, ptr->position, ptr->tiebreak, cptr->corient ) ; } fprintf( stderr, "\n" ) ; dimension_pads() ; G( process_graphics() ) ; } /* end print_pads */ #endif /* DEBUG */ /* ***************************************************************** */ static find_core() { INT minx, maxx ; INT miny, maxy ; INT l, r, b, t ; INT i ; INT num ; INT cell ; INT block ; INT xc, yc ; BBOXPTR bptr ; /* initialize xmin, ymax, etc. */ minx = INT_MAX ; miny = INT_MAX ; maxx = INT_MIN ; maxy = INT_MIN ; if( virtualCoreS ){ for( block = 1 ; block <= numRowsG ; block++ ) { num = pairArrayG[block][0] ; if( num == 0 ) { continue ; } cell = pairArrayG[block][ 1 ] ; l = carrayG[cell]->cxcenter + carrayG[cell]->tileptr->left ; cell = pairArrayG[block][ pairArrayG[block][0] ] ; r = carrayG[cell]->cxcenter + carrayG[cell]->tileptr->right ; minx = MIN( minx, l ) ; maxx = MAX( maxx, r ) ; } cell = pairArrayG[1][ 1 ] ; b = carrayG[cell]->cycenter + carrayG[cell]->tileptr->bottom ; miny = MIN( miny, b ) ; cell = pairArrayG[numRowsG][ 1 ] ; t = carrayG[cell]->cycenter + carrayG[cell]->tileptr->top ; maxy = MAX( maxy, t ) ; } else { for( block = 1 ; block <= numRowsG ; block++ ) { bptr = barrayG[block] ; xc = bptr->bxcenter ; yc = bptr->bycenter ; minx = MIN( minx, bptr->bleft + xc ) ; maxx = MAX( maxx, bptr->bright + xc ) ; miny = MIN( miny, bptr->bbottom + yc ) ; maxy = MAX( maxy, bptr->btop + yc ) ; } } /* now check macro cells if they exist */ for( i=numcellsG+1;i<=lastpadG;i++ ){ if( carrayG[i]->padptr->macroNotPad ){ /* only calculate position if it is a macro */ get_global_pos( i, &l, &b, &r, &t ) ; minx = MIN( minx, l ) ; maxx = MAX( maxx, r ) ; miny = MIN( miny, b ) ; maxy = MAX( maxy, t ) ; } } /* now guarantee space between core and pads */ minx -= track_pitchG ; miny -= track_pitchG ; maxx += track_pitchG ; maxy += track_pitchG ; /* now save the dimensions */ coreG[Y][MINI] = miny ; coreG[Y][MAXI] = maxy ; coreG[X][MINI] = minx ; coreG[X][MAXI] = maxx ; perdimG[X] = maxx - minx ; perdimG[Y] = maxy - miny ; } /* end FindCore */ /* turn virtual core on and off */ setVirtualCore( flag ) BOOL flag ; { virtualCoreS = flag ; } /* end set Virtual core */ /* given a cell it returns bounding box of cell in global coordinates */ get_global_pos( cell, l, b, r, t ) INT cell ; INT *l, *r, *b, *t ; { CBOXPTR ptr ; ptr = carrayG[cell] ; *l = ptr->tileptr->left ; *r = ptr->tileptr->right ; *b = ptr->tileptr->bottom ; *t = ptr->tileptr->top ; YtranslateT( l, b, r, t, (INT) ptr->corient ) ; /* now add xcenter ycenter to get global position */ *l += ptr->cxcenter ; *r += ptr->cxcenter ; *b += ptr->cycenter ; *t += ptr->cycenter ; } /* end get_global_pos */ placepads_retain_side( flag ) BOOL flag; { retain_sideS = flag ; } /* end placepads_retain_side */ graywolf-0.1.4+20170307gite1bf319/src/twsc/readblck.c000066400000000000000000000256121305746555600214540ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: readblck.c DESCRIPTION:read block file. CONTENTS: readblck( fp ) FILE *fp ; DATE: Mar 27, 1989 REVISIONS: Wed Jan 2 10:55:01 CST 1991 - moved DEC code to parser.c Thu Mar 7 02:42:59 EST 1991 - now there can be comments in the .blk file. Wed Sep 11 11:25:16 CDT 1991 - updated for new global router algorithm (feeds). ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) readblck.c (Yale) version 4.10 11/8/91" ; #endif #endif #define READBLCK_VARS #include "standard.h" #include "main.h" #include "parser.h" #include "readpar.h" #include "config.h" #include "readblck.h" /* global variable references */ extern INT spacer_widthG ; extern INT vertical_pitchG ; extern INT total_row_lengthG ; #if SIZEOF_VOID_P == 64 #define INTSCANSTR "%ld" #else #define INTSCANSTR "%d" #endif /* global variables */ readblck( fp ) FILE *fp ; { INT test , block , class , height , row , width , row_sep_abs ; INT lowerL_x , upperR_x , lowerL_y , upperR_y ; INT shift_amount , deviation , left_edge , reference_point ; DOUBLE relLen , row_sep , avg_row_sep , avg_row_height ; BOOL comment ; char input[1024] ; block = 0 ; rowsG = 0 ; num_exceptsG = 0 ; uniform_rowsG = 1 ; individual_rowSepsG = 0 ; total_except_widthG = 0 ; comment = FALSE ; while( fscanf( fp , " %s " , input ) == 1 ) { if( strncmp( input , "/*", 2 ) == STRINGEQ ){ comment = TRUE ; continue ; } else if( strncmp( input , "*/", 2 ) == STRINGEQ ){ comment = FALSE ; continue ; } if( comment ){ continue ; } if( strcmp( input , "block") == 0 ) { block++ ; } else if( strcmp( input , "row_sep") == 0 ) { test = fscanf( fp , " %lf " INTSCANSTR " " , &row_sep, &row_sep_abs ) ; if( test != 2 ) { test = fscanf( fp , " %lf " , &row_sep ) ; if( test != 1 ) { fprintf( fpoG,"Failed to input row_sep of a block\n"); fprintf( fpoG,"at position row_sep\n"); YexitPgm(PGMFAIL); } else { row_sep_abs = 0; } } if( ++individual_rowSepsG != block ) { fprintf( fpoG,"Failed to input a row_sep for each block\n"); YexitPgm(PGMFAIL); } } else if( strcmp( input , "height") == 0 ) { test = fscanf( fp , " " INTSCANSTR " " , &height ) ; if( test != 1 ) { fprintf( fpoG,"Failed to input height of a block\n"); fprintf( fpoG,"at position height\n"); YexitPgm(PGMFAIL); } } else if( strcmp( input , "class") == 0 ) { test = fscanf( fp , " " INTSCANSTR " " , &class ) ; if( test != 1 ) { fprintf( fpoG, "Failed to input class of a block\n"); fprintf( fpoG, "current block: %d\n", block ); YexitPgm(PGMFAIL); } if( class <= 0 || class > 256 ) { fprintf( fpoG, "block class is less than one "); fprintf( fpoG, "or greater than the limit (256)\n"); fprintf( fpoG, "current block: %d\n", block ); YexitPgm(PGMFAIL); } } else if( strcmp( input , "rows") == 0 ) { (void) fscanf( fp , " " INTSCANSTR " " , &rowsG ) ; } else if( strcmp( input , "except") == 0 ) { num_exceptsG++ ; test = fscanf(fp, INTSCANSTR " " INTSCANSTR, &lowerL_x, &upperR_x ) ; if( test != 2 ) { fprintf( fpoG, "error in new .blk format: except\n"); YexitPgm(PGMFAIL); } } else if( strcmp( input , "row") == 0 ) { test = fscanf(fp, INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR, &lowerL_x, &lowerL_y, &upperR_x, &upperR_y ) ; if( test != 4 ) { fprintf( fpoG, "error in new .blk format\n"); YexitPgm(PGMFAIL); } } else if( strcmp( input , "mirror") == 0 ) { } else if( strcmp( input , "relative_length") == 0 ) { (void) fscanf( fp , " %lf " , &relLen ) ; } else { fprintf( fpoG, "unexpected keyword in the .blk file\n"); fprintf( fpoG, "current block: %d\n", block ); YexitPgm(PGMFAIL); } } if( rowsG == 0 ) { numRowsG = block ; } else { numRowsG = rowsG ; total_row_lengthG = 0 ; } rewind( fp ) ; barrayG = (BBOXPTR *) Ysafe_malloc( (numRowsG + 1) * sizeof( BBOXPTR ) ) ; rowSepsG = (DOUBLE *) Ysafe_malloc( (numRowsG + 1) * sizeof( DOUBLE ) ) ; rowSepsAbsG = (INT *) Ysafe_malloc( (numRowsG + 1) * sizeof( INT ) ) ; relativeLenG = (DOUBLE *) Ysafe_malloc( (numRowsG + 1) * sizeof(DOUBLE)); for( block = 1 ; block <= numRowsG ; block++ ) { relativeLenG[block] = 1.0 ; } exceptionsG = (EXCEPTBOX *) Ysafe_malloc( (1 + num_exceptsG) * sizeof( EXCEPTBOX ) ) ; for( block = 1 ; block <= numRowsG ; block++ ) { barrayG[ block ] = (BBOXPTR) Ysafe_malloc( sizeof( BBOX )); barrayG[ block ]->bxcenter = 0 ; barrayG[ block ]->bycenter = 0 ; barrayG[ block ]->bleft = 0 ; barrayG[ block ]->bright = 0 ; barrayG[ block ]->bbottom = 0 ; barrayG[ block ]->btop = 0 ; barrayG[ block ]->bheight = 0 ; barrayG[ block ]->blength = 0 ; barrayG[ block ]->bclass = 0 ; barrayG[ block ]->borient = 0 ; barrayG[ block ]->desire = 0 ; barrayG[ block ]->oldsize = 0 ; barrayG[ block ]->newsize = 0 ; } block = 0 ; num_exceptsG = 0 ; celllenG = 0 ; comment = FALSE ; while( fscanf( fp , " %s " , input ) == 1 ) { if( strncmp( input , "/*", 2 ) == STRINGEQ ){ comment = TRUE ; continue ; } else if( strncmp( input , "*/", 2 ) == STRINGEQ ){ comment = FALSE ; continue ; } if( comment ){ continue ; } if( strcmp( input , "block" ) == 0 ) { block++ ; } else if( strcmp( input , "rows" ) == 0 ) { fscanf( fp , " " INTSCANSTR " " , &rowsG ) ; } else if( strcmp( input , "except") == 0 ) { num_exceptsG++ ; fscanf(fp, INTSCANSTR " " INTSCANSTR, &lowerL_x, &upperR_x ) ; celllenG += upperR_x - lowerL_x ; total_except_widthG += upperR_x - lowerL_x ; exceptionsG[num_exceptsG].row = block ; exceptionsG[num_exceptsG].ll_x = lowerL_x ; exceptionsG[num_exceptsG].ll_y = lowerL_y ; exceptionsG[num_exceptsG].ur_x = upperR_x ; exceptionsG[num_exceptsG].ur_y = upperR_y ; } else if( strcmp( input , "row" ) == 0 ) { block++ ; fscanf(fp, INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR, &lowerL_x, &lowerL_y, &upperR_x, &upperR_y ) ; height = upperR_y - lowerL_y ; width = upperR_x - lowerL_x ; total_row_lengthG += width ; barrayG[block]->bxcenter = (lowerL_x + upperR_x) / 2 ; barrayG[block]->bycenter = (lowerL_y + upperR_y) / 2 ; barrayG[block]->btop = height - height / 2 ; barrayG[block]->bbottom = - height / 2 ; barrayG[block]->bheight = height ; barrayG[block]->bright = width - width / 2 ; barrayG[block]->bleft = - width / 2 ; barrayG[block]->blength = width ; barrayG[block]->desire = width ; barrayG[block]->orig_desire = width ; barrayG[block]->bclass = 1 ; barrayG[block]->borient = 1 ; } else if( strcmp( input , "row_sep" ) == 0 ) { if (fscanf( fp , " %lf " INTSCANSTR " " , &row_sep, &row_sep_abs ) != 2) { fscanf( fp , " %lf " , &row_sep ); rowSepsAbsG[block] = 0; } else { rowSepsAbsG[block] = row_sep_abs ; } rowSepsG[block] = row_sep ; } else if( strcmp( input , "height" ) == 0 ) { fscanf( fp , " " INTSCANSTR " " , &height ) ; barrayG[block]->btop = height - height / 2 ; barrayG[block]->bbottom = - height / 2 ; barrayG[block]->bheight = height ; } else if( strcmp( input , "class" ) == 0 ) { fscanf( fp , " " INTSCANSTR " " , &class ) ; barrayG[block]->bclass = class ; barrayG[block]->borient = 1 ; } else if( strcmp( input , "mirror" ) == 0 ) { barrayG[block]->borient = 2 ; } else if( strcmp( input , "relative_length" ) == 0 ) { fscanf( fp , " %f " , &relLen ) ; relativeLenG[block] = relLen ; uniform_rowsG = 0 ; } } if( rowsG > 0 ) { /* then compute rowSepG */ if( rowsG > 1 ) { avg_row_sep = 0.0 ; for( row = 2 ; row <= rowsG ; row++ ) { avg_row_sep += (DOUBLE) barrayG[row]->bycenter - (DOUBLE) barrayG[row-1]->bycenter ; } avg_row_sep /= ((DOUBLE) rowsG - 1.0) ; avg_row_height = 0.0 ; for( row = 1 ; row <= rowsG ; row++ ) { avg_row_height += (DOUBLE) barrayG[row]->bheight ; } avg_row_height /= (DOUBLE) rowsG ; } else { avg_row_height = (DOUBLE) barrayG[1]->bheight ; avg_row_sep = avg_row_height ; } rowSepG = (avg_row_sep - avg_row_height) / avg_row_height ; } if( rowsG == 0 && rowSepG < 0.0 ) { fprintf( fpoG, "rowSep was not entered in the .par file\n"); YexitPgm(PGMFAIL); } else { fprintf( fpoG, "rowSep: %f\n" , rowSepG ) ; } if( rowsG > 0 ) { top_of_top_rowG = barrayG[rowsG]->bycenter + barrayG[rowsG]->btop ; bot_of_bot_rowG = barrayG[1]->bycenter + barrayG[rowsG]->bbottom ; /* make sure left edges of the rows latch to a grid relative to left edge of the first row */ if( vertical_pitchG > 0 ) { reference_point = barrayG[1]->bxcenter + barrayG[1]->bleft ; for( row = 2 ; row <= numRowsG ; row++ ) { shift_amount = 0 ; left_edge = barrayG[row]->bxcenter + barrayG[row]->bleft ; deviation = left_edge - reference_point ; if( deviation > 0 ) { deviation = deviation % vertical_pitchG ; if( deviation != 0 ) { if( deviation > vertical_pitchG / 2 ) { shift_amount = vertical_pitchG - deviation ; } else { shift_amount = - deviation ; } } } else if( deviation < 0 ) { deviation = (-deviation) % vertical_pitchG ; if( deviation != 0 ) { if( deviation > vertical_pitchG / 2 ) { shift_amount = -(vertical_pitchG - deviation) ; } else { shift_amount = deviation ; } } } barrayG[row]->bxcenter += shift_amount ; } } } return ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/readblck.h000066400000000000000000000017031305746555600214540ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) readblck.h (Yale) version 4.2 9/7/90" FILE: readblck.h DESCRIPTION:TimberwolfSC insert file for reading block file. CONTENTS: DATE: Mar 27, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef READBLCK_H #define READBLCK_H #ifdef READBLCK_VARS #define EXTERN #else #define EXTERN extern #endif typedef struct exceptbox { INT row ; INT ll_x ; INT ll_y ; INT ur_x ; INT ur_y ; } *EXCEPTPTR, EXCEPTBOX ; /* global variable definitions */ EXTERN INT num_exceptsG ; EXTERN INT top_of_top_rowG ; EXTERN INT bot_of_bot_rowG ; EXTERN INT uniform_rowsG ; EXTERN INT individual_rowSepsG ; EXTERN INT total_except_widthG ; EXTERN DOUBLE *rowSepsG ; EXTERN INT *rowSepsAbsG ; EXTERN DOUBLE *relativeLenG ; EXTERN EXCEPTBOX *exceptionsG ; #undef EXTERN #endif /* READBLCK_H */ graywolf-0.1.4+20170307gite1bf319/src/twsc/readcell.c000066400000000000000000001207101305746555600214530ustar00rootroot00000000000000/* * Copyright (C) 1990-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley) 01/20/90"; #endif #define YYBYACC 1 /* ----------------------------------------------------------------- FILE: readcell.c <- readcell.y <- readcell.l DESCRIPTION:This file contains the grammar (BNF) for the TimberWolfSC input file parser. The rules for lex are in readcell.l. The grammar for yacc is in readcell.y. The output of yacc (y.tab.c) is renamed to readcell.c CONTENTS: readcell( fp ) FILE *fp ; yyerror(s) char *s; yywrap() Note:readcell.c will also include the yacc parser. DATE: Jan 15, 1990 REVISIONS: Feb. 21st : added orient rule (for hardcells and pads for new .smcel file from BILL From Kalapi's work on the partitioner. Jan 15, 1991 - fixed fix_placement problem with fixed_type. Mon Jan 21 21:39:39 PST 1991 - now handle the options correctly. Sun Feb 17 21:06:47 EST 1991 - now sidespace has upper and lower bounds. Mon Feb 18 18:56:53 EST 1991 - now syntax error tells correct output file. Wed Apr 3 01:09:45 EST 1991 - now allow no pads yet have macros. Thu Apr 18 01:54:09 EDT 1991 - added initial orient and reversed numcorner. Sat May 11 22:51:19 EDT 1991 - pads without pins should only be a warning. Wed Jul 3 13:32:08 CDT 1991 - now handle more than one set of unequivs. Tue Aug 6 13:03:14 CDT 1991 - standard cells may now have 0 pins and name may be a string instead of an integer. Tue Aug 13 12:52:19 CDT 1991 - fixed problem with mirror and created_new_cell file. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) readcell.y (Yale) version 4.16 8/13/91" ; #endif #include #include #include #include #include "readcell.h" #include #include #include #undef REJECT #ifdef DEBUG #define YYDEBUG 1 /* condition compile for yacc debug */ #endif /* DEBUG */ /* #define LEXDEBUG 1 */ /* conditional compile for lex debug */ #ifdef LEXDEBUG /* two bugs in Yale version of lex */ #define allprint(x) fprintf( stdout, "%c\n", x ) #define sprint(x) fprintf( stdout, "%s\n", x ) #endif static char bufferS[LRECL] ; typedef union { INT ival ; char *string ; DOUBLE fval ; } YYSTYPE; #define INTEGER 257 #define STRING 258 #define FLOAT 259 #define FIXED 260 #define NONFIXED 261 #define RIGIDFIXED 262 #define APPROXIMATELY_FIXED 263 #define LEFT 264 #define RIGHT 265 #define BOTTOM 266 #define TOP 267 #define ASPLB 268 #define ASPUB 269 #define AT 270 #define BLOCK 271 #define CELL 272 #define CELLGROUP 273 #define CLASS 274 #define CORNERS 275 #define ECO_ADDED_CELL 276 #define ENDPINGROUP 277 #define EQUIV 278 #define FROM 279 #define GROUP 280 #define HARDCELL 281 #define INITIALLY 282 #define INSTANCE 283 #define LAYER 284 #define LEGALBLKCLASS 285 #define NAME 286 #define NEIGHBORHOOD 287 #define NOMIRROR 288 #define NOPERMUTE 289 #define OF 290 #define ORIENT 291 #define ORIENTATIONS 292 #define PAD 293 #define PADGROUP 294 #define PADSIDE 295 #define PERMUTE 296 #define PIN 297 #define PINGROUP 298 #define PORT 299 #define RESTRICT 300 #define SEQUENCE 301 #define SIDE 302 #define SIDERESTRICTION 303 #define SIDESPACE 304 #define SIGNAL 305 #define SOFTCELL 306 #define STDCELL 307 #define SUPERGROUP 308 #define SWAPGROUP 309 #define UNEQUIV 310 #define CELLOFFSET 311 #define YYERRCODE 256 short yylhs[] = { -1, 0, 0, 0, 0, 0, 9, 9, 13, 13, 11, 11, 16, 16, 10, 10, 19, 19, 17, 17, 14, 14, 15, 15, 28, 28, 29, 29, 29, 29, 29, 29, 20, 20, 37, 37, 39, 39, 21, 21, 47, 47, 48, 40, 18, 18, 18, 18, 22, 23, 23, 36, 46, 24, 62, 62, 38, 38, 64, 25, 25, 32, 33, 7, 65, 65, 8, 31, 35, 30, 66, 66, 2, 2, 2, 2, 3, 3, 34, 26, 4, 5, 51, 54, 55, 56, 56, 59, 61, 41, 67, 68, 68, 69, 42, 44, 44, 43, 43, 70, 70, 49, 50, 50, 71, 71, 71, 45, 45, 27, 27, 75, 75, 77, 77, 76, 76, 76, 76, 78, 78, 78, 72, 72, 82, 83, 73, 84, 74, 87, 85, 85, 88, 79, 79, 80, 80, 89, 89, 81, 81, 90, 90, 12, 12, 91, 91, 86, 53, 53, 53, 52, 52, 58, 58, 6, 57, 57, 92, 92, 60, 60, 63, 63, 1, 1, 1, }; short yylen[] = { 2, 2, 3, 2, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 4, 5, 1, 2, 1, 1, 1, 1, 1, 1, 2, 3, 1, 3, 5, 4, 2, 3, 1, 3, 5, 2, 6, 5, 5, 4, 4, 4, 3, 4, 4, 3, 13, 14, 8, 14, 1, 0, 8, 2, 3, 1, 1, 2, 1, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 4, 5, 2, 3, 3, 4, 4, 2, 2, 1, 2, 2, 2, 0, 2, 3, 2, 1, 2, 4, 1, 2, 1, 1, 1, 1, 2, 0, 1, 1, 2, 1, 2, 1, 2, 2, 3, 1, 2, 2, 1, 2, 1, 1, 3, 2, 3, 2, 1, 2, 5, 9, 7, 1, 2, 7, 5, 1, 2, 7, 5, 1, 2, 9, 7, 3, 0, 2, 3, 0, 3, 0, 3, 1, 1, 2, 2, 2, 1, 2, 1, 2, 1, 1, 1, }; short yydefred[] = { 0, 0, 0, 0, 0, 8, 0, 165, 164, 166, 0, 0, 0, 0, 0, 0, 3, 0, 0, 12, 14, 16, 17, 0, 0, 0, 0, 143, 0, 0, 0, 9, 20, 0, 0, 67, 0, 0, 78, 0, 0, 0, 0, 0, 24, 26, 27, 28, 29, 30, 31, 53, 0, 0, 0, 0, 0, 2, 15, 144, 0, 0, 13, 18, 0, 58, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 21, 160, 0, 0, 0, 72, 73, 74, 75, 0, 63, 0, 68, 61, 70, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 19, 0, 0, 156, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 161, 0, 0, 0, 162, 0, 0, 66, 64, 0, 71, 0, 0, 124, 22, 0, 111, 0, 0, 0, 51, 0, 82, 0, 52, 86, 85, 158, 159, 0, 0, 157, 43, 35, 94, 0, 0, 0, 0, 0, 93, 92, 0, 0, 41, 96, 0, 0, 0, 0, 88, 87, 49, 0, 0, 163, 0, 65, 0, 0, 112, 0, 0, 0, 0, 135, 139, 0, 113, 0, 23, 83, 0, 0, 48, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 0, 80, 0, 0, 76, 77, 0, 0, 0, 0, 0, 136, 140, 125, 114, 118, 0, 0, 0, 0, 155, 154, 0, 100, 0, 0, 0, 101, 0, 0, 0, 102, 104, 105, 106, 0, 0, 152, 0, 150, 108, 0, 0, 0, 0, 0, 0, 0, 0, 146, 0, 0, 0, 127, 129, 103, 0, 0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 131, 128, 81, 0, 0, 60, 0, 0, 0, 138, 0, 142, 0, 145, 56, 0, 0, 0, 0, 0, 79, 134, 0, 0, 0, 0, 0, 147, 0, 0, 0, 137, 141, 0, 132, 0, 0, 133, 0, 0, 0, 0, 0, 0, 0, 54, 0, 57, 55, }; short yydgoto[] = { 2, 222, 91, 227, 223, 299, 242, 93, 141, 3, 15, 16, 17, 4, 30, 5, 18, 61, 19, 20, 21, 22, 63, 32, 6, 42, 99, 147, 43, 44, 45, 46, 47, 48, 49, 50, 23, 67, 68, 69, 114, 70, 117, 170, 128, 219, 24, 75, 76, 125, 251, 25, 180, 182, 26, 79, 64, 110, 163, 33, 84, 34, 86, 138, 71, 142, 97, 72, 121, 122, 210, 252, 220, 254, 255, 148, 149, 200, 201, 221, 196, 197, 151, 236, 256, 278, 295, 257, 279, 198, 199, 27, 111, }; short yysindex[] = { -241, -236, 0, -170, -235, 0, -103, 0, 0, 0, -236, -236, -55, -182, -236, -200, 0, -254, -107, 0, 0, 0, 0, -240, -240, -159, -168, 0, -95, -89, -255, 0, 0, -236, -138, 0, -68, -81, 0, -77, -236, -73, -66, -103, 0, 0, 0, 0, 0, 0, 0, 0, -86, -236, -79, -236, -74, 0, 0, 0, -236, -85, 0, 0, -236, 0, -44, -67, -159, 0, -60, -180, -40, -159, -50, -67, 0, -72, -236, -66, -65, -63, 0, 0, -124, -83, -236, 0, 0, 0, 0, -37, 0, -35, 0, 0, 0, -33, -32, -108, -66, 0, -236, -59, -236, -78, -236, -126, 0, -64, -229, 0, 0, -236, -159, -67, -31, -213, -29, -26, -24, -40, 0, -67, -25, -60, -159, -22, -62, 0, -57, -236, -236, 0, -213, -43, -18, 0, -236, -42, 0, 0, -35, 0, -23, -46, 0, 0, -108, 0, -228, -56, -108, 0, -14, 0, -236, 0, 0, 0, 0, 0, -53, -57, 0, 0, 0, 0, -48, -12, -72, -28, -27, 0, 0, -21, -213, 0, 0, -52, -57, -13, -56, 0, 0, 0, -236, -19, 0, -54, 0, -4, -236, 0, -30, -17, -16, -51, 0, 0, -201, 0, -228, 0, 0, -250, -236, 0, -12, 0, -3, -56, -236, -236, -2, -140, -236, -56, 5, -56, 0, -16, 0, 6, -236, 0, 0, -15, -11, -47, -236, -236, 0, 0, 0, 0, 0, -16, -51, 11, 13, 0, 0, -3, 0, -56, 14, 15, 0, 16, 17, -140, 0, 0, 0, 0, -36, -36, 0, -56, 0, 0, -16, 9, 21, -6, 22, -236, -233, -217, 0, 24, 38, 46, 0, 0, 0, 7, -139, 0, -139, -236, 48, 30, 65, -197, 58, 97, 101, 103, 107, -236, -236, -236, 109, 0, 0, 0, 0, 123, -236, 0, 132, 143, 146, 0, 153, 0, 159, 0, 0, 161, -38, 170, 130, 179, 0, 0, 190, 195, 198, 177, -236, 0, -236, 180, 204, 0, 0, -236, 0, 210, -236, 0, 213, 193, 217, 199, -236, 200, -236, 0, -236, 0, 0, }; short yyrindex[] = { 0, 0, 0, 282, 8, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 440, 0, 481, 482, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 0, 0, 0, 0, 0, 0, 0, 484, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 124, 0, 171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -144, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 142, 0, 0, 0, 0, 0, 169, 0, 152, 0, 0, 0, 0, 183, 0, 91, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, -110, 0, 0, 0, 0, 0, 114, 0, 47, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 84, 0, 0, 0, 0, -189, 0, 0, 0, 0, 0, 0, 0, 3, 66, 0, 0, 0, 0, 0, 41, 156, 80, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -158, -151, 0, 0, 0, 0, 25, 0, 148, 0, 0, 0, 0, 0, 151, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; short yygindex[] = { 0, -1, 0, 0, -207, -243, 269, 0, 344, 0, 0, 473, 0, 0, 0, 485, 0, 0, 472, 476, 0, 0, 431, 463, 0, 451, 10, 343, 0, 453, 0, 0, 0, 0, 0, 0, 0, 429, 474, 385, -61, 2, -69, -118, 330, -58, 0, 428, 376, 0, 0, 0, 0, -20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 382, 296, 254, -173, 0, 0, 0, 358, 0, 307, -87, -100, 306, 0, 0, 0, 252, 230, 0, -186, -194, -164, 494, 402, }; #define YYTABLESIZE 512 short yytable[] = { 10, 148, 232, 98, 50, 246, 247, 239, 6, 51, 52, 54, 150, 56, 126, 134, 185, 264, 28, 153, 65, 7, 8, 9, 286, 97, 74, 77, 7, 8, 9, 1, 83, 233, 240, 66, 47, 1, 28, 95, 288, 45, 253, 232, 168, 13, 261, 115, 310, 311, 194, 287, 103, 29, 105, 95, 176, 315, 215, 107, 303, 150, 126, 109, 202, 150, 37, 289, 232, 32, 116, 162, 261, 29, 233, 74, 234, 129, 253, 169, 46, 11, 195, 133, 117, 137, 261, 304, 119, 130, 118, 148, 296, 12, 296, 341, 145, 343, 109, 344, 44, 153, 237, 155, 55, 157, 14, 119, 119, 109, 152, 11, 165, 202, 110, 7, 66, 331, 122, 120, 69, 262, 334, 12, 38, 336, 121, 78, 74, 13, 183, 184, 69, 7, 8, 9, 14, 188, 69, 120, 249, 69, 33, 207, 69, 123, 121, 69, 36, 85, 116, 42, 39, 245, 62, 205, 149, 145, 277, 259, 217, 250, 80, 158, 294, 69, 62, 69, 81, 89, 159, 95, 62, 35, 135, 62, 92, 136, 62, 36, 94, 62, 37, 151, 96, 38, 12, 60, 39, 145, 146, 229, 87, 88, 89, 90, 160, 161, 98, 62, 102, 62, 53, 8, 9, 241, 40, 104, 41, 60, 225, 226, 106, 112, 116, 241, 113, 120, 124, 127, 139, 131, 140, 132, 143, 144, 167, 156, 171, 268, 269, 172, 154, 173, 175, 178, 186, 189, 179, 187, 192, 145, 191, 204, 208, 209, 218, 181, 214, 206, 216, 212, 213, 228, 244, 266, 230, 248, 267, 195, 224, 277, 194, 263, 260, 283, 285, 322, 270, 231, 271, 272, 273, 274, 275, 265, 98, 50, 282, 284, 298, 290, 5, 98, 98, 50, 98, 301, 281, 6, 298, 298, 312, 293, 98, 148, 98, 50, 97, 298, 98, 6, 98, 50, 98, 97, 97, 6, 97, 98, 50, 98, 50, 153, 6, 305, 97, 291, 97, 115, 115, 330, 97, 153, 97, 292, 97, 300, 115, 47, 47, 97, 302, 97, 45, 45, 95, 298, 95, 298, 115, 298, 116, 116, 115, 115, 115, 37, 95, 37, 32, 116, 95, 115, 306, 115, 117, 117, 307, 37, 308, 95, 32, 116, 309, 117, 313, 116, 116, 116, 109, 109, 37, 46, 46, 32, 116, 117, 116, 109, 314, 117, 117, 117, 148, 148, 110, 110, 148, 316, 117, 109, 117, 44, 44, 110, 7, 109, 122, 122, 317, 122, 59, 318, 109, 38, 109, 110, 7, 324, 319, 122, 122, 110, 7, 122, 320, 38, 321, 122, 110, 7, 110, 33, 122, 123, 123, 323, 123, 36, 38, 36, 42, 39, 42, 33, 325, 89, 123, 123, 1, 36, 123, 89, 42, 39, 123, 326, 33, 149, 149, 123, 327, 149, 36, 328, 329, 42, 39, 332, 89, 333, 89, 89, 95, 95, 89, 335, 95, 89, 337, 95, 338, 89, 339, 95, 151, 151, 340, 342, 151, 4, 10, 165, 11, 258, 190, 151, 57, 31, 62, 58, 108, 82, 100, 203, 101, 115, 73, 166, 211, 123, 177, 174, 243, 276, 193, 235, 238, 280, 297, 59, 164, }; short yycheck[] = { 1, 0, 196, 0, 0, 212, 213, 257, 0, 10, 11, 12, 99, 14, 75, 84, 134, 224, 273, 0, 260, 257, 258, 259, 257, 0, 24, 25, 257, 258, 259, 272, 33, 197, 284, 275, 0, 272, 273, 40, 257, 0, 215, 237, 257, 299, 219, 0, 291, 292, 278, 284, 53, 308, 55, 0, 125, 300, 176, 60, 257, 148, 123, 64, 151, 152, 0, 284, 262, 0, 0, 300, 245, 308, 238, 73, 277, 78, 251, 292, 0, 281, 310, 84, 0, 86, 259, 284, 277, 79, 270, 0, 278, 293, 280, 338, 297, 340, 0, 342, 0, 102, 202, 104, 286, 106, 306, 287, 297, 110, 100, 281, 113, 200, 0, 0, 275, 324, 0, 277, 264, 221, 329, 293, 0, 332, 277, 295, 126, 299, 131, 132, 276, 257, 258, 259, 306, 138, 282, 297, 280, 285, 0, 163, 288, 0, 297, 291, 0, 287, 274, 0, 0, 211, 264, 156, 0, 297, 297, 217, 180, 301, 257, 289, 303, 309, 276, 311, 257, 0, 296, 0, 282, 276, 257, 285, 257, 260, 288, 282, 257, 291, 285, 0, 257, 288, 293, 294, 291, 297, 298, 192, 260, 261, 262, 263, 260, 261, 264, 309, 286, 311, 257, 258, 259, 206, 309, 286, 311, 294, 264, 265, 286, 257, 274, 216, 283, 257, 268, 291, 257, 286, 257, 286, 257, 257, 257, 305, 257, 230, 231, 257, 291, 257, 259, 257, 279, 279, 300, 257, 286, 297, 265, 257, 292, 257, 259, 304, 269, 302, 302, 279, 279, 257, 257, 266, 286, 259, 305, 310, 279, 297, 278, 257, 259, 271, 267, 305, 257, 286, 257, 257, 257, 257, 257, 290, 273, 273, 257, 257, 281, 257, 0, 280, 281, 281, 283, 257, 279, 281, 291, 292, 293, 286, 291, 294, 293, 293, 273, 300, 297, 293, 299, 299, 301, 280, 281, 299, 283, 306, 306, 308, 308, 294, 306, 257, 291, 279, 293, 272, 273, 322, 297, 304, 299, 279, 301, 279, 281, 293, 294, 306, 267, 308, 293, 294, 281, 338, 283, 340, 293, 342, 272, 273, 297, 298, 299, 281, 293, 283, 281, 281, 297, 306, 257, 308, 272, 273, 257, 293, 257, 306, 293, 293, 257, 281, 257, 297, 298, 299, 272, 273, 306, 293, 294, 306, 306, 293, 308, 281, 257, 297, 298, 299, 293, 294, 272, 273, 297, 257, 306, 293, 308, 293, 294, 281, 281, 299, 280, 281, 257, 283, 264, 257, 306, 281, 308, 293, 293, 279, 257, 293, 294, 299, 299, 297, 257, 293, 257, 301, 306, 306, 308, 281, 306, 280, 281, 257, 283, 281, 306, 283, 281, 281, 283, 293, 257, 268, 293, 294, 0, 293, 297, 274, 293, 293, 301, 257, 306, 293, 294, 306, 257, 297, 306, 257, 279, 306, 306, 279, 291, 257, 293, 294, 293, 294, 297, 257, 297, 300, 257, 300, 279, 304, 257, 304, 293, 294, 279, 279, 297, 0, 0, 286, 0, 216, 142, 304, 15, 4, 18, 15, 61, 30, 43, 152, 43, 68, 24, 114, 170, 73, 126, 121, 208, 251, 148, 200, 202, 257, 280, 17, 110, }; #define YYFINAL 2 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 311 #if YYDEBUG char *yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"INTEGER","STRING","FLOAT", "FIXED","NONFIXED","RIGIDFIXED","APPROXIMATELY_FIXED","LEFT","RIGHT","BOTTOM", "TOP","ASPLB","ASPUB","AT","BLOCK","CELL","CELLGROUP","CLASS","CORNERS", "ECO_ADDED_CELL","ENDPINGROUP","EQUIV","FROM","GROUP","HARDCELL","INITIALLY", "INSTANCE","LAYER","LEGALBLKCLASS","NAME","NEIGHBORHOOD","NOMIRROR","NOPERMUTE", "OF","ORIENT","ORIENTATIONS","PAD","PADGROUP","PADSIDE","PERMUTE","PIN", "PINGROUP","PORT","RESTRICT","SEQUENCE","SIDE","SIDERESTRICTION","SIDESPACE", "SIGNAL","SOFTCELL","STDCELL","SUPERGROUP","SWAPGROUP","UNEQUIV","CELLOFFSET", }; char *yyrule[] = { "$accept : start_file", "start_file : core macros", "start_file : core macros pads", "start_file : core pads", "start_file : core ports", "start_file : core", "core : corecells", "core : corecells cellgroups", "corecells : stdcell", "corecells : corecells stdcell", "pads : padcells", "pads : padcells padgroups", "padcells : padcell", "padcells : padcells padcell", "macros : macro", "macros : macros macro", "macro : hardcell", "macro : softcell", "padgroups : padgroup", "padgroups : padgroups padgroup", "cellgroups : cellgroup", "cellgroups : cellgroups cellgroup", "stdcell : cellname std_fixed bbox pinlist", "stdcell : cellname optional_list std_fixed bbox pinlist", "optional_list : option", "optional_list : optional_list option", "option : celloffset", "option : eco", "option : swap_group", "option : legal_block_classes", "option : mirror", "option : initial_orient", "hardcell : hardcellname custom_instance_list", "hardcell : hardcellname fixed custom_instance_list", "custom_instance_list : custom_instance", "custom_instance_list : custom_instance_list instance custom_instance", "custom_instance : corners class orient actual_orient hardpins", "custom_instance : corners class orient actual_orient", "softcell : softname soft_instance_list", "softcell : softname fixed soft_instance_list", "soft_instance_list : soft_instance", "soft_instance_list : soft_instance_list instance soft_instance", "soft_instance : corners aspect class orient softpins", "instance : INSTANCE string", "padcell : padname corners actual_orient restriction_pad sidespace hardpins", "padcell : padname corners actual_orient restriction_pad sidespace", "padcell : padname_std padside bbox sidespace hardpins", "padcell : padname_std padside bbox sidespace", "padgroup : padgroupname padgrouplist restriction_pdgrp sidespace", "cellgroup : supergroupname supergrouplist class orient", "cellgroup : cellgroupname neighborhood cellgrouplist", "hardcellname : HARDCELL string NAME string", "softname : SOFTCELL string NAME string", "cellname : CELL string string", "neighborhood : NEIGHBORHOOD INTEGER FROM xloc INTEGER FROM yloc INTEGER FROM xloc INTEGER FROM yloc", "neighborhood : NEIGHBORHOOD FIXED INTEGER FROM xloc INTEGER FROM yloc INTEGER FROM xloc INTEGER FROM yloc", "fixed : fixedcontext AT INTEGER FROM xloc INTEGER FROM yloc", "fixed : fixedcontext NEIGHBORHOOD INTEGER FROM xloc INTEGER FROM yloc INTEGER FROM xloc INTEGER FROM yloc", "fixedcontext : FIXED", "std_fixed :", "std_fixed : INITIALLY fixed_type INTEGER FROM fixed_loc OF BLOCK INTEGER", "swap_group : SWAPGROUP string", "legal_block_classes : LEGALBLKCLASS num_block_classes block_classes", "num_block_classes : INTEGER", "block_classes : block_class", "block_classes : block_classes block_class", "block_class : INTEGER", "eco : ECO_ADDED_CELL", "initial_orient : ORIENT INTEGER", "celloffset : CELLOFFSET offset_list", "offset_list : INTEGER", "offset_list : offset_list INTEGER", "fixed_type : FIXED", "fixed_type : NONFIXED", "fixed_type : RIGIDFIXED", "fixed_type : APPROXIMATELY_FIXED", "fixed_loc : LEFT", "fixed_loc : RIGHT", "mirror : NOMIRROR", "bbox : LEFT INTEGER RIGHT INTEGER BOTTOM INTEGER TOP INTEGER", "xloc : string", "yloc : string", "padname : PAD string NAME string", "padname_std : PAD INTEGER string ORIENT INTEGER", "padside : PADSIDE string", "padgroupname : PADGROUP string PERMUTE", "padgroupname : PADGROUP string NOPERMUTE", "supergroupname : SUPERGROUP INTEGER NAME string", "cellgroupname : CELLGROUP INTEGER NAME string", "corners : num_corners cornerpts", "num_corners : CORNERS INTEGER", "cornerpts : cornerpt", "cornerpts : cornerpts cornerpt", "cornerpt : INTEGER INTEGER", "class : CLASS INTEGER", "actual_orient :", "actual_orient : ORIENT INTEGER", "orient : INTEGER ORIENTATIONS orientlist", "orient : ORIENTATIONS orientlist", "orientlist : INTEGER", "orientlist : orientlist INTEGER", "aspect : ASPLB FLOAT ASPUB FLOAT", "softpins : softtype", "softpins : softpins softtype", "softtype : pintype", "softtype : pingrouptype", "softtype : sequencetype", "hardpins : pintype", "hardpins : hardpins pintype", "pinlist :", "pinlist : stdgrppins", "stdgrppins : std_grppintype", "stdgrppins : stdgrppins std_grppintype", "stdpins : std_pintype", "stdpins : stdpins std_pintype", "std_grppintype : pinrecord", "std_grppintype : pinrecord equiv_list", "std_grppintype : pinrecord unequiv_list", "std_grppintype : pingroup stdpins endpingroup", "std_pintype : pinrecord", "std_pintype : pinrecord equiv_list", "std_pintype : pinrecord unequiv_list", "pintype : pinrecord", "pintype : pinrecord equiv_list", "pingroup : PINGROUP", "endpingroup : ENDPINGROUP", "pingrouptype : pingroupident softpinlist siderestriction", "pingroupident : GROUP INTEGER", "sequencetype : seqident softpinlist siderestriction", "seqident : SEQUENCE INTEGER", "softpinlist : softpinrecord", "softpinlist : softpinlist softpinrecord", "softpinrecord : PIN NAME string SIGNAL string", "pinrecord : PIN NAME string SIGNAL string LAYER INTEGER INTEGER INTEGER", "pinrecord : PIN NAME string SIGNAL string INTEGER INTEGER", "equiv_list : equiv", "equiv_list : equiv_list equiv", "equiv : EQUIV NAME string LAYER INTEGER INTEGER INTEGER", "equiv : EQUIV NAME string INTEGER INTEGER", "unequiv_list : unequiv", "unequiv_list : unequiv_list unequiv", "unequiv : UNEQUIV NAME string LAYER INTEGER INTEGER INTEGER", "unequiv : UNEQUIV NAME string INTEGER INTEGER", "ports : port", "ports : ports port", "port : PORT NAME string SIGNAL string LAYER INTEGER INTEGER INTEGER", "port : PORT NAME string SIGNAL string INTEGER INTEGER", "siderestriction : SIDERESTRICTION INTEGER INTEGER", "sidespace :", "sidespace : SIDESPACE FLOAT", "sidespace : SIDESPACE FLOAT FLOAT", "restriction_pad :", "restriction_pad : RESTRICT SIDE sideplace", "restriction_pdgrp :", "restriction_pdgrp : RESTRICT SIDE sideplace", "sideplace : string", "padgrouplist : padset", "padgrouplist : padgrouplist padset", "padset : string FIXED", "padset : string NONFIXED", "supergrouplist : string", "supergrouplist : supergrouplist string", "cellgrouplist : string", "cellgrouplist : cellgrouplist string", "string : STRING", "string : INTEGER", "string : FLOAT", }; #endif #define yyclearin (yychar=(-1)) #define yyerrok (yyerrflag=0) #ifdef YYSTACKSIZE #ifndef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #endif #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 500 #define YYMAXDEPTH 500 #endif #endif int yydebug; int yynerrs; int yyerrflag; int yychar; short *yyssp; YYSTYPE *yyvsp; YYSTYPE yyval; YYSTYPE yylval; short yyss[YYSTACKSIZE]; YYSTYPE yyvs[YYSTACKSIZE]; #define yystacksize YYSTACKSIZE #include "readcell_l.h" /* add readcell_l.h for debug purposes */ /* ********************* #include "readcell_l.h" *******************/ /* ********************* #include "readcell_l.h" *******************/ readcell( fp ) FILE *fp ; { #ifdef YYDEBUG extern int yydebug ; yydebug = FALSE ; D( "twsc/readcell", yydebug = TRUE ; ) ; #endif yyin = fp ; line_countS = 0 ; initialize_parser() ; yyparse(); cleanup_readcells(); } /* end readcell */ yyerror(s) char *s; { if( rowsG > 0 ){ sprintf(YmsgG,"problem reading %s.scel:", cktNameG ); } else { sprintf(YmsgG,"problem reading %s.cel:", cktNameG ); } M( ERRMSG, "yacc", YmsgG ) ; sprintf(YmsgG, " line %d near '%s' : %s\n" , line_countS+1, yytext, s ); M( ERRMSG,NULL, YmsgG ) ; set_error_flag() ; } /* end yyerror */ yywrap() { return(1); } #define YYABORT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int yyparse() { register int yym, yyn, yystate; #if YYDEBUG register char *yys; extern char *getenv(); if (yys = getenv("YYDEBUG")) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = (-1); yyssp = yyss; yyvsp = yyvs; *yyssp = yystate = 0; yyloop: if (yyn = yydefred[yystate]) goto yyreduce; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, shifting to state %d\n", yystate, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; #ifdef lint goto yynewerror; #endif yynewerror: #if YYDEBUG { int test_state, i, expect, two_or_more ; char err_msg[BUFSIZ] ; if( yyname[yychar] ){ sprintf( err_msg, "\nsyntax error - found:%s expected:", yyname[yychar] ) ; two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = YYERRCODE+1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if( expect <= YYTABLESIZE && yycheck[expect] == i ){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = YYERRCODE+1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if( expect <= YYTABLESIZE && yycheck[expect] == i ){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } strcat( err_msg, "\n" ) ; yyerror( err_msg ) ; } else { yyerror("syntax error"); } } #else yyerror("syntax error"); #endif #ifdef lint goto yyerrlab; #endif yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, error recovery shifting\ to state %d\n", *yyssp, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("yydebug: error recovery discarding state %d\n", *yyssp); #endif if (yyssp <= yyss) goto yyabort; --yyssp; --yyvsp; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, error recovery discards token %d (%s)\n", yystate, yychar, yys); } #endif yychar = (-1); goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("yydebug: state %d, reducing by rule %d (%s)\n", yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; yyval = yyvsp[1-yym]; switch (yyn) { case 6: { add_extra_cells() ; } break; case 7: { add_extra_cells() ; } break; case 37: { sprintf( YmsgG, "hardcell at line %d does not have any pins\n", line_countS+1 ) ; M(WARNMSG,"readcells",YmsgG ) ; } break; case 43: { Ysafe_free( yyvsp[0].string ) ; } break; case 48: { end_padgroup() ; } break; case 51: { addCell( yyvsp[0].string, HARDCELLTYPE ) ; } break; case 52: { not_supported("softcells") ; Ysafe_free( yyvsp[0].string ) ; } break; case 53: { addCell( yyvsp[0].string, STDCELLTYPE ) ; } break; case 60: { fix_placement( yyvsp[-6].string, yyvsp[-5].ival, yyvsp[-3].string, yyvsp[0].ival ) ; } break; case 61: { add_swap_group( yyvsp[0].string ) ; } break; case 66: { add_legal_blocks( yyvsp[0].ival ) ; } break; case 67: { add_eco() ; } break; case 68: { add_initial_orient( yyvsp[0].ival ) ; } break; case 72: { yyval.string = Ystrclone( "fixed" ) ; } break; case 73: { yyval.string = Ystrclone( "nonfixed" ) ; } break; case 74: { yyval.string = Ystrclone( "rigidly_fixed" ) ; } break; case 75: { yyval.string = Ystrclone( "approximately_fixed" ) ; } break; case 76: { yyval.string = Ystrclone( "left" ) ; } break; case 77: { yyval.string = Ystrclone( "right" ) ; } break; case 78: { set_mirror_flag(); } break; case 79: { add_tile( yyvsp[-6].ival, yyvsp[-2].ival, yyvsp[-4].ival, yyvsp[0].ival ) ; } break; case 80: { yyval.string = yyvsp[0].string; } break; case 81: { yyval.string = yyvsp[0].string; } break; case 82: { addCell( yyvsp[0].string, PADTYPE ) ; } break; case 83: { addCell( yyvsp[-2].string, PADTYPE ) ; add_orient(yyvsp[0].ival); } break; case 84: { add_padside( yyvsp[0].string ) ; set_old_format( yyvsp[0].string ) ; } break; case 85: { addCell( yyvsp[-1].string, PADGROUPTYPE ) ; setPermutation( TRUE ) ; add_tile( 0,0,0,0 ) ; } break; case 86: { addCell( yyvsp[-1].string, PADGROUPTYPE ) ; setPermutation( FALSE ) ; add_tile( 0,0,0,0 ) ; } break; case 87: { Ysafe_free( yyvsp[0].string ) ; } break; case 88: { Ysafe_free( yyvsp[0].string ) ; } break; case 89: { process_corners() ; } break; case 90: { init_corners() ; } break; case 93: { add_corner( yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 96: { add_orient(yyvsp[0].ival); } break; case 124: { add_pingroup(); } break; case 125: { end_pingroup(); } break; case 132: { /* addNet( $5 ) ; */ } break; case 133: { add_pin( yyvsp[-6].string, yyvsp[-4].string, yyvsp[-2].ival, yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 134: { add_pin( yyvsp[-4].string, yyvsp[-2].string, 0, yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 137: { add_equiv( yyvsp[-4].string, yyvsp[-2].ival, yyvsp[-1].ival, yyvsp[0].ival, FALSE ) ; } break; case 138: { add_equiv( yyvsp[-2].string, 0, yyvsp[-1].ival, yyvsp[0].ival, FALSE ) ; } break; case 141: { add_equiv( yyvsp[-4].string, yyvsp[-2].ival, yyvsp[-1].ival, yyvsp[0].ival, TRUE ) ; } break; case 142: { add_equiv( yyvsp[-2].string, 0, yyvsp[-1].ival, yyvsp[0].ival, TRUE ) ; } break; case 145: { add_port( yyvsp[-6].string, yyvsp[-4].string, yyvsp[-2].ival, yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 146: { add_port( yyvsp[-4].string, yyvsp[-2].string, 0, yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 149: { add_sidespace( yyvsp[0].fval, yyvsp[0].fval ); } break; case 150: { add_sidespace( yyvsp[-1].fval, yyvsp[0].fval ); } break; case 155: { add_padside( yyvsp[0].string ) ; } break; case 158: { add2padgroup( yyvsp[-1].string, TRUE ) ; /* fixed */ } break; case 159: { add2padgroup( yyvsp[-1].string, FALSE ) ; /* nonfixed */ } break; case 160: { Ysafe_free( yyvsp[0].string ) ; } break; case 161: { Ysafe_free( yyvsp[0].string ) ; } break; case 162: { Ysafe_free( yyvsp[0].string ) ; } break; case 163: { Ysafe_free( yyvsp[0].string ) ; } break; case 164: { yyval.string = yyvsp[0].string ; } break; case 165: { /* convert integer to string */ /* this allows integers to be used as strings */ sprintf( bufferS,"%d", yyvsp[0].ival ) ; /* now clone string */ yyval.string = Ystrclone( bufferS ) ; } break; case 166: { /* convert float to string */ /* this allows floats to be used as strings */ sprintf( bufferS,"%f", yyvsp[0].fval ) ; /* now clone string */ yyval.string = Ystrclone( bufferS ) ; } break; } yyssp -= yym; yystate = *yyssp; yyvsp -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state 0 to\ state %d\n", YYFINAL); #endif yystate = YYFINAL; *++yyssp = YYFINAL; *++yyvsp = yyval; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state %d \ to state %d\n", *yyssp, yystate); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate; *++yyvsp = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: return (1); yyaccept: return (0); } graywolf-0.1.4+20170307gite1bf319/src/twsc/readcell.h000066400000000000000000000040511305746555600214570ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: readcell.h DESCRIPTION:This file redefines global variable of yacc and lex so that we can have more than one parser in TimberWolfSC. CONTENTS: macro redefinitions for parser in readcell. DATE: Aug 7, 1988 REVISIONS: ----------------------------------------------------------------- */ /* ***************************************************************** static char SccsId[] = "@(#) readcell.h version 4.2 9/7/90" ; ***************************************************************** */ #define yyact READCEL_yyact #define yyback READCEL_yyback #define yybgin READCEL_yybgin #define yychar READCEL_yychar #define yychk READCEL_yychk #define yycrank READCEL_yycrank #define yydebug READCEL_yydebug #define yydef READCEL_yydef #define yyerrflag READCEL_yyerrflag #define yyerror READCEL_yyerror #define yyestate READCEL_yyestate #define yyexca READCEL_yyexca #define yyextra READCEL_yyextra #define yyfnd READCEL_yyfnd #define yyin READCEL_yyin #define yyinput READCEL_yyinput #define yyleng READCEL_yyleng #define yylex READCEL_yylex #define yylineno READCEL_yylineno #define yylook READCEL_yylook #define yylsp READCEL_yylsp #define yylstate READCEL_yylstate #define yylval READCEL_yylval #define yymatch READCEL_yymatch #define yymorfg READCEL_yymorfg #define yynerrs READCEL_yynerrs #define yyolsp READCEL_yyolsp #define yyout READCEL_yyout #define yyoutput READCEL_yyoutput #define yypact READCEL_yypact #define yyparse READCEL_yyparse #define yypgo READCEL_yypgo #define yyprevious READCEL_yyprevious #define yyreds READCEL_yyreds #define yyr1 READCEL_yyr1 #define yyr2 READCEL_yyr2 #define yysbuf READCEL_yysbuf #define yysptr READCEL_yysptr #define yysvec READCEL_yysvec #define yytchar READCEL_yytchar #define yytext READCEL_yytext #define yytoks READCEL_yytoks #define yytop READCEL_yytop #define yyunput READCEL_yyunput #define yyv READCEL_yyv #define yyval READCEL_yyval #define yyvstop READCEL_yyvstop #define yywrap READCEL_yywrap graywolf-0.1.4+20170307gite1bf319/src/twsc/readcell_l.h000066400000000000000000000403711305746555600217770ustar00rootroot00000000000000#ifdef linux # include #else # include "stdio.h" #endif # define U(x) ((x)&0377) # define NLSTATE yyprevious=YYNEWLINE # define BEGIN yybgin = yysvec + 1 + # define INITIAL 0 # define YYLERR yysvec # define YYSTATE (yyestate-yysvec-1) # define YYOPTIM 1 # define YYLMAX 200 # define output(c) putc(c,yyout) # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} # define yymore() (yymorfg=1) # define ECHO fprintf(yyout, "%s",yytext) # define REJECT { nstr = yyreject(); goto yyfussy;} int yyleng; extern char yytext[]; int yymorfg; extern char *yysptr, yysbuf[]; int yytchar; #ifdef linux FILE *yyin = (FILE *)NULL, *yyout = (FILE *)NULL; #else FILE *yyin ={stdin}, *yyout ={stdout}; #endif extern int yylineno; struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops;}; struct yysvf *yyestate; extern struct yysvf yysvec[], *yybgin; /* ----------------------------------------------------------------- FILE: readcell.l DESCRIPTION:rules for lexical analyzer for syntax checker. This lexical analyzer uses a binary search to reduce the size of the f.a. generated by lex. Thanks to Gary Richey who showed me the trick. See chapter 3 of "Introduction to Compiler Construction with UNIX" by Schreiner & Friedman for more details. CONTENTS: lex rules - screen() DATE: Aug 03, 1990 - "@(#) readcell.l (Yale) version 4.7 3/22/91" ; REVISIONS: Dec 7, 1990 - add | for National. Sun Jan 20 21:51:45 PST 1991 - added * for VALID. Mon Jan 21 21:38:48 PST 1991 - added ASCII char set for alphanum. Fri Mar 22 16:21:58 CST 1991 - made letter more general. ----------------------------------------------------------------- */ #undef YYLMAX #define YYLMAX 2000 /* comments may be at most 2000 characters */ #define token(x) x /* makes it look like regular lex */ #define END(v) (v-1 + sizeof(v) / sizeof( v[0] ) ) /* for table lookup */ static screen() ; static check_line_count() ; static INT line_countS = 0 ; # define YYNEWLINE 10 yylex(){ int nstr; extern int yyprevious; while((nstr = yylook()) >= 0) yyfussy: switch(nstr){ case 0: if(yywrap()) return(0); break; case 1: { /* C-style comments over multiple lines */ check_line_count(yytext) ; } break; case 2: { /* convert to an integer */ yylval.ival = atoi( yytext ) ; return (INTEGER); } break; case 3: { /* convert to an float */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 4: { /* convert to an float */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 5: { return( screen() ) ; } break; case 6: { line_countS++;} break; case 7: ; break; case 8: { return( token(yytext[0]) ) ;} break; case -1: break; default: fprintf(yyout,"bad switch yylook %d",nstr); } return(0); } /* end of yylex */ /* reserved word screener */ /* ----------------------------------------------------------------- The following is table of the reserved words - Table must be in alphabetical order for binary search to work properly. ----------------------------------------------------------------- */ static struct rw_table { /* reserved word table */ char *rw_name ; /* pattern */ int rw_yylex ; /* lex token number */ } rwtable[] = { "ECO_added_cell", token(ECO_ADDED_CELL), "approximately_fixed", token(APPROXIMATELY_FIXED), "asplb", token(ASPLB), "aspub", token(ASPUB), "at", token(AT), "block", token(BLOCK), "bottom", token(BOTTOM), "cell", token(CELL), "cell_offset", token(CELLOFFSET), "cellgroup", token(CELLGROUP), "class", token(CLASS), "corners", token(CORNERS), "end_pin_group", token(ENDPINGROUP), "equiv", token(EQUIV), "fixed", token(FIXED), "from", token(FROM), "group", token(GROUP), "hardcell", token(HARDCELL), "initially", token(INITIALLY), "instance", token(INSTANCE), "layer", token(LAYER), "left", token(LEFT), "legal_block_classes", token(LEGALBLKCLASS), "name", token(NAME), "neighborhood", token(NEIGHBORHOOD), "nomirror", token(NOMIRROR), "nonfixed", token(NONFIXED), "nopermute", token(NOPERMUTE), "of", token(OF), "orient", token(ORIENT), "orientations", token(ORIENTATIONS), "pad", token(PAD), "padgroup", token(PADGROUP), "padside", token(PADSIDE), "permute", token(PERMUTE), "pin", token(PIN), "pin_group", token(PINGROUP), "port", token(PORT), "restrict", token(RESTRICT), "right", token(RIGHT), "rigidly_fixed", token(RIGIDFIXED), "sequence", token(SEQUENCE), "side", token(SIDE), "side.restriction", token(SIDERESTRICTION), "sidespace", token(SIDESPACE), "signal", token(SIGNAL), "softcell", token(SOFTCELL), "stdcell", token(STDCELL), "supergroup", token(SUPERGROUP), "swap_group", token(SWAPGROUP), "top", token(TOP), "unequiv", token(UNEQUIV) } ; static int screen() { int c ; struct rw_table *low = rwtable, /* ptr to beginning */ *mid , *high = END(rwtable) ; /* ptr to end */ /* binary search to look thru table to find pattern match */ while( low <= high){ mid = low + (high-low) / 2 ; if( (c = strcmp(mid->rw_name, yytext) ) == STRINGEQ){ return( mid->rw_yylex ) ; /* return token number */ } else if( c < 0 ){ low = mid + 1 ; } else { high = mid - 1 ; } } /* at this point we haven't found a match so we have a string */ /* save the string by making copy */ yylval.string = Ystrclone( yytext ) ; return (STRING); } /* end screen function */ static int check_line_count( s ) char *s ; { if( s ){ if( strlen(s) >= YYLMAX ){ sprintf(YmsgG,"comment beginning at line %d ",line_countS+1 ); M( ERRMSG, "lex", YmsgG ) ; sprintf(YmsgG,"exceeds maximum allowed length:%d chars.\n", YYLMAX ); M( MSG, NULL, YmsgG ) ; } for( ;*s;s++ ){ if( *s == '\n'){ line_countS++; } } } } /* end check_line_count */ int yyvstop[] ={ 0, 7, 0, 7, 0, 8, 0, 7, 8, 0, 6, 0, 5, 8, 0, 5, 8, 0, 3, 5, 8, 0, 5, 8, 0, 2, 8, 0, 7, 0, 5, 0, 3, 5, 0, 2, 5, 0, 5, 0, 3, 5, 0, 2, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 1, 5, 0, 5, 0, 4, 5, 0, 1, 0, 5, 0, 1, 5, 0, 1, 0, 0}; # define YYTYPE unsigned char struct yywork { YYTYPE verify, advance; } yycrank[] ={ 0,0, 0,0, 1,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,4, 1,5, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 1,7, 9,15, 0,0, 1,8, 1,9, 1,10, 7,13, 19,19, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 7,14, 25,33, 26,34, 32,24, 33,25, 34,25, 0,0, 0,0, 0,0, 1,6, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 8,13, 10,16, 0,0, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 10,17, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 14,16, 0,0, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 14,14, 15,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 15,18, 15,18, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 0,0, 0,0, 0,0, 0,0, 18,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 16,22, 15,19, 18,23, 18,18, 20,24, 0,0, 18,18, 18,18, 18,18, 0,0, 15,20, 15,19, 20,24, 20,24, 15,19, 15,21, 15,19, 17,16, 0,0, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 17,17, 18,18, 0,0, 0,0, 16,22, 0,0, 0,0, 0,0, 20,25, 15,19, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 20,26, 20,25, 0,0, 0,0, 20,25, 20,27, 20,25, 22,28, 0,0, 22,28, 0,0, 0,0, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 22,29, 23,24, 0,0, 0,0, 0,0, 0,0, 20,25, 0,0, 24,18, 0,0, 23,30, 23,24, 0,0, 0,0, 23,24, 23,31, 23,24, 24,23, 24,18, 0,0, 0,0, 24,18, 24,32, 24,18, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 28,29, 0,0, 0,0, 0,0, 23,24, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 24,18, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 29,29, 30,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 30,23, 30,18, 0,0, 0,0, 30,18, 30,35, 30,18, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 30,18, 0,0, 0,0, 0,0}; struct yysvf yysvec[] ={ 0, 0, 0, yycrank+-1, 0, yyvstop+1, yycrank+0, yysvec+1, yyvstop+3, yycrank+0, 0, yyvstop+5, yycrank+3, 0, yyvstop+7, yycrank+0, 0, yyvstop+10, yycrank+38, 0, yyvstop+12, yycrank+4, yysvec+6, yyvstop+15, yycrank+117, yysvec+6, yyvstop+18, yycrank+3, yysvec+6, yyvstop+22, yycrank+129, yysvec+6, yyvstop+25, yycrank+0, yysvec+4, yyvstop+28, yycrank+0, yysvec+6, yyvstop+30, yycrank+139, yysvec+6, yyvstop+32, yycrank+151, yysvec+6, yyvstop+35, yycrank+-208, 0, yyvstop+38, yycrank+171, yysvec+6, yyvstop+40, yycrank+211, yysvec+6, yyvstop+43, yycrank+-200, yysvec+15, 0, yycrank+-4, yysvec+15, yyvstop+45, yycrank+-243, 0, yyvstop+47, yycrank+0, yysvec+15, yyvstop+49, yycrank+249, yysvec+6, yyvstop+51, yycrank+-274, yysvec+20, 0, yycrank+-281, yysvec+15, 0, yycrank+-15, yysvec+15, yyvstop+53, yycrank+-16, yysvec+15, yyvstop+55, yycrank+0, yysvec+6, yyvstop+57, yycrank+282, yysvec+6, yyvstop+60, yycrank+303, yysvec+6, yyvstop+62, yycrank+-328, yysvec+15, 0, yycrank+0, 0, yyvstop+65, yycrank+17, 0, 0, yycrank+18, yysvec+6, yyvstop+67, yycrank+19, yysvec+6, yyvstop+69, yycrank+0, yysvec+32, yyvstop+72, 0, 0, 0}; struct yywork *yytop = yycrank+397; struct yysvf *yybgin = yysvec+1; char yymatch[] ={ 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 011 ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'*' ,'+' ,'!' ,'+' ,'.' ,'/' , '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , '0' ,'0' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 0}; char yyextra[] ={ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0}; /* ncform 4.1 83/08/11 */ int yylineno =1; # define YYU(x) x # define NLSTATE yyprevious=YYNEWLINE char yytext[YYLMAX]; struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; char yysbuf[YYLMAX]; char *yysptr = yysbuf; int *yyfnd; extern struct yysvf *yyestate; int yyprevious = YYNEWLINE; yylook(){ register struct yysvf *yystate, **lsp; register struct yywork *yyt; struct yysvf *yyz; int yych; struct yywork *yyr; # ifdef LEXDEBUG int debug; # endif char *yylastch; #ifdef linux if (yyin == (FILE *)NULL) yyin = stdin; if (yyout == (FILE *)NULL) yyout = stdout; #endif /* start off machines */ # ifdef LEXDEBUG debug = 0; # endif if (!yymorfg) yylastch = yytext; else { yymorfg=0; yylastch = yytext+yyleng; } for(;;){ lsp = yylstate; yyestate = yystate = yybgin; if (yyprevious==YYNEWLINE) yystate++; for (;;){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); # endif yyt = yystate->yystoff; if(yyt == yycrank){ /* may not be any transitions */ yyz = yystate->yyother; if(yyz == 0)break; if(yyz->yystoff == yycrank)break; } *yylastch++ = yych = input(); tryagain: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"unsigned char "); allprint(yych); putchar('\n'); } # endif yyr = yyt; if ( (int)yyt > (int)yycrank){ yyt = yyr + yych; if (yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } # ifdef YYOPTIM else if((int)yyt < (int)yycrank) { /* r < yycrank */ yyt = yyr = yycrank+(yycrank-yyt); # ifdef LEXDEBUG if(debug)fprintf(yyout,"compressed state\n"); # endif yyt = yyt + yych; if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } yyt = yyr + YYU(yymatch[yych]); # ifdef LEXDEBUG if(debug){ fprintf(yyout,"try fall back character "); allprint(YYU(yymatch[yych])); putchar('\n'); } # endif if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transition */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); # endif goto tryagain; } # endif else {unput(*--yylastch);break;} contin: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"state %d char ",yystate-yysvec-1); allprint(yych); putchar('\n'); } # endif ; } # ifdef LEXDEBUG if(debug){ fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); allprint(yych); putchar('\n'); } # endif while (lsp-- > yylstate){ *yylastch-- = 0; if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ yyolsp = lsp; if(yyextra[*yyfnd]){ /* must backup */ while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ lsp--; unput(*yylastch--); } } yyprevious = YYU(*yylastch); yylsp = lsp; yyleng = yylastch-yytext+1; yytext[yyleng] = 0; # ifdef LEXDEBUG if(debug){ fprintf(yyout,"\nmatch "); sprint(yytext); fprintf(yyout," action %d\n",*yyfnd); } # endif return(*yyfnd++); } unput(*yylastch); } if (yytext[0] == 0 /* && feof(yyin) */) { yysptr=yysbuf; return(0); } yyprevious = yytext[0] = input(); if (yyprevious>0) output(yyprevious); yylastch=yytext; # ifdef LEXDEBUG if(debug)putchar('\n'); # endif } } yyback(p, m) int *p; { if (p==0) return(0); while (*p) { if (*p++ == m) return(1); } return(0); } /* the following are only used in the lex library */ yyinput(){ #ifdef linux if (yyin == NULL) yyin = stdin; #endif return(input()); } yyoutput(c) int c; { #ifdef linux if (yyout == NULL) yyout = stdout; #endif output(c); } yyunput(c) int c; { unput(c); } graywolf-0.1.4+20170307gite1bf319/src/twsc/readnets.c000066400000000000000000000601561305746555600215140ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ #ifndef lint static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley) 01/20/90"; #endif #define YYBYACC 1 /* ----------------------------------------------------------------- FILE: readnets.c <- readnets_yacc <- readnets_lex DESCRIPTION:This file contains the grammar (BNF) for the TimberWolfMC input file parser for nets. The rules for lex are in readnets_lex. The grammar for yacc is in readnets_yacc. The output of yacc (y.tab.c) is renamed to readnets.c CONTENTS: readnets( fp ) FILE *fp ; yyerror(s) char *s; yywrap() Note:readnets.c will also include the yacc parser. DATE: Aug 7, 1988 REVISIONS: Jan 29, 1989 - changed to msgG and added \n's. Mar 01, 1989 - modified argument to YexitPgm. Mar 11, 1989 - added get_total_paths for new print_paths. Mar 16, 1989 - changed data structure of netlist. Thu Dec 20 00:16:51 EST 1990 - added check_nets to make sure constraints are consistent. Sun Jan 20 21:47:52 PST 1991 - ported to AIX. Thu Mar 14 16:39:01 CST 1991 - fixed crash in bad_nets. Thu Apr 18 01:55:39 EDT 1991 - added debug function and fixed for new library names. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) readnets.y (Yale) version 4.12 4/21/91" ; #endif #endif #include #include #include #include "readnets.h" /* redefine yacc and lex globals */ #include "standard.h" #include "main.h" #undef REJECT /* undefine TimberWolfSC definition */ #define STARTPATH 1 /* flag for start of path */ #define CONTPATH 0 /* flag for continuing path */ #ifdef DEBUG #define YYDEBUG 1 /* condition compile for yacc debug */ #endif /* DEBUG */ static INT line_countS ; static INT netS ; /* current net being processed */ static char bufferS[LRECL] ; static BOOL abortFlagS = FALSE ; static INT total_num_pathS = 0 ; static GLISTPTR netPtrS ; static YHASHPTR net_hash_tableS ; static PATHPTR pathPtrS = NULL ; /* start of path list */ static PATHPTR curPathS ; /* current bottom of path list so list */ /* is in order given by user debug easier */ typedef union { INT ival ; char *string ; double fval ; } YYSTYPE; #define INTEGER 257 #define STRING 258 #define FLOAT 259 #define ALLNETS 260 #define COLON 261 #define HVWEIGHTS 262 #define PATH 263 #define IGNORE 264 #define DONTGLOBALROUTE 265 #define NET 266 #define YYERRCODE 256 short yylhs[] = { -1, 0, 0, 2, 2, 3, 3, 6, 6, 7, 7, 5, 4, 4, 8, 9, 9, 1, 1, 1, }; short yylen[] = { 2, 0, 1, 1, 2, 1, 2, 1, 2, 1, 1, 2, 5, 4, 2, 1, 2, 1, 1, 1, }; short yydefred[] = { 0, 0, 0, 0, 0, 3, 5, 0, 0, 18, 17, 19, 15, 0, 11, 4, 9, 10, 0, 7, 0, 16, 8, 0, 0, 12, }; short yydgoto[] = { 3, 12, 4, 5, 6, 7, 18, 19, 8, 13, }; short yysindex[] = { -263, -253, -249, 0, -263, 0, 0, -257, -251, 0, 0, 0, 0, -253, 0, 0, 0, 0, -257, 0, -246, 0, 0, -245, -244, 0, }; short yyrindex[] = { 14, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, -243, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, }; short yygindex[] = { 0, 3, 0, 13, 0, 0, 0, 4, 0, 0, }; #define YYTABLESIZE 268 short yytable[] = { 1, 6, 13, 2, 9, 10, 11, 16, 17, 14, 20, 23, 24, 25, 1, 2, 21, 15, 14, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 13, 0, 6, 13, }; short yycheck[] = { 263, 0, 0, 266, 257, 258, 259, 264, 265, 258, 261, 257, 257, 257, 0, 0, 13, 4, 261, -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 263, 263, -1, 266, 266, }; #define YYFINAL 3 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 266 #if YYDEBUG char *yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"INTEGER","STRING","FLOAT", "ALLNETS","COLON","HVWEIGHTS","PATH","IGNORE","DONTGLOBALROUTE","NET", }; char *yyrule[] = { "$accept : start_nets", "start_nets :", "start_nets : list_of_paths_n_nets", "list_of_paths_n_nets : path_or_net", "list_of_paths_n_nets : list_of_paths_n_nets path_or_net", "path_or_net : single_path", "path_or_net : net_record net_options", "net_options : list_of_options", "net_options : net_options list_of_options", "list_of_options : IGNORE", "list_of_options : DONTGLOBALROUTE", "net_record : NET STRING", "single_path : pathlist COLON INTEGER INTEGER INTEGER", "single_path : pathlist COLON INTEGER INTEGER", "pathlist : PATH netlist", "netlist : string", "netlist : netlist string", "string : STRING", "string : INTEGER", "string : FLOAT", }; #endif #define yyclearin (yychar=(-1)) #define yyerrok (yyerrflag=0) #ifdef YYSTACKSIZE #ifndef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #endif #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 500 #define YYMAXDEPTH 500 #endif #endif int yydebug; int yynerrs; int yyerrflag; int yychar; short *yyssp; YYSTYPE *yyvsp; YYSTYPE yyval; YYSTYPE yylval; short yyss[YYSTACKSIZE]; YYSTYPE yyvs[YYSTACKSIZE]; #define yystacksize YYSTACKSIZE #include "readnets_l.h" /* add readnets_l.h for debug purposes */ /* ********************* #include "readnets_l.h" *******************/ /* ********************* #include "readnets_l.h" *******************/ static free_net_data(); static bad_net(); char *Ystrclone(); readnets( fp ) FILE *fp ; { /* static free_net_data() ; */ YHASHPTR get_net_table() ; #ifdef YYDEBUG extern int yydebug ; yydebug = FALSE ; D( "twsc/readnets", yydebug = TRUE ; ) ; #endif yyin = fp ; yyout = stdout ; line_countS = 0 ; numpathsG = 0 ; net_hash_tableS = get_net_table() ; /* parse input file using yacc */ if( fp ) { yyparse(); } check_paths() ; if( abortFlagS ){ YexitPgm( PGMFAIL ) ; } build_path_array() ; init_path_set() ; init_net_set() ; add_paths_to_cells() ; /* free hash table */ Yhash_table_delete( net_hash_tableS , free_net_data ) ; } /* end readnets */ static free_net_data( data ) INT *data ; { Ysafe_free( data ) ; } /* free_swap_data */ process_net_rec( netname ) char *netname ; { INT *data ; if(!(data = (INT *) Yhash_search( net_hash_tableS, netname, NULL, FIND ))){ bad_net( netname, FALSE ) ; /* not fatal */ netS = 0 ; } else { netS = *data ; } } /* end process_net_rec */ ignore_net() { if( netS ){ netarrayG[netS]->ignore = 1 ; } } /* end ignore_net */ ignore_route() { if( netS ){ netarrayG[netS]->ignore = -1 ; } } /* end ignore_route */ yyerror(s) char *s; { sprintf(YmsgG,"problem reading %s.net:", cktNameG ); M( ERRMSG, "yacc", YmsgG ) ; sprintf(YmsgG, " line %d near '%s' : %s\n" , line_countS+1, yytext, s ); M( ERRMSG,NULL, YmsgG ) ; Ymessage_error_count() ; abortFlagS = TRUE ; } yywrap() { return(1); } add_path( pathFlag, net ) BOOL pathFlag ; char *net ; { INT *data ; GLISTPTR tempNetPtr ; if( pathFlag == STARTPATH ){ /* see if pathptr exists */ if( pathPtrS ){ curPathS->next = (PATHPTR) Ysafe_malloc( sizeof(PATHBOX) ) ; curPathS = curPathS->next ; } else { /* first path - start list */ curPathS = pathPtrS = (PATHPTR) Ysafe_malloc( sizeof(PATHBOX) ) ; } curPathS->next = NULL ; netPtrS = curPathS->nets = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; netPtrS->next = NULL ; } else { /* continuing a path */ tempNetPtr = netPtrS ; ASSERT( netPtrS, "add_path", "net pointer should be non-NULL" ) ; netPtrS = curPathS->nets = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; netPtrS->next = tempNetPtr ; } if( data = (INT *) Yhash_search( net_hash_tableS , net, NULL, FIND)){ /* get data from field */ netPtrS->p.net = *data ; } else { bad_net( net, TRUE ) ; /* Fatal abort */ } /* string bufferS is allocated in lex */ if( net ){ Ysafe_free( net ) ; } } /* end add_path */ end_path(lower_bound, upper_bound, priority ) INT lower_bound, upper_bound, priority ; { GLISTPTR nets, path_ptr, tempPath ; DBOXPTR dimptr ; INT net_number ; if( abortFlagS ){ return ; } curPathS->lower_bound = lower_bound ; curPathS->upper_bound = upper_bound ; curPathS->priority = priority ; total_num_pathS++ ; /* total number of paths given */ if( priority ){ numpathsG++ ; /* increment number of active paths */ /* add path to path list in netarrayG */ for( nets = curPathS->nets; nets ; nets = nets->next ){ net_number = nets->p.net ; dimptr = netarrayG[net_number] ; if( tempPath = dimptr->paths ){ path_ptr = dimptr->paths = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; path_ptr->next = tempPath ; } else { /* start a new list */ path_ptr = dimptr->paths = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; path_ptr->next = NULL ; } /* use total_num_pathS so we can index patharrayG */ path_ptr->p.path = total_num_pathS ; } } } /* end function end_path */ check_paths() { INT i ; /* counter */ DBOXPTR nptr ; /* traverse the nets */ /* first make sure that the nets in paths are not ignored */ for( i = 1; i <= numnetsG; i++ ){ nptr = netarrayG[i] ; if( nptr->paths && nptr->ignore ){ sprintf( YmsgG, "Net:%s is specified in a path and ignored\n", nptr->name ) ; M( ERRMSG, "check_paths", YmsgG ) ; abortFlagS = TRUE ; } } } /* check_paths */ build_path_array() { INT i ; PATHPTR curPtr ; patharrayG = (PATHPTR *) Ysafe_malloc( (total_num_pathS+1)*sizeof(PATHPTR) ) ; i = 1 ; for( curPtr = pathPtrS; curPtr ; curPtr = curPtr->next ){ patharrayG[i++] = curPtr ; } } /* end build_path_array */ PATHPTR get_path_list() { return( pathPtrS ) ; } /* end get_path_list */ INT get_total_paths() { return( total_num_pathS ) ; } /* end get_total_paths */ add_paths_to_cells() { INT i ; INT net_number ; INT total_cells ; PSETPTR pathlist, enum_path_set() ; CBOXPTR ptr ; GLISTPTR path_ptr, tempPath ; DBOXPTR dimptr ; PINBOXPTR pinptr ; for( i=1;i<=lastpadG; i++ ){ ptr = carrayG[i] ; clear_path_set() ; /* look for the UNIQUE paths that connects to this cell */ for(pinptr=ptr->pins;pinptr;pinptr=pinptr->nextpin){ net_number = pinptr->net ; /* now go to net array */ dimptr = netarrayG[net_number] ; /* look at all paths that use this net */ for( path_ptr=dimptr->paths;path_ptr;path_ptr=path_ptr->next){ add2path_set( path_ptr->p.path ) ; } } /* now add UNIQUE list of paths to this cell */ for( pathlist=enum_path_set(); pathlist; pathlist=pathlist->next){ if( tempPath = ptr->paths ){ path_ptr = ptr->paths = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; path_ptr->next = tempPath ; } else { /* start a new list */ path_ptr = ptr->paths = (GLISTPTR) Ysafe_malloc( sizeof(GLISTBOX) ) ; path_ptr->next = NULL ; } /* copy path to cell list of paths */ path_ptr->p.path = pathlist->path ; } } } static bad_net( net, fatal ) char *net ; BOOL fatal ; { sprintf( YmsgG, "The net named: %s in the .net file ", net ); strcat( YmsgG, "was not encountered\n" ) ; fprintf( fpoG, "%s ", YmsgG ) ; if( fatal ){ M( ERRMSG, "add_path", YmsgG ) ; strcpy( YmsgG,"\twhile reading the .cel file --- FATAL error\n") ; abortFlagS = TRUE ; M( ERRMSG, NULL, YmsgG ) ; } else { M( WARNMSG, "add_path", YmsgG ) ; strcpy( YmsgG, "\twhile reading the .cel file --- net constraint ignored.\n") ; M( WARNMSG, NULL, YmsgG ) ; } fprintf( fpoG, "%s ", YmsgG ) ; } /* end bad_net */ #define YYABORT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int yyparse() { register int yym, yyn, yystate; #if YYDEBUG register char *yys; extern char *getenv(); if (yys = getenv("YYDEBUG")) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = (-1); yyssp = yyss; yyvsp = yyvs; *yyssp = yystate = 0; yyloop: if (yyn = yydefred[yystate]) goto yyreduce; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, shifting to state %d\n", yystate, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; #ifdef lint goto yynewerror; #endif yynewerror: #if YYDEBUG { int test_state, i, expect, two_or_more ; char err_msg[BUFSIZ] ; if( yyname[yychar] ){ sprintf( err_msg, "\nsyntax error - found:%s expected:", yyname[yychar] ) ; two_or_more = 0 ; if( test_state = yysindex[yystate] ){ for( i = YYERRCODE+1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if( expect <= YYTABLESIZE && yycheck[expect] == i ){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } if( test_state = yyrindex[yystate] ){ for( i = YYERRCODE+1; i <= YYMAXTOKEN; i++ ){ expect = test_state + i ; if( expect <= YYTABLESIZE && yycheck[expect] == i ){ if( two_or_more ){ strcat( err_msg, " | " ) ; } else { two_or_more = 1 ; } strcat( err_msg, yyname[i] ) ; } } } strcat( err_msg, "\n" ) ; yyerror( err_msg ) ; } else { yyerror("syntax error"); } } #else yyerror("syntax error"); #endif #ifdef lint goto yyerrlab; #endif yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("yydebug: state %d, error recovery shifting\ to state %d\n", *yyssp, yytable[yyn]); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("yydebug: error recovery discarding state %d\n", *yyssp); #endif if (yyssp <= yyss) goto yyabort; --yyssp; --yyvsp; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, error recovery discards token %d (%s)\n", yystate, yychar, yys); } #endif yychar = (-1); goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("yydebug: state %d, reducing by rule %d (%s)\n", yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; yyval = yyvsp[1-yym]; switch (yyn) { case 9: { ignore_net() ; } break; case 10: { ignore_route() ; } break; case 11: { process_net_rec( yyvsp[0].string ) ; } break; case 12: { /* pathlist COLON lowerBound upperBound priority*/ end_path( yyvsp[-2].ival, yyvsp[-1].ival, yyvsp[0].ival ) ; } break; case 13: { end_path( yyvsp[-1].ival, yyvsp[0].ival, 1 ) ; } break; case 15: { add_path( STARTPATH, yyvsp[0].string ) ; } break; case 16: { add_path( CONTPATH, yyvsp[0].string ) ; } break; case 17: { yyval.string = yyvsp[0].string ; } break; case 18: { /* convert integer to string */ /* this allows integers to be used as strings */ /* a kluge but timberwolf's old parser supported it */ sprintf( bufferS,"%d", yyvsp[0].ival ) ; /* now clone string */ yyval.string = (char *) Ystrclone( bufferS ) ; } break; case 19: { /* convert float to string */ /* this allows floats to be used as strings */ /* a kluge but timberwolf's old parser supported it */ sprintf( bufferS,"%f", yyvsp[0].fval ) ; /* now clone string */ yyval.string = (char *) Ystrclone( bufferS ) ; } break; } yyssp -= yym; yystate = *yyssp; yyvsp -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state 0 to\ state %d\n", YYFINAL); #endif yystate = YYFINAL; *++yyssp = YYFINAL; *++yyvsp = yyval; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("yydebug: state %d, reading %d (%s)\n", YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("yydebug: after reduction, shifting from state %d \ to state %d\n", *yyssp, yystate); #endif if (yyssp >= yyss + yystacksize - 1) { goto yyoverflow; } *++yyssp = yystate; *++yyvsp = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: return (1); yyaccept: return (0); } graywolf-0.1.4+20170307gite1bf319/src/twsc/readnets.h000066400000000000000000000047621305746555600215220ustar00rootroot00000000000000/* ----------------------------------------------------------------- FILE: readnets.h DESCRIPTION:This file redefines global variable of yacc and lex so that we can have more than one parser in TimberWolfMC. CONTENTS: macro redefinitions for parser in readnets. DATE: Oct 19, 1988 REVISIONS: Mar 27, 1989 - added to TimberWolfSC also added PSETBOX def. Thu Mar 7 02:43:49 EST 1991 - added more definitions for byacc. ----------------------------------------------------------------- */ /* ***************************************************************** "@(#) readnets.h (Yale) version 4.4 3/7/91" ***************************************************************** */ typedef struct psetrec { INT member; /* integer for determining membership */ INT path ; /* data */ struct psetrec *next ; } PSETBOX, *PSETPTR ; /* path set record */ #define yyact NET_yyact #define yyback NET_yyback #define yybgin NET_yybgin #define yychar NET_yychar #define yychk NET_yychk #define yycrank NET_yycrank #define yydebug NET_yydebug #define yydef NET_yydef #define yyerrflag NET_yyerrflag #define yyerror NET_yyerror #define yyestate NET_yyestate #define yyexca NET_yyexca #define yyextra NET_yyextra #define yyfnd NET_yyfnd #define yyin NET_yyin #define yyinput NET_yyinput #define yyleng NET_yyleng #define yylex NET_yylex #define yylineno NET_yylineno #define yylook NET_yylook #define yylsp NET_yylsp #define yylstate NET_yylstate #define yylval NET_yylval #define yymatch NET_yymatch #define yymorfg NET_yymorfg #define yynerrs NET_yynerrs #define yyolsp NET_yyolsp #define yyout NET_yyout #define yyoutput NET_yyoutput #define yypact NET_yypact #define yyparse NET_yyparse #define yypgo NET_yypgo #define yyprevious NET_yyprevious #define yyr1 NET_yyr1 #define yyr2 NET_yyr2 #define yysbuf NET_yysbuf #define yysptr NET_yysptr #define yysvec NET_yysvec #define yytchar NET_yytchar #define yytext NET_yytext #define yytop NET_yytop #define yyunput NET_yyunput #define yyv NET_yyv #define yyval NET_yyval #define yyvstop NET_yyvstop #define yywrap NET_yywrap /* for byacc */ #define yyrule NET_yyrule #define yyname NET_yyname #define yytable NET_yytable #define yycheck NET_yycheck #define yydgoto NET_yydgoto #define yydefred NET_yydefred #define yygindex NET_yygindex #define yyrindex NET_yyrindex #define yysindex NET_yysindex #define yylen NET_yylen #define yylhs NET_yylhs graywolf-0.1.4+20170307gite1bf319/src/twsc/readnets_l.h000066400000000000000000000347041305746555600220340ustar00rootroot00000000000000#ifdef linux # include #else # include "stdio.h" #endif # define U(x) ((x)&0377) # define NLSTATE yyprevious=YYNEWLINE # define BEGIN yybgin = yysvec + 1 + # define INITIAL 0 # define YYLERR yysvec # define YYSTATE (yyestate-yysvec-1) # define YYOPTIM 1 # define YYLMAX 200 # define output(c) putc(c,yyout) # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} # define yymore() (yymorfg=1) # define ECHO fprintf(yyout, "%s",yytext) # define REJECT { nstr = yyreject(); goto yyfussy;} int yyleng; extern char yytext[]; int yymorfg; extern char *yysptr, yysbuf[]; int yytchar; #ifdef linux FILE *yyin =NULL, *yyout =NULL; #else FILE *yyin ={stdin}, *yyout ={stdout}; #endif extern int yylineno; struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops;}; struct yysvf *yyestate; extern struct yysvf yysvec[], *yybgin; /* ----------------------------------------------------------------- "@(#) readnets.l (Yale) version 4.6 4/18/91" FILE: readnets_lex DESCRIPTION:rules for lexical analyzer in readnets. This lexical analyzer uses a binary search to reduce the size of the f.a. generated by lex. Thanks to Gary Richey who showed me the trick. See chapter 3 of "Introduction to Compiler Construction with UNIX" by Schreiner & Friedman for more details. CONTENTS: lex rules - screen() DATE: Oct 19, 1988 - original coding REVISIONS: Mar 29, 1989 - added to TimberWolfSC. Oct 11, 1989 - added comments over multiple lines. Nov 5, 1989 - fixed problem with sign - now ? (0 or 1 occurences) instead of * (0 or more). Thu Mar 14 16:20:10 CST 1991 - added all ASCII characters. Fri Mar 22 16:21:58 CST 1991 - made letter more general. ----------------------------------------------------------------- */ #undef YYLMAX #define YYLMAX 2000 /* comments may be at most 2000 characters */ #define token(x) x /* makes it look like regular lex */ #define END(v) (v-1 + sizeof(v) / sizeof( v[0] ) ) /* for table lookup */ static INT screen() ; static INT check_line_count() ; # define YYNEWLINE 10 yylex(){ int nstr; extern int yyprevious; while((nstr = yylook()) >= 0) yyfussy: switch(nstr){ case 0: if(yywrap()) return(0); break; case 1: { /* C-style comments over multiple lines */ check_line_count(yytext) ; } break; case 2: { /* convert to an integer */ yylval.ival = atoi( yytext ) ; return (INTEGER); } break; case 3: { /* convert to an integer */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 4: { /* convert to an integer */ yylval.fval = atof( yytext ) ; return (FLOAT); } break; case 5: { return( COLON ) ; } break; case 6: { return( screen() ) ; } break; case 7: { line_countS++;} break; case 8: ; break; case 9: { return( token(yytext[0]) ) ;} break; case -1: break; default: fprintf(yyout,"bad switch yylook %d",nstr); } return(0); } /* end of yylex */ /* reserved word screener */ /* ----------------------------------------------------------------- The following is table of the reserved words - Table must be in alphabetical order for binary search to work properly. ----------------------------------------------------------------- */ static struct rw_table { /* reserved word table */ char *rw_name ; /* pattern */ INT rw_yylex ; /* lex token number */ } rwtable[] = { "HVweights", token(HVWEIGHTS), "allnets", token(ALLNETS), "do_not_global_route", token(DONTGLOBALROUTE), "ignore", token(IGNORE), "net", token(NET), "path", token(PATH) } ; static INT screen() { INT c ; struct rw_table *low = rwtable, /* ptr to beginning */ *mid , *high = END(rwtable) ; /* ptr to end */ char *Ystrclone() ; /* binary search to look thru table to find pattern match */ while( low <= high){ mid = low + (high-low) / 2 ; if( (c = strcmp(mid->rw_name, yytext) ) == STRINGEQ){ return( mid->rw_yylex ) ; /* return token number */ } else if( c < 0 ){ low = mid + 1 ; } else { high = mid - 1 ; } } /* at this poINT we haven't found a match so we have a string */ /* save the string by making copy */ yylval.string = Ystrclone( yytext ) ; return (STRING); } /* end screen function */ static INT check_line_count( s ) char *s ; { if( s ){ if( strlen(s) >= YYLMAX ){ sprintf(YmsgG,"comment beginning at line %d ",line_countS+1 ); M( ERRMSG, "lex", YmsgG ) ; sprintf(YmsgG,"exceeds maximum allowed length:%d chars.\n", YYLMAX ); M( MSG, NULL, YmsgG ) ; YexitPgm(PGMFAIL) ; } for( ;*s;s++ ){ if( *s == '\n'){ line_countS++; } } } } /* end check_line_count */ int yyvstop[] ={ 0, 8, 0, 8, 0, 9, 0, 8, 9, 0, 7, 0, 6, 9, 0, 6, 9, 0, 6, 9, 0, 2, 9, 0, 5, 6, 9, 0, 8, 0, 6, 0, 2, 6, 0, 6, 0, 3, 6, 0, 2, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6, 0, 1, 6, 0, 6, 0, 4, 6, 0, 1, 0, 6, 0, 1, 6, 0, 1, 0, 0}; # define YYTYPE unsigned char struct yywork { YYTYPE verify, advance; } yycrank[] ={ 0,0, 0,0, 1,3, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,4, 1,5, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 4,11, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,6, 1,7, 8,14, 0,0, 1,6, 1,8, 1,9, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 1,10, 7,13, 7,13, 7,13, 7,13, 7,13, 7,13, 7,13, 7,13, 7,13, 7,13, 1,6, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 6,12, 9,15, 18,18, 9,16, 9,16, 9,16, 9,16, 9,16, 9,16, 9,16, 9,16, 9,16, 9,16, 13,15, 24,32, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 13,13, 14,17, 25,33, 31,23, 32,24, 33,24, 0,0, 0,0, 0,0, 14,17, 14,17, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 15,15, 0,0, 0,0, 0,0, 0,0, 17,17, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 15,21, 14,18, 17,22, 17,17, 0,0, 0,0, 17,17, 17,17, 17,17, 0,0, 14,19, 14,18, 0,0, 0,0, 14,18, 14,20, 14,18, 0,0, 17,17, 19,23, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 14,18, 19,23, 19,23, 17,17, 0,0, 0,0, 15,21, 0,0, 0,0, 0,0, 16,15, 14,18, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 16,16, 0,0, 0,0, 0,0, 19,24, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 19,25, 19,24, 0,0, 0,0, 19,24, 19,26, 19,24, 0,0, 0,0, 0,0, 0,0, 0,0, 21,27, 0,0, 21,27, 0,0, 19,24, 21,28, 21,28, 21,28, 21,28, 21,28, 21,28, 21,28, 21,28, 21,28, 21,28, 19,24, 22,23, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 23,17, 0,0, 22,29, 22,23, 0,0, 0,0, 22,23, 22,30, 22,23, 23,22, 23,17, 0,0, 0,0, 23,17, 23,31, 23,17, 0,0, 0,0, 22,23, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 23,17, 0,0, 0,0, 0,0, 22,23, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 23,17, 27,28, 27,28, 27,28, 27,28, 27,28, 27,28, 27,28, 27,28, 27,28, 27,28, 28,28, 28,28, 28,28, 28,28, 28,28, 28,28, 28,28, 28,28, 28,28, 28,28, 29,17, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 29,22, 29,17, 0,0, 0,0, 29,17, 29,34, 29,17, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 29,17, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 29,17, 0,0, 0,0, 0,0, 0,0}; struct yysvf yysvec[] ={ 0, 0, 0, yycrank+-1, 0, yyvstop+1, yycrank+0, yysvec+1, yyvstop+3, yycrank+0, 0, yyvstop+5, yycrank+3, 0, yyvstop+7, yycrank+0, 0, yyvstop+10, yycrank+38, 0, yyvstop+12, yycrank+12, yysvec+6, yyvstop+15, yycrank+3, yysvec+6, yyvstop+18, yycrank+119, yysvec+6, yyvstop+21, yycrank+0, yysvec+6, yyvstop+24, yycrank+0, yysvec+4, yyvstop+28, yycrank+0, yysvec+6, yyvstop+30, yycrank+131, yysvec+6, yyvstop+32, yycrank+-188, 0, yyvstop+35, yycrank+151, yysvec+6, yyvstop+37, yycrank+210, yysvec+6, yyvstop+40, yycrank+-180, yysvec+14, 0, yycrank+-119, yysvec+14, yyvstop+42, yycrank+-238, 0, yyvstop+44, yycrank+0, yysvec+14, yyvstop+46, yycrank+249, yysvec+6, yyvstop+48, yycrank+-275, yysvec+19, 0, yycrank+-282, yysvec+14, 0, yycrank+-131, yysvec+14, yyvstop+50, yycrank+-143, yysvec+14, yyvstop+52, yycrank+0, yysvec+6, yyvstop+54, yycrank+304, yysvec+6, yyvstop+57, yycrank+314, yysvec+6, yyvstop+59, yycrank+-339, yysvec+14, 0, yycrank+0, 0, yyvstop+62, yycrank+144, 0, 0, yycrank+145, yysvec+6, yyvstop+64, yycrank+146, yysvec+6, yyvstop+66, yycrank+0, yysvec+31, yyvstop+69, 0, 0, 0}; struct yywork *yytop = yycrank+408; struct yysvf *yybgin = yysvec+1; char yymatch[] ={ 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 011 ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'*' ,'+' ,'!' ,'+' ,'.' ,'/' , '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , '0' ,'0' ,':' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'E' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' , '!' ,'!' ,'!' ,'!' ,'!' ,'!' ,'!' ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 0}; char yyextra[] ={ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0}; /* ncform 4.1 83/08/11 */ int yylineno =1; # define YYU(x) x # define NLSTATE yyprevious=YYNEWLINE char yytext[YYLMAX]; struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; char yysbuf[YYLMAX]; char *yysptr = yysbuf; int *yyfnd; extern struct yysvf *yyestate; int yyprevious = YYNEWLINE; yylook(){ register struct yysvf *yystate, **lsp; register struct yywork *yyt; struct yysvf *yyz; int yych; struct yywork *yyr; # ifdef LEXDEBUG int debug; # endif char *yylastch; /* start off machines */ #ifdef linux if (yyin == NULL) yyin = stdin; if (yyout == NULL) yyout = stdout; #endif # ifdef LEXDEBUG debug = 0; # endif if (!yymorfg) yylastch = yytext; else { yymorfg=0; yylastch = yytext+yyleng; } for(;;){ lsp = yylstate; yyestate = yystate = yybgin; if (yyprevious==YYNEWLINE) yystate++; for (;;){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1); # endif yyt = yystate->yystoff; if(yyt == yycrank){ /* may not be any transitions */ yyz = yystate->yyother; if(yyz == 0)break; if(yyz->yystoff == yycrank)break; } *yylastch++ = yych = input(); tryagain: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"unsigned char "); allprint(yych); putchar('\n'); } # endif yyr = yyt; if ( (int)yyt > (int)yycrank){ yyt = yyr + yych; if (yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } # ifdef YYOPTIM else if((int)yyt < (int)yycrank) { /* r < yycrank */ yyt = yyr = yycrank+(yycrank-yyt); # ifdef LEXDEBUG if(debug)fprintf(yyout,"compressed state\n"); # endif yyt = yyt + yych; if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transitions */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } yyt = yyr + YYU(yymatch[yych]); # ifdef LEXDEBUG if(debug){ fprintf(yyout,"try fall back character "); allprint(YYU(yymatch[yych])); putchar('\n'); } # endif if(yyt <= yytop && yyt->verify+yysvec == yystate){ if(yyt->advance+yysvec == YYLERR) /* error transition */ {unput(*--yylastch);break;} *lsp++ = yystate = yyt->advance+yysvec; goto contin; } } if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ # ifdef LEXDEBUG if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); # endif goto tryagain; } # endif else {unput(*--yylastch);break;} contin: # ifdef LEXDEBUG if(debug){ fprintf(yyout,"state %d char ",yystate-yysvec-1); allprint(yych); putchar('\n'); } # endif ; } # ifdef LEXDEBUG if(debug){ fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); allprint(yych); putchar('\n'); } # endif while (lsp-- > yylstate){ *yylastch-- = 0; if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ yyolsp = lsp; if(yyextra[*yyfnd]){ /* must backup */ while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ lsp--; unput(*yylastch--); } } yyprevious = YYU(*yylastch); yylsp = lsp; yyleng = yylastch-yytext+1; yytext[yyleng] = 0; # ifdef LEXDEBUG if(debug){ fprintf(yyout,"\nmatch "); sprint(yytext); fprintf(yyout," action %d\n",*yyfnd); } # endif return(*yyfnd++); } unput(*yylastch); } if (yytext[0] == 0 /* && feof(yyin) */) { yysptr=yysbuf; return(0); } yyprevious = yytext[0] = input(); if (yyprevious>0) output(yyprevious); yylastch=yytext; # ifdef LEXDEBUG if(debug)putchar('\n'); # endif } } yyback(p, m) int *p; { if (p==0) return(0); while (*p) { if (*p++ == m) return(1); } return(0); } /* the following are only used in the lex library */ yyinput(){ #ifdef linux if (yyin == NULL) yyin = stdin; #endif return(input()); } yyoutput(c) int c; { #ifdef linux if (yyout == NULL) yyout = stdout; #endif output(c); } yyunput(c) int c; { unput(c); } graywolf-0.1.4+20170307gite1bf319/src/twsc/readpar.c000066400000000000000000000622741305746555600213300ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * Copyright (C) 2013 Tim Edwards * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: readpar.c DESCRIPTION:read parameter file. CONTENTS: readParFile() yaleIntro(message) char *message ; DATE: Mar 27, 1989 REVISIONS: Nov 23, 1990 - now use new readpar library function. Only need to read one of two .par or .spar Thu Feb 7 00:11:36 EST 1991 - added new.pin.format. Sun Feb 17 21:05:03 EST 1991 - added min_pad_spacing. Sat Feb 23 00:30:06 EST 1991 - now handle wildcarding. Wed Mar 13 13:46:21 CST 1991 - made the new format the default. Thu Apr 18 01:56:45 EDT 1991 - added new parameter functions for design rules. Wed Jun 5 16:47:12 CDT 1991 - added default for vertical_wire_weight. Thu Jun 13 11:48:40 CDT 1991 - changed to no.graphics. Wed Jul 3 13:51:21 CDT 1991 - added print_pins. Fri Sep 6 15:18:00 CDT 1991 - added no_feed_est for emergencies. Thu Sep 19 14:15:51 EDT 1991 - added equal width cell capability. Fri Nov 8 01:13:18 EST 1991 - added even the rows maximally. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) readpar.c (Yale) version 4.26 5/12/92" ; #endif #endif #define READPAR_VARS #define NOTSPECIFIED -1 #define COMMENT '#' #include "standard.h" #include "main.h" #include "parser.h" #include "readpar.h" #include "groute.h" #include "feeds.h" #include "config.h" #include "pads.h" #include #include #include /* globals variable definitions */ INT attprcelG ; INT core_widthG ; INT core_heightG ; INT core_xstartG ; INT core_ystartG ; INT spacer_widthG = -1 ; INT *spacer_feedsG ; INT vertical_pitchG = 0 ; INT total_row_lengthG ; INT vertical_track_pitchG = 0 ; INT horizontal_track_pitchG = 0 ; INT approximately_fixed_factorG = 1 ; INT global_routing_iterationsG = 0 ; BOOL no_feed_estG = TRUE ; BOOL placement_improveG = TRUE ; BOOL intel_debugG = FALSE ; BOOL do_fast_globalG = FALSE ; BOOL new_row_formatG = FALSE ; BOOL no_feed_at_endG ; BOOL call_row_evenerG = FALSE ; BOOL turn_off_checksG = FALSE ; BOOL min_peak_densityG = FALSE ; BOOL do_not_even_rowsG = FALSE ; BOOL min_total_densityG = FALSE ; BOOL ignore_crossbusesG = FALSE ; BOOL output_at_densityG = FALSE ; BOOL spacer_name_twfeedG = FALSE ; BOOL create_new_cel_fileG = FALSE ; BOOL rigidly_fixed_cellsG = FALSE ; BOOL exclude_noncrossbus_padsG = TRUE ; BOOL stand_cell_as_gate_arrayG = FALSE ; BOOL good_initial_placementG = FALSE ; BOOL glob_route_only_crit_netsG = FALSE ; BOOL unused_feed_name_twspacerG = FALSE ; BOOL absolute_minimum_feedsG = FALSE ; BOOL ignore_feedsG = FALSE ; BOOL vertical_track_on_cell_edgeG ; BOOL route_padnets_outsideG ; BOOL prop_rigid_cellsG = FALSE ; BOOL even_rows_maximallyG = FALSE ; DOUBLE indentG ; DOUBLE metal2_pitchG ; /* globals variable references */ extern BOOL orientation_optimizationG ; extern BOOL doubleback_rows_start_at_oneG ; /* static variables */ static BOOL abortS = FALSE ; static BOOL readparamS = FALSE ; static init_read_par(); static readparam(); static process_readpar(); static err_msg(); readParFile() { init_read_par() ; readparam( TWSC ) ; readparam( USER ) ; process_readpar() ; } static init_read_par() { /* initialization of variables */ SGGRG = FALSE ; gate_arrayG = FALSE ; try_not_to_add_explicit_feedsG = FALSE ; vertical_track_on_cell_edgeG = FALSE ; no_feed_at_endG = TRUE ; spacer_feedsG = (INT *) Ysafe_malloc( 101 * sizeof(INT) ) ; spacer_feedsG[0] = 0 ; metal2_pitchG = 0.0 ; core_widthG = 0 ; core_heightG = 0 ; core_xstartG = 0 ; core_ystartG = 0 ; vertical_wire_weightG = -1.0 ; vertical_path_weightG = -1.0 ; horizontal_path_weightG = 1.0 ; swap_netG = FALSE ; case_unequiv_pinG = FALSE ; swappable_gates_existG = FALSE ; min_pad_spacingG = 0 ; Equal_Width_CellsG = FALSE ; file_conversionG = FALSE ; } /* end init_read_par */ static readparam( parfile ) INT parfile ; { INT test ; INT speed ; INT pins ; INT spacer_tmp ; INT line ; INT numtokens ; BOOL onNotOff ; BOOL wildcard ; char **tokens ; char *lineptr ; Yreadpar_init( cktNameG, parfile, TWSC, FALSE ) ; OUT1( "\n\n" ) ; while( tokens = Yreadpar_next( &lineptr, &line, &numtokens, &onNotOff, &wildcard )){ readparamS = TRUE ; if( numtokens == 0 ){ /* skip over empty lines */ continue ; } else if( strcmp( tokens[0],"fast") == STRINGEQ ){ if( numtokens == 2 ) { tw_fastG = atoi( tokens[1] ) ; } else { err_msg("fast") ; } } else if( strcmp( tokens[0],"slow") == STRINGEQ ){ if( numtokens == 2 ) { tw_slowG = atoi( tokens[1] ) ; } else { err_msg("slow") ; } } else if( strcmp( tokens[0], "equal_width_cells" ) == STRINGEQ ){ if( onNotOff ){ Equal_Width_CellsG = TRUE ; } else { Equal_Width_CellsG = FALSE ; } /*--------------------------------------------------------------*/ } else if( strcmp( tokens[0],"file_conversion_only") == STRINGEQ ){ if( onNotOff ){ file_conversionG = TRUE ; } else { file_conversionG = FALSE ; } } else if( strcmp( tokens[0],"even_rows_maximally") == STRINGEQ ){ if( onNotOff ){ even_rows_maximallyG = TRUE ; } else { even_rows_maximallyG = FALSE ; } } else if( strcmp( tokens[0],"vertical_wire_weight") == STRINGEQ ){ if( numtokens == 2 ) { vertical_wire_weightG = atof( tokens[1] ) ; } else { err_msg("vertical_wire_weight") ; } } else if( strcmp( tokens[0],"vertical_path_weight") == STRINGEQ ){ if( numtokens == 2 ) { vertical_path_weightG = atof( tokens[1] ) ; if( vertical_wire_weightG < 0.0 ){ vertical_wire_weightG = vertical_path_weightG ; } } else { err_msg("vertical_path_weight") ; } } else if( strcmp( tokens[0],"horizontal_path_weight") == STRINGEQ ){ if( numtokens == 2 ) { horizontal_path_weightG = atof( tokens[1] ) ; } else { err_msg("horizontal_path_weight") ; } } else if( strcmp( tokens[0],"approximately_fixed_factor") == STRINGEQ ){ if( numtokens == 2 ) { approximately_fixed_factorG = atoi( tokens[1] ) ; } else { err_msg("approximately_fixed_factor") ; } if( approximately_fixed_factorG < 1 ) { err_msg("approximately_fixed_factor") ; } } else if( strcmp( tokens[0],"turn_off_checks") == STRINGEQ ){ if( onNotOff ){ turn_off_checksG = TRUE ; } else { turn_off_checksG = FALSE ; } } else if( strcmp( tokens[0],"gr_placement_improve") == STRINGEQ ){ if( onNotOff ){ placement_improveG = TRUE ; } else { placement_improveG = FALSE ; } } else if( strcmp( tokens[0],"route_only_critical_nets") == STRINGEQ ){ if( onNotOff ){ glob_route_only_crit_netsG = TRUE ; } else { glob_route_only_crit_netsG = FALSE ; } } else if( strcmp( tokens[0],"min_peak_density") == STRINGEQ ){ if( onNotOff ){ min_peak_densityG = TRUE ; } else { min_peak_densityG = FALSE ; } } else if( strcmp( tokens[0],"min_total_density") == STRINGEQ ){ if( onNotOff ){ min_total_densityG = TRUE ; } else { min_total_densityG = FALSE ; } } else if( strcmp( tokens[0],"call_row_evener") == STRINGEQ ){ if( onNotOff ){ call_row_evenerG = TRUE ; } else { call_row_evenerG = FALSE ; } } else if( strcmp( tokens[0],"create_new_cel_file") == STRINGEQ ){ if( onNotOff ){ create_new_cel_fileG = TRUE ; } else { create_new_cel_fileG = FALSE ; } } else if( strcmp( tokens[0],"unused_feed_name_twspacer") == STRINGEQ ){ if( onNotOff ){ unused_feed_name_twspacerG = TRUE ; } else { unused_feed_name_twspacerG = FALSE ; } } else if( strcmp( tokens[0],"spacer_name_twfeed") == STRINGEQ ){ if( onNotOff ){ spacer_name_twfeedG = TRUE ; } else { spacer_name_twfeedG = FALSE ; } } else if( strcmp( tokens[0],"new_row_format") == STRINGEQ ){ if( onNotOff ){ new_row_formatG = TRUE ; } else { new_row_formatG = FALSE ; } } else if( strcmp( tokens[0],"good_initial_placement") == STRINGEQ ){ if( numtokens == 2 ) { good_initial_placementG = atoi( tokens[1] ) ; } else { err_msg("good_initial_placement") ; } } else if( strcmp( tokens[0],"orientation_optimization") == STRINGEQ ){ if( onNotOff ){ orientation_optimizationG = TRUE ; } else { orientation_optimizationG = FALSE ; } } else if( strcmp( tokens[0],"do_not_even_rows") == STRINGEQ ){ if( onNotOff ){ do_not_even_rowsG = TRUE ; } else { do_not_even_rowsG = FALSE ; } } else if( strcmp( tokens[0],"absolute_minimum_feeds") == STRINGEQ ){ if( onNotOff ){ absolute_minimum_feedsG = TRUE ; } else { absolute_minimum_feedsG = FALSE ; } } else if( strcmp( tokens[0],"ignore_feeds") == STRINGEQ ){ if( onNotOff ){ ignore_feedsG = TRUE ; } else { ignore_feedsG = FALSE ; } } else if( strcmp( tokens[0],"pin_layers_given") == STRINGEQ ){ if( onNotOff ){ pin_layers_givenG = TRUE ; } else { pin_layers_givenG = FALSE ; } } else if( strcmp( tokens[0],"no_explicit_feeds") == STRINGEQ ){ if( onNotOff ){ try_not_to_add_explicit_feedsG = TRUE ; } else { try_not_to_add_explicit_feedsG = FALSE ; } } else if( strcmp( tokens[0],"no_feed_at_end") == STRINGEQ ){ if( onNotOff ){ no_feed_at_endG = TRUE ; } else { no_feed_at_endG = FALSE ; } } else if( strcmp( tokens[0],"intel_debug") == STRINGEQ ){ if( onNotOff ){ intel_debugG = TRUE ; } else { intel_debugG = FALSE ; } } else if( strcmp( tokens[0],"exclude_noncrossbus_pads") == STRINGEQ ){ if( onNotOff ){ exclude_noncrossbus_padsG = TRUE ; } else { exclude_noncrossbus_padsG = FALSE ; } } else if( strcmp( tokens[0],"proportionally_space_rigid_cells") == STRINGEQ ){ if( onNotOff ){ prop_rigid_cellsG = TRUE ; } else { prop_rigid_cellsG = FALSE ; } } else if( strcmp( tokens[0],"ignore_crossbuses") == STRINGEQ ){ if( onNotOff ){ ignore_crossbusesG = TRUE ; } else { ignore_crossbusesG = FALSE ; } } else if( strcmp( tokens[0],"connection_machine") == STRINGEQ ){ if( numtokens == 2 ) { connection_machineG = atoi( tokens[1] ) ; } else { err_msg("connection_machine") ; } } else if( strcmp( tokens[0],"doubleback_rows_start_at_one") == STRINGEQ ){ if( onNotOff ){ intelG = TRUE ; no_feed_estG = TRUE ; doubleback_rows_start_at_oneG = TRUE ; } else { intelG = FALSE ; no_feed_estG = TRUE ; doubleback_rows_start_at_oneG = FALSE ; } } else if( strcmp( tokens[0],"doubleback_rows_start_at_two") == STRINGEQ ){ if( onNotOff ){ intelG = TRUE ; no_feed_estG = TRUE ; doubleback_rows_start_at_oneG = FALSE ; } else { intelG = FALSE ; no_feed_estG = TRUE ; doubleback_rows_start_at_oneG = FALSE ; } } else if( strcmp( tokens[0],"vertical_track_on_cell_edge") == STRINGEQ ){ if( onNotOff ){ vertical_track_on_cell_edgeG = TRUE ; } else { vertical_track_on_cell_edgeG = FALSE ; } } else if( strcmp( tokens[0],"cost_only") == STRINGEQ ){ if( onNotOff ){ costonlyG = TRUE ; } else { costonlyG = FALSE ; } } else if( strcmp( tokens[0],"no_feed_est") == STRINGEQ ){ if( onNotOff ){ no_feed_estG = TRUE ; } else { no_feed_estG = TRUE ; } } else if( strcmp( tokens[0],"only.do.global.route") == STRINGEQ ){ if( onNotOff ){ doglobalG = TRUE ; costonlyG = TRUE ; resume_runG = YES ; } else { doglobalG = FALSE ; costonlyG = FALSE ; resume_runG = NO ; } } else if( strcmp( tokens[0],"SGGR") == STRINGEQ ){ if( onNotOff ){ SGGRG = TRUE ; } else { SGGRG = FALSE ; } } else if( strcmp( tokens[0],"global_routing_iterations") == STRINGEQ ){ if( numtokens == 2 ) { global_routing_iterationsG = atoi( tokens[1] ) ; } else { err_msg("global_routing_iterations") ; } } else if( strcmp( tokens[0],"do.global.route") == STRINGEQ ){ if( onNotOff ){ doglobalG = TRUE ; } else { doglobalG = FALSE ; } } else if( strcmp( tokens[0],"standard_cell_as_gate_array") == STRINGEQ ){ if( onNotOff ){ stand_cell_as_gate_arrayG = TRUE ; } else { stand_cell_as_gate_arrayG = FALSE ; } } else if( strcmp( tokens[0], "print_pins" ) == STRINGEQ ){ if( numtokens == 2 ) { pins = atoi( tokens[1] ) ; set_print_pin( pins ) ; } else { err_msg("print_pins") ; } } else if( strcmp( tokens[0],"do.fast.global.route") == STRINGEQ ){ if( onNotOff ){ do_fast_globalG = TRUE ; doglobalG = TRUE ; } else { do_fast_globalG = FALSE ; doglobalG = FALSE ; } } else if( strcmp( tokens[0],"feedThruWidth") == STRINGEQ ){ if( numtokens == 2 ) { fdWidthG = atoi( tokens[1] ) ; } else if( numtokens == 4 ) { pin_layers_givenG = TRUE ; fdWidthG = atoi( tokens[1] ) ; feedLayerG = atoi( tokens[3] ) ; if( feedLayerG == 0 ){ feedLayerG = 1 ; } else if( feedLayerG == 0 ){ err_msg("layer") ; } } else { err_msg("feedThruWidth") ; } } else if( strcmp( tokens[0],"total_row_length") == STRINGEQ ){ if( numtokens == 2 ) { total_row_lengthG = atoi( tokens[1] ) ; } else { err_msg("total_row_length") ; } } else if( strcmp( tokens[0],"spacer_width") == STRINGEQ ){ if( numtokens == 2 ) { spacer_widthG = atoi( tokens[1] ) ; } else { err_msg("spacer_width") ; } gate_arrayG = TRUE ; try_not_to_add_explicit_feedsG = TRUE ; } else if( strcmp( tokens[0],"spacer_feed_from_left") == STRINGEQ ){ if( numtokens == 2 ) { spacer_tmp = atoi( tokens[1] ) ; } else { err_msg("spacer_feed_from_left") ; } spacer_feedsG[ ++spacer_feedsG[0] ] = spacer_tmp ; } else if( strcmp( tokens[0],"metal2_pitch") == STRINGEQ ){ if( numtokens == 2 ) { metal2_pitchG = atof( tokens[1] ) ; } else { err_msg("metal2_pitch") ; } } else if( strcmp( tokens[0],"vertical.pitch") == STRINGEQ ){ if( numtokens == 2 ) { vertical_pitchG = atoi( tokens[1] ) ; } else { err_msg("vertical.pitch") ; } } else if( strcmp( tokens[0],"core_width") == STRINGEQ ){ if( numtokens == 2 ) { core_widthG = atoi( tokens[1] ) ; } else { err_msg("core_width") ; } } else if( strcmp( tokens[0],"core_height") == STRINGEQ ){ if( numtokens == 2 ) { core_heightG = atoi( tokens[1] ) ; } else { err_msg("core_height") ; } } else if( strcmp( tokens[0],"core_xstart_relative_to_left_edge_of_rows") == STRINGEQ ){ if( numtokens == 2 ) { core_xstartG = atoi( tokens[1] ) ; } else { err_msg("core_xstart_relative_to_left_edge_of_rows") ; } } else if( strcmp( tokens[0],"core_ystart_relative_to_bottom_of_first_row") == STRINGEQ ){ if( numtokens == 2 ) { core_ystartG = atoi( tokens[1] ) ; } else { err_msg("core_ystart_relative_to_bottom_of_first_row") ; } } else if( strcmp( tokens[0],"addFeeds") == STRINGEQ ){ /* don't do anything for old keyword */ } else if( strcmp( tokens[0],"indent") == STRINGEQ ){ if( numtokens != 2 ) { err_msg("indent") ; } indentG = 1.0 ; /* indent should always be 1.0 now */ } else if( strcmp( tokens[0],"random.seed") == STRINGEQ ){ if( numtokens == 2 ) { randomSeedG = (UNSIGNED_INT) atoi( tokens[1] ) ; } else { err_msg("random.seed") ; } } else if( strcmp( tokens[0],"rowSep") == STRINGEQ ){ if( numtokens >= 2 ) { rowSepG = atof( tokens[1] ) ; rowSepAbsG = (numtokens == 3) ? (INT) atof( tokens[2] ) : 0 ; } else { err_msg("rowSep") ; } } else if( strcmp( tokens[0],"restart") == STRINGEQ ){ if( onNotOff ){ resume_runG = YES ; } else { resume_runG = NO ; } } else if( strcmp( tokens[0],"uneven.cell.height") == STRINGEQ ){ if( onNotOff ){ uneven_cell_heightG = TRUE ; } else { uneven_cell_heightG = FALSE ; } } else if( strcmp( tokens[0],"route.to.active") == STRINGEQ ){ /* route2act is the routing layer to active cell minimum spacing */ if( numtokens == 2 ) { route2actG = atoi( tokens[1] ) ; } else { err_msg("route.to.active") ; } } else if( strcmp( tokens[0],"output.at.density") == STRINGEQ ){ if( onNotOff ){ output_at_densityG = TRUE ; } else { output_at_densityG = FALSE ; } } else if( strcmp( tokens[0],"one.pin.feedthru") == STRINGEQ ){ if( onNotOff ){ one_pin_feedthruG = TRUE ; } else { one_pin_feedthruG = FALSE ; } } else if( strcmp( tokens[0],"route_padnets_outside") == STRINGEQ ){ if( onNotOff ){ route_padnets_outsideG = TRUE ; } else { route_padnets_outsideG = FALSE ; } } else if( strcmp( tokens[0],"lambda") == STRINGEQ ){ } else if( strcmp( tokens[0],"no.graphics") == STRINGEQ ){ if( onNotOff ){ doGraphicsG = FALSE ; } else { doGraphicsG = TRUE ; } } else if( strcmp( tokens[0],"no.graphics.update") == STRINGEQ ){ if( onNotOff ){ G( set_update( FALSE ) ) ; } else { G( set_update( TRUE ) ) ; } } else if( strcmp( tokens[0],"graphics.wait") == STRINGEQ ){ } else if( strcmp( tokens[0],"old.pin.format") == STRINGEQ ){ if( onNotOff ){ set_pin_format( TRUE ) ; } else { set_pin_format( FALSE ) ; } } else if( strcmp( tokens[0], "contiguous_pad_groups" ) == STRINGEQ ){ if( onNotOff ){ contiguousG = TRUE ; } else { contiguousG = FALSE ; } } else if( strcmp( tokens[0], "minimum_pad_space" ) == STRINGEQ ){ if( numtokens == 2 ) { min_pad_spacingG = atoi( tokens[1] ); } else { err_msg("minimum space between pads") ; } } else if( strcmp( tokens[0], "padspacing" ) == STRINGEQ ){ if( numtokens == 2 ) { if( strcmp( tokens[1] , "uniform" ) == STRINGEQ ) { padspacingG = UNIFORM_PADS ; } else if( strcmp( tokens[1] , "variable" ) == STRINGEQ ) { padspacingG = VARIABLE_PADS ; } else if( strcmp( tokens[1] , "abut" ) == STRINGEQ ) { padspacingG = ABUT_PADS ; } else if( strcmp( tokens[1] , "exact" ) == STRINGEQ ) { padspacingG = EXACT_PADS ; } else { OUT1("Unexpected padspacing keyword in the .par file\n"); abortS = TRUE ; } } else { err_msg("padspacing") ; } /*** catch all ***/ } else if(!(wildcard)){ if( parfile == USER ){ OUT4("ERROR[readpar]:unexpected keyword in the %s.par file at line:%d\n\t%s\n", cktNameG, line, lineptr ); } else { OUT4("ERROR[readpar]:Unexpected keyword in the %s.spar file at line:%d\n\t%s\n", cktNameG, line, lineptr ); } Ymessage_error_count() ; abortS = TRUE ; } } } /* end readparam */ static process_readpar() { char *layer ; /* name of layer */ INT i ; /* counter */ INT pitch ; /* the pitch of the layer */ INT numv_layers ; /* number of vertical layers */ INT numh_layers ; /* number of horizontal layers */ INT num_layers ; /* total number of layers */ if( abortS ){ OUT1( "Errors found in the .par file. Must exit\n\n" ) ; YexitPgm(PGMFAIL); } if( !(readparamS)){ M( ERRMSG, "process_readpar", "No parameter files found. Must exit\n\n") ; YexitPgm(PGMFAIL); } if( vertical_wire_weightG < 0 ) { fprintf( fpoG, "vertical_wire_weight ") ; fprintf( fpoG, "was NOT found in the .par file\n"); YexitPgm(PGMFAIL); } if( vertical_path_weightG < 0 ) { fprintf( fpoG, "vertical_path_weight ") ; fprintf( fpoG, "was NOT found in the .par file\n"); YexitPgm(PGMFAIL); } if( spacer_widthG == -1 ) { spacer_feedsG[0] = 1 ; spacer_feedsG[1] = fdWidthG / 2 ; spacer_widthG = fdWidthG ; } numv_layers = 0 ; numh_layers = 0 ; num_layers = Yreadpar_numlayers() ; for( i = 1; i <= num_layers; i++ ){ layer = Yreadpar_id2layer( i ) ; pitch = Yreadpar_pitch( layer ) ; if( Yreadpar_layer_HnotV( layer ) ){ horizontal_track_pitchG += pitch ; numh_layers++ ; } else { vertical_track_pitchG += pitch ; numv_layers++ ; } } /* get the average pitch of all the layers */ if( numv_layers > 0 ){ vertical_track_pitchG /= numv_layers ; if( vertical_track_pitchG == 0 ){ vertical_track_pitchG == 1 ; } } if( numh_layers > 0 ){ horizontal_track_pitchG++ ; /* to account for the -1 initialization */ horizontal_track_pitchG /= numh_layers ; if( horizontal_track_pitchG == 0 ){ horizontal_track_pitchG == 1 ; } track_pitchG = horizontal_track_pitchG ; /* these are the same var. */ } if( vertical_track_pitchG == 0 || horizontal_track_pitchG == 0 ) { if( vertical_track_pitchG == 0 ) { M( ERRMSG, "readpar", "Vertical track pitch could not be calculated from design rules\n"); M( ERRMSG, NULL, "Check the design rules in parameter file\n\n") ; } if( horizontal_track_pitchG == 0 ) { M( ERRMSG, "readpar", "Horizontal track pitch could not be calculated from design rules\n"); M( ERRMSG, NULL, "Check the design rules in parameter file\n\n") ; } YexitPgm(PGMFAIL); } #ifdef INTEL if( 0 /* intel */ ) { doglobalG = 0 ; if( metal2_pitchG == 0.0 ) { fprintf( fpoG,"metal2_pitch was not entered in the .par file\n"); YexitPgm(PGMFAIL); } else { fprintf( fpoG, "metal2_pitch: %f\n" , metal2_pitchG ) ; } } #endif /* INTEL */ if( doglobalG ) { fprintf(fpoG,"TimberWolf will perform a global route step\n"); } if( doglobalG == TRUE && fdWidthG == -1 ) { fprintf(fpoG,"feedThruWidth was not entered in the .par file\n"); YexitPgm(PGMFAIL); } else { fprintf( fpoG, "feedThruWidth: %d\n" , fdWidthG ) ; } /* make sure track pitch has been specified for uneven cell heights */ if( uneven_cell_heightG ){ if( track_pitchG == NOTSPECIFIED ){ fprintf( fpoG, "TimberWolfSC cannot perform uneven cell"); fprintf( fpoG, "height calculations without track pitch\n"); fprintf( fpoG, "Enter track.pitch in the .par file\n"); } } if( track_pitchG != NOTSPECIFIED ) { fprintf( fpoG, "track.pitch: %d\n" , track_pitchG ) ; if( route2actG == NOTSPECIFIED ){ fprintf( fpoG, "route2act was not entered in the .par file\n"); fprintf( fpoG, "route2act defaulted to track.pitch\n"); route2actG = track_pitchG ; } fprintf( fpoG, "route2act: %d\n" , route2actG ) ; } else { fprintf( fpoG, "track.pitch was not specified in par file\n" ) ; fprintf( fpoG, "TimberWolfSC will output cell locations according\n"); fprintf( fpoG, "to user supplied row separation.\n" ) ; } return ; } /* end process_readpar */ yaleIntro() { INT i ; fprintf(fpoG,"\n%s\n",YmsgG) ; fprintf(fpoG,"Row-Based Placement and Global Routing Program\n"); fprintf(fpoG,"Authors: Carl Sechen, Kai-Win Lee, and Bill Swartz,\n"); fprintf(fpoG," Yale University\n"); printf("%s\n",YmsgG) ; printf("Row-Based Placement and Global Routing Program\n"); printf("Authors: Carl Sechen, Kai-Win Lee, and Bill Swartz,\n"); printf(" Yale University\n"); /* inialize variables */ randomSeedG = (unsigned) Yrandom_seed() ; fixarrayG = (INT *) NULL ; ffeedsG = 0 ; macspaceG = (DOUBLE *) Ysafe_malloc( 24 * sizeof(DOUBLE) ) ; for( i = 1 ; i <= 15 ; i++ ) { macspaceG[i] = -1.0 ; } costonlyG = FALSE ; fdthrusG = FALSE ; doglobalG = FALSE ; attprcelG = 0 ; fdWidthG = -1 ; track_pitchG = -1 ; route2actG = -1 ; rowSepG = -1.0 ; rowSepAbsG = 0 ; indentG = 1.0 ; numSegsG = 0 ; resume_runG = NO ; pin_layers_givenG = TRUE ; no_feeds_side_netsG = FALSE ; feedLayerG = 0 ; tw_fastG = 0 ; tw_slowG = 0 ; estimate_feedsG = TRUE ; connection_machineG = 0 ; route_padnets_outsideG = FALSE ; } /* end yaleIntro */ static err_msg( keyword ) char *keyword ; { OUT2("The value for %s was", keyword ); OUT1(" not properly entered in the .par file\n"); abortS = TRUE ; }/* end err_msg */ graywolf-0.1.4+20170307gite1bf319/src/twsc/readpar.h000066400000000000000000000022431305746555600213230ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) readpar.h (Yale) version 4.4 11/8/91" FILE: readpar.h DESCRIPTION:global definitions for TimberWolfSC CONTENTS: DATE: Mar 27, 1989 REVISIONS: Thu Sep 19 14:15:51 EDT 1991 - added equal width cell capability. ----------------------------------------------------------------- */ #ifndef READPAR_H #define READPAR_H /* global variables defined for main */ #ifdef READPAR_VARS #define EXTERN #else #define EXTERN extern #endif EXTERN BOOL addFeedsG ; EXTERN BOOL connection_machineG ; EXTERN BOOL costonlyG ; EXTERN BOOL cswapsG ; EXTERN BOOL doglobalG ; EXTERN BOOL doGraphicsG ; EXTERN BOOL estimate_feedsG ; EXTERN BOOL gate_arrayG ; EXTERN BOOL gate_array_specialG ; EXTERN BOOL intelG ; EXTERN BOOL restartG ; EXTERN BOOL SGGRG ; EXTERN BOOL try_not_to_add_explicit_feedsG ; EXTERN BOOL Equal_Width_CellsG ; EXTERN BOOL file_conversionG ; EXTERN BOOL even_rows_maximallyG ; EXTERN INT feedLayerG ; EXTERN INT no_feeds_side_netsG ; EXTERN INT pin_layers_givenG ; EXTERN INT tw_fastG ; EXTERN INT tw_slowG ; #undef EXTERN #endif /* READPAR_VARS */ graywolf-0.1.4+20170307gite1bf319/src/twsc/reconfig.c000066400000000000000000000256571305746555600215120ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: reconfig.c DESCRIPTION:cell topology configuration with feed estimation. CONTENTS: INT reconfig() DATE: Mar 27, 1989 REVISIONS: Thu Jan 31 15:56:39 EST 1991 - now only call findcostf if criteria is met. Instead call recompute_wirecosts and recompute_timecosts. Wed Jul 24 20:58:00 CDT 1991 - reset the MIN_FEED_RATIO number. Fri Sep 6 15:19:05 CDT 1991 - now calculate the feed taper from previous run. Wed Sep 11 11:27:46 CDT 1991 - added user output info for blocks. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) reconfig.c (Yale) version 4.11 4/2/92" ; #endif #endif #include "standard.h" #include "readpar.h" #include "main.h" #include #include #include #if SIZEOF_VOID_P == 64 #define INTSCANSTR "%ld" #else #define INTSCANSTR "%d" #endif #define MIN_FEED_RATIO 0.66 /* global definitions */ extern BOOL no_feed_estG ; extern INT fdWidthG ; extern INT totalRG ; extern INT extra_cellsG ; extern INT *feeds_in_rowG ; /* static definitions */ static BOOL feed_length_setS = TRUE ; static INT feed_lengthS ; /* the current feed length */ static INT old_feed_lengthS = 0 ; /* the feed length from the last iteration */ static BOOL print_desiredS = TRUE ; INT reconfig() { INT block ; INT total_desire ; if( print_desiredS ) { print_desiredS = FALSE ; total_desire = 0 ; for( block = 1 ; block <= numRowsG ; block++ ) { total_desire += barrayG[block]->desire ; fprintf(fpoG,"block:%d desire:%d\n",block,barrayG[block]->desire); } fprintf(fpoG,"Total Desired Length: %d\n", total_desire ) ; } /* place the pads */ placepads() ; /* call this since pad placement may change costs */ funccostG = recompute_wirecost() ; timingcostG = recompute_timecost() ; return( 0 ) ; } /* end reconfig */ static configuref() { INT row ; INT cell ; INT core_left ; INT core_right ; INT shift_amount ; INT extra_shift , tmp ; /* see if any rows would be completely filled with feeds */ extra_shift = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { tmp = feeds_in_rowG[row] * fdWidthG ; if( tmp > barrayG[row]->orig_desire ) { extra_shift += tmp - barrayG[row]->orig_desire ; } } feed_lengthS -= extra_shift ; shift_amount = (feed_lengthS / numRowsG) - (old_feed_lengthS / numRowsG) ; if( shift_amount == 0 ) { for( row = 1 ; row <= numRowsG ; row++ ) { barrayG[row]->oldsize = 0 ; } return ; } core_right = INT_MIN ; core_left = INT_MAX ; for( row = 1 ; row <= numRowsG ; row++ ) { if( barrayG[row]->bxcenter + barrayG[row]->bleft < core_left ) { core_left = barrayG[row]->bxcenter + barrayG[row]->bleft ; } totalRG += shift_amount ; barrayG[row]->bright += shift_amount ; barrayG[row]->blength += shift_amount ; barrayG[row]->desire += shift_amount ; barrayG[row]->oldsize = 0 ; if( barrayG[row]->bxcenter + barrayG[row]->bright > core_right ) { core_right = barrayG[row]->bxcenter + barrayG[row]->bright ; } } for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( carrayG[cell]->cclass < 0 ) { if( carrayG[cell]->border < 0 ) { carrayG[cell]->cxcenter += shift_amount ; } } } old_feed_lengthS = feed_lengthS ; } /* end configuref */ read_feeds( fp ) FILE *fp ; { fscanf( fp , INTSCANSTR , &feed_lengthS ) ; feed_length_setS = TRUE ; } /* end read_feeds */ save_feeds( fp ) FILE *fp ; { fprintf( fp, "%d\n", feed_lengthS ) ; } /* end save_feeds */ /* *********************************************************** Use .pl2 to find the number of rows in the output .pl1 file. Read the .pl1 to find out the number of explicit feeds. We can then set the feed taper for each row. First we assume that we have the same number of rows. If we don't, then we will bin the rows to smooth the function and approximate. *********************************************************** */ BOOL read_feed_data() { #define EQUAL_CASE 0 /* equal number of rows */ #define LESS_ROWS_CASE 1 /* currently have less rows */ #define MORE_ROWS_CASE 2 /* currently have more rows */ INT row ; /* counter */ INT numtokens ; /* number of tokens on the line */ INT pl1_rows ; /* the number of row found in .pl2 */ INT pl1_case ; /* which of 3 cases we have */ INT row_in_pl1 ; /* the feed was found in this row */ INT start_row ; /* the first row in case 3 */ INT end_row ; /* the last row in case 3 */ FILE *fp ; /* current file pointer */ DOUBLE *smooth ; /* used to calculate MORE_ROWS case */ DOUBLE value ; /* distribute feed over mult. rows */ char filename[LRECL] ; /* name of the file */ char buffer[LRECL] ; /* read string into buffer */ char *bufferptr ; /* start of the buffer */ char **tokens ; /* tokens on the line */ /* only process this file once */ static BOOL already_processedL = FALSE ; /* save the result for future use. Default no feeds */ static BOOL feed_statusL = FALSE ; if( already_processedL ){ /* We only need to call routine once. Return the saved result. */ return( feed_statusL ) ; } already_processedL = TRUE ; /* If we get here, this is the first time try to open .pl2 */ sprintf( filename, "%s.pl2", cktNameG ) ; fp = TWOPEN( filename, "r", NOABORT ) ; if(!(fp)){ /* no feed data present return false */ return( FALSE ) ; } /*********************************************************** * Read from circuitName.pl2 file. ***********************************************************/ pl1_rows = 0 ; while( bufferptr = fgets( buffer, LRECL, fp ) ){ tokens = Ystrparser( bufferptr, " \t\n", &numtokens ) ; if( numtokens != 7 ){ continue ; } row = atoi( tokens[0] ) ; if( row > 0 ){ /* make sure the last two fields are zero */ if( atoi(tokens[5]) == 0 && atoi(tokens[6]) == 0 ){ pl1_rows = row ; } } } TWCLOSE( fp ) ; if( pl1_rows <= 0 ){ /* no valid feed data present return false */ return( FALSE ) ; } /*********************************************************** * Now set the case. Easy case I. pl1_rows == numRowsG. * case II. pll1_rows > numRowsG. * case III. pl1_rows < numRowsG. ***********************************************************/ if( pl1_rows == numRowsG ){ pl1_case = EQUAL_CASE ; } else if( pl1_rows > numRowsG ){ pl1_case = LESS_ROWS_CASE ; M( WARNMSG, "read_feed_data", "The number of rows have decreased since the last run.\n" ) ; } else if( pl1_rows < numRowsG ){ pl1_case = MORE_ROWS_CASE ; M( WARNMSG, "read_feed_data", "The number of rows have increased since the last run.\n" ) ; /* here we need also to make a smoothing array */ smooth = (DOUBLE *) Ysafe_malloc( (numRowsG+1) * sizeof(DOUBLE) ) ; for( row = 1; row <= numRowsG; row++ ){ smooth[row] = 0.0 ; } } if( pl1_case == LESS_ROWS_CASE || pl1_case == MORE_ROWS_CASE ){ M( WARNMSG, NULL, "This may affect feed estimation. To insure the best results,\n" ) ; M( WARNMSG, NULL, "\trun TimberWolf at least one more time.\n\n" ) ; } /*********************************************************** * Now read from circuitName.pl1 file to get explicit feeds. ***********************************************************/ /* Now try to open .pl1 file */ sprintf( filename, "%s.pl1", cktNameG ) ; fp = TWOPEN( filename, "r", NOABORT ) ; if(!(fp)){ /* no feed data present return false */ return( FALSE ) ; } /* now allocate space for feeds in row */ feed_lengthS = 0 ; while( bufferptr = fgets( buffer, LRECL, fp ) ){ tokens = Ystrparser( bufferptr, " \t\n", &numtokens ) ; if( numtokens != 7 ){ continue ; } if( strncmp( tokens[0], "twfeed", 6 ) == STRINGEQ ){ feed_lengthS += fdWidthG ; row_in_pl1 = atoi( tokens[6] ) ; switch( pl1_case ){ case EQUAL_CASE : feeds_in_rowG[row_in_pl1]++ ; break ; case LESS_ROWS_CASE : row = ROUND( (DOUBLE) row_in_pl1 / (DOUBLE) pl1_rows * (DOUBLE) numRowsG ) ; feeds_in_rowG[row]++ ; break ; case MORE_ROWS_CASE : value = (DOUBLE) row_in_pl1 / (DOUBLE) pl1_rows * (DOUBLE) numRowsG ; start_row = (INT) floor( value ) ; if( start_row <= 0 ){ start_row = 1 ; } end_row = (INT) ceil( value ) ; value = 1.0 / (end_row - start_row + 1) ; for( row = start_row; row <= end_row; row++ ){ smooth[row] += value ; } break ; } /* end switch( pl1_case... */ } } /* end while( bufferptr... */ TWCLOSE( fp ) ; if( pl1_case == MORE_ROWS_CASE ){ /* perform the rounding after all feeds have been accounted*/ for( row = 1; row <= numRowsG; row++ ){ feeds_in_rowG[row] = ROUND( smooth[row] ) ; } Ysafe_free( smooth ) ; } feed_statusL = TRUE ; /* feed data is valid at this point */ M( MSG, NULL, "\nFeed Taper:\n" ) ; for( row = 1; row <= numRowsG; row++ ){ sprintf( YmsgG, "\trow:%4d num explicit feeds:%d\n", row, feeds_in_rowG[row] ) ; M( MSG, NULL, YmsgG ) ; } M( MSG, NULL, "\n\n" ) ; /* now update the configuration */ configuref() ; funccostG = findcostf() ; return( feed_statusL ) ; } /* end read_feed_data */ graywolf-0.1.4+20170307gite1bf319/src/twsc/rmoverlap.c000066400000000000000000000352141305746555600217130ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: rmoverlap.c DESCRIPTION:remove netsegment overlap function. CONTENTS: assgn_channel_to_seg() free_chan_seg() remove_overlap_segment( net ) INT net ; rm_segm_overlap( checkseg , m ) SEGBOXPTR *checkseg ; INT m ; PINBOXPTR depth_first_search( ptr, bptr1, bptr2, aseg, edge ) PINBOXPTR ptr , bptr1 , bptr2 ; SEGBOXPTR aseg , edge ; replace_seg( netptr, oldnode, newnode ) PINBOXPTR netptr , oldnode , newnode ; add_adj( segptr, node ) SEGBOXPTR segptr ; PINBOXPTR node ; check_overlap_at_pin( ptr ) PINBOXPTR ptr ; check_connectivity( net ) INT net ; depth_first_check( ptr , oldedge ) PINBOXPTR ptr ; SEGBOXPTR oldedge ; DATE: Mar 27, 1989 REVISIONS: Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) rmoverlap.c (Yale) version 4.4 12/15/90" ; #endif #endif #include "standard.h" #include "groute.h" /* global variable references */ extern BOOL connectFlagG ; PINBOXPTR depth_first_search() ; /* static definitions */ static INT *segcountS ; static SEGBOXPTR **chan_segS ; assgn_channel_to_seg() { PINBOXPTR ptr1 , ptr2 ; SEGBOXPTR segptr ; INT i , net , *maxcount ; INT channel , topchan , botchan ; segcountS = (INT *)Ysafe_calloc( numChansG+1 , sizeof(INT) ) ; maxcount = (INT *)Ysafe_calloc( numChansG+1 , sizeof(INT) ) ; for( net = 1 ; net <= numnetsG ; net++ ) { topchan = 0 ; botchan = numChansG ; for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ) { ptr1 = segptr->pin1ptr ; ptr2 = segptr->pin2ptr ; if( ptr1->row == ptr2->row ) { if( segptr->switchvalue == swUP ) { segptr->flag = ptr1->row + 1 ; } else if( segptr->switchvalue == swDOWN ) { segptr->flag = ptr1->row ; } else if( ptr1->pinloc >= NEITHER && ptr2->pinloc >= NEITHER ) { if( ptr1->row == numChansG ) { segptr->flag = ptr1->row ; } else { segptr->flag = ptr1->row + 1 ; } } else { segptr->flag = ptr1->row ; } } else { segptr->flag = ( ptr1->row > ptr2->row ) ? ptr1->row : ptr2->row ; } segcountS[ ( channel = segptr->flag ) ]++ ; if( channel > topchan ) topchan = channel ; if( channel < botchan ) botchan = channel ; } for( i = botchan ; i <= topchan ; i++ ) { if( segcountS[i] > maxcount[i] ) { maxcount[i] = segcountS[i] ; } segcountS[i] = 0 ; } } chan_segS = (SEGBOXPTR **)Ysafe_calloc( numChansG+1, sizeof(SEGBOXPTR *) ); for( i = 1 ; i <= numChansG ; i++ ) { chan_segS[i] = (SEGBOXPTR *)Ysafe_calloc( maxcount[i] + 10, sizeof(SEGBOXPTR) ) ; } Ysafe_free( maxcount ) ; } free_chan_seg() { INT i ; for( i = 1 ; i <= numChansG ; i++ ) { Ysafe_free( chan_segS[i] ) ; } Ysafe_free( chan_segS ) ; Ysafe_free( segcountS ) ; } remove_overlap_segment( net ) INT net ; { PINBOXPTR ptr ; SEGBOXPTR segptr ; INT chan , botchan , topchan ; INT checkFlag ; for( ptr = netarrayG[net]->pins ; ptr ; ptr = ptr->next ) { ptr->flag = 1 ; } do { checkFlag = 0 ; for( ptr = netarrayG[net]->pins ; ptr ; ptr = ptr->next ) { if( ptr->flag == 1 ) { check_overlap_at_pin( ptr ) ; checkFlag = 1 ; } } } while( checkFlag == 1 ) ; topchan = 0 ; botchan = numChansG ; for( segptr = netsegHeadG[net]->next ; segptr ; segptr = segptr->next ) { chan = segptr->flag ; if( chan > topchan ) topchan = chan ; if( chan < botchan ) botchan = chan ; chan_segS[chan][ ++segcountS[chan] ] = segptr ; } for( chan = botchan ; chan <= topchan ; chan++ ) { if( segcountS[chan] <= 1 ) { segcountS[chan] = 0 ; continue ; } rm_segm_overlap( chan_segS[chan], segcountS[chan] ); segcountS[chan] = 0 ; } if( check_connectivity( net ) == 0 ) { connectFlagG = FALSE ; } } rm_segm_overlap( checkseg , m ) SEGBOXPTR *checkseg ; INT m ; { SEGBOXPTR aseg , bseg , seg ; PINBOXPTR aptr1 , aptr2 , bptr1 , bptr2 , anode , bnode ; ADJASEGPTR adj ; INT i , j , flag ; do { flag = 0 ; for( i = 1 ; i <= m ; i++ ) { for( j = 1 ; j <= m ; j++ ) { if( i == j ) continue ; aseg = checkseg[i] ; aptr1 = aseg->pin1ptr ; aptr2 = aseg->pin2ptr ; bseg = checkseg[j] ; bptr1 = bseg->pin1ptr ; bptr2 = bseg->pin2ptr ; if( aptr1->xpos >= bptr2->xpos || aptr2->xpos <= bptr1->xpos ) { continue ; } if( aptr1 == bptr1 ) { if( aptr2->xpos <= bptr2->xpos ) { replace_seg( bptr2 , bptr1 , aptr2 ) ; } else { replace_seg( aptr2 , aptr1 , bptr2 ) ; } flag = 1 ; continue ; } else if( aptr2 == bptr2 ) { if( aptr1->xpos <= bptr1->xpos ) { replace_seg( aptr1 , aptr2 , bptr1 ) ; } else { replace_seg( bptr1 , bptr2 , aptr1 ) ; } flag = 1 ; continue ; } if( aptr1->xpos == bptr1->xpos ) { for( adj = aptr1->adjptr->next ; adj ; adj = adj->next){ seg = adj->segptr ; if( seg->pin1ptr == aptr1 && seg->pin2ptr == bptr1|| seg->pin1ptr == bptr1 && seg->pin2ptr == aptr1){ break ; } } if( adj ) { if( aptr2->xpos <= bptr2->xpos ) { replace_seg( bptr2 , bptr1 , aptr2 ) ; } else { replace_seg( aptr2 , aptr1 , bptr2 ) ; } flag = 1 ; continue ; } } if( aptr2->xpos == bptr2->xpos ) { for( adj = aptr2->adjptr->next ; adj ; adj = adj->next){ seg = adj->segptr ; if( seg->pin1ptr == aptr2 && seg->pin2ptr == bptr2|| seg->pin1ptr == bptr2 && seg->pin2ptr == aptr2){ break ; } } if( adj ) { if( aptr1->xpos <= bptr1->xpos ) { replace_seg( aptr1 , aptr2 , bptr1 ) ; } else { replace_seg( bptr1 , bptr2 , aptr1 ) ; } flag = 1 ; continue ; } } bnode = depth_first_search( aptr1, bptr1, bptr2, aseg, 0 ) ; if( bnode ) { anode = aptr1 ; } else { anode = aptr2 ; bnode = depth_first_search( aptr2 , bptr1 , bptr2 , aseg, 0 ); if( bnode == NULL ) { printf("connectivity is lost for net %d\n", aptr1->net); exit(0) ; } } if( aptr1->xpos <= bptr1->xpos ) { if( aptr2->xpos <= bptr2->xpos ) { /* a1 b1 a2 b2 */ if( anode == aptr1 && bnode == bptr1 ) { replace_seg( aptr2 , aptr1 , bptr1 ) ; replace_seg( bptr2 , bptr1 , aptr2 ) ; } else if( anode == aptr2 && bnode == bptr2 ) { replace_seg( aptr1 , aptr2 , bptr1 ) ; replace_seg( bptr1 , bptr2 , aptr2 ) ; } else { replace_seg( aptr1 , aptr2 , bptr1 ) ; replace_seg( bptr2 , bptr1 , aptr2 ) ; } } else { /* a1 b1 b2 a2 */ if( anode == aptr1 && bnode == bptr1 || anode == aptr1 && bnode == bptr2 ) { replace_seg( aptr2 , aptr1 , bptr2 ) ; } else { replace_seg( aptr1 , aptr2 , bptr1 ) ; } } } else { /* b1 < a1 */ if( bptr2->xpos <= aptr2->xpos ) { /* b1 a1 b2 a2 */ if( bnode == bptr1 && anode == aptr1 ) { replace_seg( bptr2 , bptr1 , aptr1 ) ; replace_seg( aptr2 , aptr1 , bptr2 ) ; } else if( bnode == bptr2 && anode == aptr2 ) { replace_seg( bptr1 , bptr2 , aptr1 ) ; replace_seg( aptr1 , aptr2 , bptr2 ) ; } else { replace_seg( bptr1 , bptr2 , aptr1 ) ; replace_seg( aptr2 , aptr1 , bptr2 ) ; } } else { /* a2 < b2 */ /* b1 a1 a2 b2 */ if( bnode == bptr1 && anode == aptr1 || bnode == bptr1 && anode == aptr2 ) { replace_seg( bptr2 , bptr1 , aptr2 ) ; } else { replace_seg( bptr1 , bptr2 , aptr1 ) ; } } } flag = 1 ; } } } while( flag ) ; } PINBOXPTR depth_first_search( ptr , bptr1 , bptr2 , aseg , edge ) PINBOXPTR ptr , bptr1 , bptr2 ; SEGBOXPTR aseg , edge ; { PINBOXPTR next ; SEGBOXPTR seg ; ADJASEGPTR adj ; for( adj = ptr->adjptr->next ; adj ; adj = adj->next ) { seg = adj->segptr ; if( seg == edge || seg == aseg ) { continue ; } if( seg->pin1ptr == ptr ) { next = seg->pin2ptr ; } else { next = seg->pin1ptr ; } if( next == bptr1 || next == bptr2 ) { return( next ) ; } else { next = depth_first_search( next, bptr1, bptr2, aseg, seg ); if( next == bptr1 || next == bptr2 ) { return( next ) ; } } } return( NULL ) ; } replace_seg( netptr, oldnode, newnode ) PINBOXPTR netptr , oldnode , newnode ; { ADJASEGPTR adj, tmpadj ; SEGBOXPTR segptr ; for( adj = netptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( segptr->pin1ptr == oldnode ) { segptr->pin1ptr = newnode ; break ; } else if( segptr->pin2ptr == oldnode ) { segptr->pin2ptr = newnode ; break ; } } for( adj = oldnode->adjptr ; adj->next ; adj = adj->next ) { if( adj->next->segptr == segptr ) { tmpadj = adj->next ; adj->next = adj->next->next ; Ysafe_free( tmpadj ) ; break ; } } add_adj( segptr, newnode ) ; if( netptr->row != newnode->row ) { segptr->switchvalue = nswLINE ; } else if( netptr->pinloc != NEITHER || newnode->pinloc != NEITHER ) { segptr->switchvalue = nswLINE ; } else if( segptr->flag > netptr->row ) { segptr->switchvalue = swUP ; } else { segptr->switchvalue = swDOWN ; } } add_adj( segptr, node ) SEGBOXPTR segptr ; PINBOXPTR node ; { ADJASEG *adjptr ; adjptr = (ADJASEG *)Ysafe_calloc( 1, sizeof(ADJASEG) ) ; adjptr->segptr = segptr ; adjptr->next = node->adjptr->next ; node->adjptr->next = adjptr ; } check_overlap_at_pin( ptr ) PINBOXPTR ptr ; { PINBOXPTR aptr , bptr ; SEGBOXPTR aseg , bseg ; ADJASEGPTR adj , bdj , next_adj , next_bdj ; INT breakFlag ; ptr->flag = 0 ; breakFlag = 0 ; for( adj = ptr->adjptr ; adj->next ; ) { next_adj = adj->next ; aseg = next_adj->segptr ; if( aseg->pin1ptr == ptr ) { aptr = aseg->pin2ptr ; } else { aptr = aseg->pin1ptr ; } for( bdj = adj->next ; bdj->next ; bdj = bdj->next ) { next_bdj = bdj->next ; bseg = next_bdj->segptr ; if( aseg->flag != bseg->flag ) { continue ; } if( bseg->pin1ptr == ptr ) { bptr = bseg->pin2ptr ; } else { bptr = bseg->pin1ptr ; } if( ptr->xpos < aptr->xpos && aptr->xpos < bptr->xpos ) { /* ptr aptr bptr */ /* move the segment between ptr and bptr to be in between aptr and bptr. */ bseg->pin1ptr = aptr ; bdj->next = next_bdj->next ; /* remove the next_bdj from ptr adjacent list */ next_bdj->next = aptr->adjptr->next ; aptr->adjptr->next = next_bdj ; aptr->flag = 1 ; /* add next_bdj to the adjacent list of aptr */ bseg->switchvalue = nswLINE ; break ; } else if( ptr->xpos > aptr->xpos && aptr->xpos > bptr->xpos ) { /* bptr aptr ptr */ /* move the segment between bptr and ptr to be in between bptr and aptr. */ bseg->pin2ptr = aptr ; bdj->next = next_bdj->next ; /* remove the next_bdj from ptr adjacent list */ next_bdj->next = aptr->adjptr->next ; aptr->adjptr->next = next_bdj ; aptr->flag = 1 ; /* add next_bdj to the adjacent list of aptr */ bseg->switchvalue = nswLINE ; break ; } else if( ptr->xpos < bptr->xpos && bptr->xpos < aptr->xpos ) { /* ptr bptr aptr */ /* move the segment between ptr and aptr to be in between bptr and aptr. */ aseg->pin1ptr = bptr ; adj->next = next_adj->next ; /* remove the next_adj from ptr adjacent list */ next_adj->next = bptr->adjptr->next ; bptr->adjptr->next = next_adj ; bptr->flag = 1 ; /* add next_adj to the adjacent list of bptr */ aseg->switchvalue = nswLINE ; breakFlag = 1 ; break ; } else if( ptr->xpos > bptr->xpos && bptr->xpos > aptr->xpos ) { /* aptr bptr ptr */ /* move the segment between aptr and ptr to be in between aptr and bptr. */ aseg->pin2ptr = bptr ; adj->next = next_adj->next ; /* remove the next_adj from ptr adjacent list */ next_adj->next = bptr->adjptr->next ; bptr->adjptr->next = next_adj ; bptr->flag = 1 ; /* add next_adj to the adjacent list of bptr */ aseg->switchvalue = nswLINE ; breakFlag = 1 ; break ; } } if( !breakFlag ) { adj = adj->next ; } else { breakFlag = 0 ; } } } check_connectivity( net ) INT net ; { INT correctness = 1 ; PINBOXPTR ptr , hdptr ; hdptr= netarrayG[net]->pins ; if( !hdptr ) { return(1); } for( ptr = hdptr ; ptr ; ptr = ptr->next ) { ptr->flag = NEW ; } hdptr->flag = OLD ; depth_first_check( hdptr , 0 ) ; for( ptr = hdptr ; ptr ; ptr = ptr->next ) { if( ptr->flag == NEW ) { printf(" the connectivity of net %d after" , net ) ; printf(" the remove_overlap operation was lost\n" ) ; correctness = 0 ; exit(0) ; } } return( correctness ) ; } depth_first_check( ptr , oldedge ) PINBOXPTR ptr ; SEGBOXPTR oldedge ; { PINBOXPTR nextptr ; SEGBOXPTR segptr ; ADJASEGPTR adj ; for( adj = ptr->adjptr->next ; adj ; adj = adj->next ) { segptr = adj->segptr ; if( segptr == oldedge ) { continue ; } if( segptr->pin1ptr == ptr ) { nextptr = segptr->pin2ptr ; } else { nextptr = segptr->pin1ptr ; } if( nextptr->flag == NEW ) { nextptr->flag = OLD ; depth_first_check( nextptr , segptr ) ; } else { printf(" there is a cycle in net %d after" , ptr->net ) ; printf(" the remove overlap function\n" ) ; exit(0) ; } } } graywolf-0.1.4+20170307gite1bf319/src/twsc/rowevener.c000066400000000000000000000120531305746555600217140ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: rowevener.c DESCRIPTION:cell row evener functions. CONTENTS: rowevener() decide_right_most_in_class() dump_rowlength( flag ) int flag ; kick_off_cells_to_next_row( row , length_diff ) int row , length_diff ; borrow_cell_from_other_row( row , last_cell_rite ) int row , last_cell_rite ; DATE: Mar 27, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) rowevener.c (Yale) version 4.7 12/5/91" ; #endif #endif #include "standard.h" #include "groute.h" #include "feeds.h" #include "readpar.h" /* global variables */ INT exact_feedsG ; /* global references */ extern BOOL do_not_even_rowsG ; extern BOOL no_row_lengthsG ; extern BOOL ignore_feedsG ; /* static definitions */ static INT *expect_row_rightS , *expect_row_lengthS ; static INT *cell_kickedS ; rowevener() { INT i , n , row , *addnum , add_to_this_row , total_remaining ; INT row_left , row_right , length_diff , last_cell_rite ; INT expect_extra , total_extra ; INT total_cells_length , total_desire_length , total_feed_length ; CBOXPTR cellptr , lastptr ; total_feed_length = 0 ; total_desire_length = 0 ; total_cells_length = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { n = 0 ; addnum = fdcel_needG[row] ; for( i = 1 ; i <= chan_node_noG ; i++ ) { n += addnum[i] ; } fdcel_addedG[row] = n ; if (!ignore_feedsG) total_feed_length += n * fdWidthG ; row_left = barrayG[row]->bxcenter + barrayG[row]->bleft ; cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; row_right = cellptr->cxcenter + cellptr->tileptr->right ; total_cells_length += row_right - row_left ; total_desire_length += barrayG[row]->desire ; } total_remaining = total_feed_length ; for( row = 1 ; row <= numRowsG ; row++ ) { add_to_this_row = total_remaining / (numRowsG - row + 1) ; total_remaining -= add_to_this_row ; barrayG[row]->desire = barrayG[row]->orig_desire + add_to_this_row ; } exact_feedsG = 1 ; if( !do_not_even_rowsG ) { even_the_rows(!ignore_feedsG,FALSE) ; if( even_rows_maximallyG ){ even_the_rows(!ignore_feedsG,TRUE) ; } } assign_row_to_pin() ; no_row_lengthsG = 0 ; findunlap(1) ; no_row_lengthsG = 0 ; decide_right_most_in_class() ; return ; } decide_right_most_in_class() { INT n , row , row_right ; CBOXPTR cellptr ; n = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; row_right = cellptr->cxcenter + cellptr->tileptr->right ; if( row_rite_classG[row] > n ) { right_most_in_classG[++n] = row_right ; } else if( right_most_in_classG[n] < row_right ) { right_most_in_classG[n] = row_right ; } } } #ifdef NEEDED dump_rowlength( flag ) int flag ; { FILE *fp ; CBOXPTR cellptr ; int row , before , after , rowleft ; if( flag == 0 ) { fp = TWOPEN( "rowlen.dat" , "w", ABORT ) ; } else { fp = TWOPEN( "rowlen.dat" , "a", ABORT ) ; } fprintf(fp," row before_add feednum after_add difference"); fprintf(fp," last_cell_length\n" ) ; for( row = 1 ; row <= numRows ; row++ ) { rowleft = barray[row]->bxcenter + barray[row]->bleft ; cellptr = carray[ pairArray[row][ pairArray[row][0] ] ] ; before = cellptr->cxcenter + cellptr->tileptr->right - rowleft ; after = before + fdcel_added[row] * fdWidth ; fprintf(fp," %3d %10d %7d %8d %10d %10d\n", row , before , fdcel_added[row] , after , after - expect_row_length[row] , cellptr->clength ) ; } TWCLOSE(fp) ; } #endif graywolf-0.1.4+20170307gite1bf319/src/twsc/savewolf.c000066400000000000000000000140761305746555600215350ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: savewolf.c DESCRIPTION:checkpoINT file routines. CONTENTS: savewolf(flag) INT flag ; TW_oldin( fp ) FILE *fp ; DATE: Mar 27, 1989 REVISIONS: Wed Mar 13 13:48:30 CST 1991 - make sure the .blk and the .res file are consistent. Thu Sep 19 16:36:02 EDT 1991 - added more error checking. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) savewolf.c (Yale) version 4.6 9/19/91" ; #endif #endif #include "standard.h" #include "main.h" #include "groute.h" #include "feeds.h" #include "readpar.h" #include "parser.h" #include #if SIZEOF_VOID_P == 64 #define INTSCANSTR "%ld" #else #define INTSCANSTR "%d" #endif savewolf(flag) INT flag ; { FILE *fp ; INT xcenter , ycenter ; INT cell , block , orient ; char filename[64] ; char file1[1024], file2[1024]; CBOXPTR cellptr ; DOUBLE Ycpu_time(); DOUBLE current_time; static DOUBLE last_time = 0.0; if( !flag ) { #ifndef VMS /* make sure another checkpoINT is worthwhile !! */ current_time = Ycpu_time(); if ((current_time - last_time) < 900.0 ) { return; } last_time = current_time; #else if( iterationG % 10 != 0 ) { return ; } #endif } #ifdef VMS sprintf( filename , "%s.sav" , cktNameG ) ; fp = TWOPEN( filename , "w", ABORT ) ; sprintf( filename , "%s.sav;-2" , cktNameG ) ; delete( filename ) ; #else sprintf( filename , "%s.tmp" , cktNameG ) ; fp = TWOPEN( filename , "w", ABORT ) ; #endif fprintf( fp, "%f\n", TG ) ; fprintf( fp, "%d\n", iterationG ) ; fprintf( fp, "%d\n", ffeedsG ) ; fprintf( fp, "1\n" ) ; fprintf( fp, "%f\n", binpenConG ) ; fprintf( fp, "%f\n", roLenConG ) ; /* was cost_scale_factor added for backward compatibility */ fprintf( fp, "%f\n", 1.0 ) ; fprintf( fp, "%d\n", estimate_feedsG ) ; save_feeds( fp ) ; save_control( fp ) ; for( cell = 1 ; cell <= lastpadG ; cell++ ) { cellptr = carrayG[ cell ] ; orient = cellptr->corient ; block = cellptr->cblock ; xcenter = cellptr->cxcenter ; ycenter = cellptr->cycenter ; fprintf( fp , "%d %d %d %d %d\n", cell , block , orient , xcenter , ycenter ) ; } TWCLOSE( fp ) ; #ifndef VMS sprintf(file1, "%s.tmp", cktNameG); sprintf(file2, "%s.sav", cktNameG); rename(file1, file2); #endif return ; } TW_oldin( fp ) FILE *fp ; { INT cell , orient , numfds ; INT block , xcenter , ycenter , dummy ; INT last_cell ; INT number_of_core_cells ; DOUBLE cost_scale_factor ; CBOXPTR ptr ; PINBOXPTR pinptr ; fscanf( fp , "%lf" , &TG ) ; fscanf( fp , INTSCANSTR , &iterationG ) ; fscanf( fp , INTSCANSTR , &numfds ) ; fscanf( fp , INTSCANSTR , &dummy ) ; fscanf( fp , "%lf" , &binpenConG ) ; fscanf( fp , "%lf" , &roLenConG ) ; /* no longer use cost_scale_factor but save for backwards compatibility */ fscanf( fp , "%lf" , &cost_scale_factor ) ; fscanf( fp , INTSCANSTR , &estimate_feedsG ) ; read_feeds( fp ) ; read_control( fp ) ; /* add error checking to catch problems with different number of cells */ last_cell = 0 ; number_of_core_cells = numcellsG - extra_cellsG ; /* ignore the spacer cells */ while( fscanf( fp , " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR " " INTSCANSTR " ", &cell , &block , &orient , &xcenter , &ycenter ) == 5 ) { ptr = carrayG[ cell ] ; if( cell <= number_of_core_cells ) { /* check to make sure block is valid */ if( block < 1 || block > numRowsG ){ sprintf( YmsgG, "block out of bounds for cell:%s\n", ptr->cname ) ; M( ERRMSG, "TW_oldin", YmsgG ) ; M( ERRMSG, NULL,"Restart file does not match block file\n"); M( ERRMSG, NULL, "Must exit\n\n" ) ; TWCLOSE( fpoG ) ; closegraphics() ; YexitPgm(PGMFAIL) ; } ptr->cblock = block ; ptr->corient = orient ; ptr->cxcenter = xcenter ; ptr->cycenter = ycenter ; for( pinptr = ptr->pins; pinptr ; pinptr = pinptr->nextpin ) { pinptr->xpos = pinptr->txpos[ orient/2 ] + xcenter ; pinptr->ypos = pinptr->typos[ orient%2 ] + ycenter ; } last_cell = cell ; } if( strcmp( ptr->cname, "GATE_ARRAY_SPACER" ) == STRINGEQ ){ /* no need to process spacer cells or pads */ break ; } } /* now check to make sure we have the same number of cells */ if( last_cell != number_of_core_cells ){ sprintf( YmsgG, "Wrong number of cells in restart file:%d vs %d in cell file.\n", last_cell, number_of_core_cells ) ; M( ERRMSG, "TW_oldin", YmsgG ) ; M( ERRMSG, NULL, "Fatal Error. Must exit\n\n" ) ; TWCLOSE( fpoG ) ; closegraphics() ; YexitPgm(PGMFAIL) ; } return ; } /* end TW_oldin */ graywolf-0.1.4+20170307gite1bf319/src/twsc/sc_menu000066400000000000000000000022301305746555600211040ustar00rootroot00000000000000# TimberWolfMC menu file. # "@(#) sc_menu (Yale) version 4.8 5/7/91" # # Comments start with a sharp # MENU is a keyword must be capitalized. # Everything in this file is case sensitive. # Fields are separated by commas. # Format: # MENU,menuName - followed by list of entries for this menu # - one on each line. # Normal menu entry - MenuEntry,FunctionNumber # Boolean menu entry - # TrueMenuEntry,FunctionNumber1,FalseMenuEntry,FunctionNumber2,Init # where Init is the initial state and is 1 for True and 0 for False. # # Menu are placed on the screen in a left to right order according # to the order in this file. # MENU,CONTROL Auto Redraw On,1,Auto Redraw Off,2,1 Close Graphics,3 Colors,4 Continue Pgm,5 Dump Graphics,6 FullView,7 Graphics Update On,8,Graphics Update Off,9,1 Redraw,10 Tell Point,11 Translate,12 Zoom,13 Cancel,0 MENU,DRAW Draw Blocks,20,Ignore Blocks,21,1 Draw Stdcells,22,Ignore Stdcells,23,1 Draw Labels,24,Ignore Labels,25,0 Draw Nets,26,Ignore Nets,27,0 Draw Orient,33,Ignore Orient,34,0 Draw Pins,28,Ignore Pins,29,0 Draw Single Net,30 Draw Single Cell Moves,31,Ignore Single Moves,32,0 Cancel,0 graywolf-0.1.4+20170307gite1bf319/src/twsc/seagate.c000066400000000000000000000222311305746555600213100ustar00rootroot00000000000000/* * Copyright (C) 1990-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: seagate.c DESCRIPTION:Sea of gate global routing translator function. CONTENTS: DATE: Apr 7, 1990 REVISIONS: ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) seagate.c (Yale) version 4.7 3/7/91" ; #endif #endif #include "standard.h" #include "groute.h" #include "main.h" #include "readpar.h" #include "pads.h" extern INT vertical_track_pitchG ; extern INT horizontal_track_pitchG ; extern INT global_routing_iterationsG ; extern BOOL new_row_formatG ; extern BOOL min_peak_densityG ; extern BOOL min_total_densityG ; extern BOOL stand_cell_as_gate_arrayG ; seagate_input() { FILE *fp ; CBOXPTR cellptr ; IPBOXPTR imptr ; PINBOXPTR pinptr ; char filename[128], *pin_name, *eqpin_name ; INT left, rite, *Aray, left_most_pitch ; INT coreLeft, coreRite, coreBot, coreTop, cxcenter ; INT x, y, n, m, net, row, cell, padside, templateHeight ; INT left_edge , rite_edge ; INT top_edge , bot_edge , first_pin ; coreBot = INT_MIN ; coreTop = INT_MAX ; m = pairArrayG[1][0] ; cellptr = carrayG[ pairArrayG[1][1] ] ; coreLeft = cellptr->cxcenter + cellptr->tileptr->left ; cellptr = carrayG[ pairArrayG[1][m] ] ; coreRite = cellptr->cxcenter + cellptr->tileptr->right ; for( row = 2 ; row <= numRowsG ; row++ ) { Aray = pairArrayG[row] ; m = Aray[0] ; cellptr = carrayG[ Aray[1] ] ; left = cellptr->cxcenter + cellptr->tileptr->left ; cellptr = carrayG[ Aray[m] ] ; rite = cellptr->cxcenter + cellptr->tileptr->right ; if( left < coreLeft ) coreLeft = left ; if( rite > coreRite ) coreRite = rite ; } for( cell = lastpadG ; cell > numcellsG ; cell-- ) { cellptr = carrayG[cell] ; if( cellptr->padptr ){ padside = cellptr->padptr->padside ; } else { continue ; } switch( padside ) { case T : case MT : case MTT : y = cellptr->cycenter + cellptr->tileptr->bottom ; if( y < coreTop ) coreTop = y ; break ; case B : case MB : case MBB : y = cellptr->cycenter + cellptr->tileptr->top ; if( y > coreBot ) coreBot = y ; break ; default : break ; } } if( coreBot == INT_MIN ) { cellptr = carrayG[ pairArrayG[1][1] ] ; coreBot = cellptr->cycenter + cellptr->tileptr->bottom ; } if( coreTop == INT_MAX ) { cellptr = carrayG[ pairArrayG[numRowsG][1] ] ; coreTop = cellptr->cycenter + cellptr->tileptr->top ; } templateHeight = barrayG[2]->bycenter - barrayG[1]->bycenter ; left_most_pitch = coreRite ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = carrayG[cell] ; cxcenter = cellptr->cxcenter ; for( imptr = cellptr->imptr ; imptr ; imptr = imptr->next ) { if( cellptr->corient <= 1 ) { imptr->xpos = cxcenter + imptr->txpos ; if( imptr->xpos < left_most_pitch ) left_most_pitch = imptr->xpos ; } else { if( cellptr->clength % 2 == 0 ) { imptr->xpos = cxcenter - imptr->txpos ; } else { imptr->xpos = cxcenter - imptr->txpos - 1 ; } if( imptr->xpos < left_most_pitch ) left_most_pitch = imptr->xpos ; } } } sprintf( filename, "%s.sgpar", cktNameG ) ; fp = TWOPEN( filename, "w", ABORT ) ; if( min_peak_densityG ) { /* do nothing */ } else if( min_total_densityG ) { fprintf( fp, "standard_cell\n") ; } else { if( !gate_arrayG || stand_cell_as_gate_arrayG ) { fprintf( fp, "standard_cell\n") ; } } if( global_routing_iterationsG == 0 ) { global_routing_iterationsG = 5 ; } fprintf( fp, "global_routing_iterations %d\n", global_routing_iterationsG); fprintf( fp, "chipLeft %d\n", coreLeft ) ; fprintf( fp, "chipRite %d\n", coreRite ) ; fprintf( fp, "chipTop %d\n", coreTop ) ; fprintf( fp, "chipBot %d\n", coreBot ) ; fprintf( fp, "left_most_pitch %d\n", left_most_pitch ); fprintf( fp, "x_pitch %d\n", vertical_track_pitchG ) ; fprintf( fp, "y_pitch %d\n", horizontal_track_pitchG ) ; fprintf( fp, "channel_capacity 1000\n"); fprintf( fp, "numblocks %d\n", numRowsG + 1 ) ; fprintf( fp, "templateHeight %d\n", templateHeight ) ; fprintf( fp, "vt_offset %d\n", barrayG[1]->bycenter - coreBot ) ; if( pin_layers_givenG ) { fprintf(fp,"pin_layers_given\n"); fprintf(fp,"feedLayer %d\n", feedLayerG ); } if( rowsG > 0 || new_row_formatG ) { fprintf(fp,"new_row_format\n"); } fprintf( fp, "top_of_rows %d\n", barrayG[numRowsG]->bycenter + barrayG[numRowsG]->btop ) ; fprintf( fp, "bot_of_rows %d\n", barrayG[1]->bycenter + barrayG[1]->bbottom ) ; for( row = 1 ; row <= numRowsG ; row++ ) { left_edge = barrayG[row]->bxcenter + barrayG[row]->bleft ; cellptr = carrayG[ pairArrayG[row][ pairArrayG[row][0] ] ] ; rite_edge = cellptr->cxcenter + cellptr->tileptr->right ; bot_edge = barrayG[row]->bycenter + barrayG[row]->bbottom ; top_edge = barrayG[row]->bycenter + barrayG[row]->btop ; fprintf(fp, "%d %d %d %d\n", left_edge , rite_edge , bot_edge , top_edge ) ; } TWCLOSE( fp ) ; sprintf( filename, "%s.sgnet", cktNameG ) ; fp = TWOPEN( filename, "w", ABORT ) ; for( net = 1 ; net <= numnetsG ; net++ ) { first_pin = 1 ; for( pinptr = netarrayG[net]->pins ;pinptr ; pinptr = pinptr->next ) { cellptr = carrayG[pinptr->cell] ; if( cellptr->padptr ){ padside = cellptr->padptr->padside ; } else { padside = 0 ; } if( !padside ) { x = pinptr->xpos ; if( pinptr->eqptr ) { y = barrayG[pinptr->row]->bycenter ; switch( cellptr->corient ) { case 0: case 2: if( pinptr->eqptr->typos > 0 ) { pin_name = pinptr->eqptr->pinname; eqpin_name = pinptr->pinname ; } else { pin_name = pinptr->pinname ; eqpin_name = pinptr->eqptr->pinname; } break ; case 1: case 3: if( pinptr->eqptr->typos > 0 ) { pin_name = pinptr->pinname ; eqpin_name = pinptr->eqptr->pinname; } else { pin_name = pinptr->eqptr->pinname; eqpin_name = pinptr->pinname ; } break ; } } else { y = pinptr->ypos ; pin_name = pinptr->pinname; } } else { x = pinptr->xpos ; y = pinptr->ypos ; pin_name = pinptr->pinname ; } if( first_pin ) { fprintf( fp, "signal %s\n", netarrayG[net]->name ) ; first_pin = 0 ; } if( pinptr->eqptr ) { fprintf(fp, " %s %s %d %d %s\n", pin_name, eqpin_name, x, y, cellptr->cname ) ; } else { fprintf(fp, " %s DUMMY %d %d %s\n", pin_name, x, y, cellptr->cname ) ; } } } TWCLOSE( fp ) ; sprintf( filename, "%s.sgpass", cktNameG ) ; fp = TWOPEN( filename, "w", ABORT ) ; for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = carrayG[cell] ; cxcenter = cellptr->cxcenter ; for( imptr = cellptr->imptr ; imptr ; imptr = imptr->next ) { if( cellptr->corient <= 1 ) { imptr->xpos = cxcenter + imptr->txpos ; } else { if( cellptr->clength % 2 == 0 ) { imptr->xpos = cxcenter - imptr->txpos ; } else { imptr->xpos = cxcenter - imptr->txpos - 1 ; } } } } link_imptr() ; for( row = 1 ; row <= numRowsG ; row++ ) { n = 0; for( imptr = impFeedsG[row]->next ; imptr ; imptr= imptr->next ) n++; fprintf(fp, " blk %d numFeeds %d\n", row+1, n ) ; for( imptr = impFeedsG[row]->next ; imptr ; imptr= imptr->next ) { cellptr = carrayG[imptr->cell] ; if( cellptr->corient == 0 || cellptr->corient == 2 ) { fprintf(fp, "%d %s %s %s\n", imptr->xpos, imptr->pinname, imptr->eqpinname, cellptr->cname ); } else { fprintf(fp, "%d %s %s %s\n", imptr->xpos, imptr->eqpinname, imptr->pinname, cellptr->cname ); } } fprintf(fp, "\n" ); } for( cell = 1 ; cell <= numcellsG ; cell++ ) { cellptr = carrayG[cell] ; imptr = cellptr->imptr ; if( imptr ) { for( ; imptr->next ; imptr = imptr->next ) { if( imptr->next->cell != cell ) break ; } imptr->next = NULL ; } } TWCLOSE( fp ) ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/sort.c000066400000000000000000000075561305746555600207030ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: sort.c DESCRIPTION:various sort functions for quicksort. CONTENTS: compare_cost( a , b ) EDGE_COST *a , *b ; comparegdx( a , b ) CHANGRDPTR *a , *b ; comparetxpos( a , b ) IPBOXPTR *a , *b ; comparenptr( a , b ) FEED_SEG_PTR *a , *b ; comparepinx( a , b ) PINBOXPTR *a , *b ; comparex( a , b ) INT *a , *b ; cmpr_sx( aptr, bptr ) PINBOXPTR *aptr, *bptr ; cmpr_lx( aptr, bptr ) PINBOXPTR *aptr, *bptr ; cmpr_sy( aptr, bptr ) PINBOXPTR *aptr, *bptr ; cmpr_ly( aptr, bptr ) PINBOXPTR *aptr, *bptr ; DATE: Mar 27, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) sort.c (Yale) version 4.3 9/7/90" ; #endif #endif #include "standard.h" #include "groute.h" #include "feeds.h" typedef struct graph_edge_cost { SHORT node1 ; SHORT node2 ; INT cost ; INT channel ; } *EDGE_COST , EDGE_COST_BOX ; compare_cost( a , b ) EDGE_COST *a , *b ; { return( (*a)->cost - (*b)->cost ) ; } INT comparegdx( a , b ) CHANGRDPTR *a , *b ; { return( (*a)->netptr->xpos - (*b)->netptr->xpos ) ; } INT comparetxpos( a , b ) IPBOXPTR *a , *b ; { return( (*a)->txpos - (*b)->txpos ) ; } INT comparenptr( a , b ) FEED_SEG_PTR *a , *b ; { return( (*a)->netptr->xpos - (*b)->netptr->xpos ) ; } comparepinx( a , b ) PINBOXPTR *a , *b ; { return( (*a)->xpos - (*b)->xpos ) ; } INT comparex( a , b ) INT *a , *b ; { return( carrayG[ *a ]->cxcenter - carrayG[ *b ]->cxcenter ) ; } INT cmpr_sx( aptr, bptr ) PINBOXPTR *aptr, *bptr ; { if( (*aptr)->xpos > (*bptr)->xpos ) { return(1) ; } else if( (*aptr)->xpos < (*bptr)->xpos ) { return(-1) ; } else { return(0) ; } } INT cmpr_lx( aptr, bptr ) PINBOXPTR *aptr, *bptr ; { if( (*aptr)->xpos > (*bptr)->xpos ) { return(-1) ; } else if( (*aptr)->xpos < (*bptr)->xpos ) { return(1) ; } else { return(0) ; } } INT cmpr_sy( aptr, bptr ) PINBOXPTR *aptr, *bptr ; { if( (*aptr)->newy > (*bptr)->newy ) { return(1) ; } else if( (*aptr)->newy < (*bptr)->newy ) { return(-1) ; } else { return(0) ; } } INT cmpr_ly( aptr, bptr ) PINBOXPTR *aptr, *bptr ; { if( (*aptr)->newy > (*bptr)->newy ) { return(-1) ; } else if( (*aptr)->newy < (*bptr)->newy ) { return(1) ; } else { return(0) ; } } graywolf-0.1.4+20170307gite1bf319/src/twsc/sortpad.c000066400000000000000000000236041305746555600213600ustar00rootroot00000000000000/* * Copyright (C) 1988-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: sortpad.c DESCRIPTION:This file contains the utility routines to sort pads for the new pad routines. CONTENTS: DATE: Aug 12, 1988 REVISIONS: Sun Jan 20 21:47:52 PST 1991 - ported to AIX. Thu Feb 14 02:45:14 EST 1991 - new pad placement algorithm. Sun Feb 17 21:04:12 EST 1991 - renamed global variables to be the same as placepads. Tue Mar 12 17:09:30 CST 1991 - fixed initialization problem with permute_pads. ----------------------------------------------------------------- */ #ifndef lint static char SccsId[] = "@(#) sortpad.c version 4.6 3/12/91" ; #endif #include #include #include #include /* Forward declarations */ static INT compare_pads(); static INT sort_by_pos(); static void install_pad_groups(); static void permute_pads(); /****************************************************************************** PAD SORTING ROUTINES *******************************************************************************/ sort_pads() { INT i ; /* pad counter */ INT pos ; /* position in place array */ PADBOXPTR pad ; /* current pad */ /* first perform an initial sort to order the pads by side, hierarchy, */ /* and position on the side. */ Yquicksort( &(sortarrayG[1]), totalpadsG,sizeof(PADBOXPTR), compare_pads ); D( "placepads/after_sort", print_pads("pads after initial sort\n",sortarrayG, totalpadsG ) ; ) ; /* Now make sure the pads are permuted correctly */ for( i = 1; i <= totalpadsG;i++ ){ pad = sortarrayG[i]; if( pad->hierarchy == ROOT ){ permute_pads( pad ) ; } } /* NOW INSTALL THE PAD GROUPS IN THEIR PROPER ORDER. There are 2 cases: */ /* CASE I CONTIGUOUS INSURE THAT GROUP REMAIN INTACT */ pos = 1 ; for( i = 1; i <= totalpadsG; i++ ){ pad = sortarrayG[i]; if( pad->hierarchy == ROOT || pad->hierarchy == NONE ){ install_pad_groups( pad, &pos ) ; } } D( "placepads/after_install", print_pads("pads after install\n",placearrayG,numpadsG); ) ; if(!(contiguousG)){ /* CASE II - LEAVES ARE ALIGNED LIKE ORDINARY PADS IF THEY HAVE NO */ /* CONSTRAINTS SUCH AS ORDER OR PERMUTE. **/ Yquicksort( &(placearrayG[1]), numpadsG, sizeof(PADBOXPTR), sort_by_pos ) ; D( "placepads/after_ncontsort", print_pads("pads after noncontiguous sort\n",placearrayG,numpadsG); ) ; } } /* end SortPads */ /* ***************************************************************** */ /*** compare_pads() RETURNS TRUE IF ARG1 > ARG2 BY ITS OWN RULES **/ static INT compare_pads( padptr1, padptr2 ) PADBOXPTR *padptr1, *padptr2 ; { PADBOXPTR pad1, pad2; pad1 = *padptr1 ; pad2 = *padptr2 ; if( pad1->padside != pad2->padside) { return( pad1->padside - pad2->padside ) ; } if( pad1->hierarchy != pad2->hierarchy ){ /*** MOVE ROOTS TO THE BEGINNING OF ARRAY MOVE */ /* LEAVES ARE SEPARATED, ROOTS ARE MERGED **/ if( pad1->hierarchy == SUBROOT ){ return( 1 ) ; } else if( pad2->hierarchy == SUBROOT ){ return( 0 ) ; } else if( pad1->hierarchy == LEAF ){ return( 1 ) ; } else if( pad2->hierarchy == LEAF ){ return( 0 ) ; } } if( pad1->position == pad2->position ){ return( pad1->tiebreak - pad2->tiebreak ) ; } else { return( pad1->position - pad2->position ) ; } } /* end compare_pads */ /* ***************************************************************** */ static INT sort_by_pos( padptr1, padptr2 ) PADBOXPTR *padptr1, *padptr2 ; { PADBOXPTR pad1, pad2; BOOL pad1fixed, pad2fixed ; /* Don't know why this happens, but the sorting algorithm crashes */ /* because padptr1 = padptr2 does not return zero as it should! */ /* ---Tim, 10/14/08 */ if (padptr1 <= padptr2) return 0 ; pad1 = *padptr1 ; pad2 = *padptr2 ; if( pad1->padside != pad2->padside) { return( pad1->padside - pad2->padside ) ; } if( pad1->ordered || pad1->permute ){ pad1fixed = TRUE ; } else { pad1fixed = FALSE ; } if( pad2->ordered || pad2->permute ){ pad2fixed = TRUE ; } else { pad2fixed = FALSE ; } if( pad1fixed && pad2fixed && !(contiguousG) ){ return( 0 ) ; } else if( pad1fixed && contiguousG ){ return( 0 ) ; } else if( pad2fixed && contiguousG ){ return( 1 ) ; } else if( pad1->position == pad2->position ){ return( pad1->tiebreak - pad2->tiebreak ) ; } else { return( pad1->position - pad2->position ) ; } } /* end sort_by_pos */ /* ***************************************************************** */ static void install_pad_groups( pad, position ) PADBOXPTR pad ; INT *position ; { INT i ; /* pad counter */ INT howmany ; /* number of pads in group */ INT initial_position ; /* position of next open place in placearray */ INT sort_by_pos() ; /* how to sort the pads */ PADBOXPTR child ; /* current child */ PADBOXPTR *temparray ; /* temporary array to sort pads */ initial_position = *position ; if( pad->padtype == PADTYPE ){ placearrayG[initial_position] = pad ; *position = ++initial_position ; } else { howmany = pad->children[HOWMANY] ; temparray = (PADBOXPTR *) Yvector_alloc( 1,howmany,sizeof(PADBOXPTR) ) ; for( i = 1 ;i <= howmany ; i++ ){ child = padarrayG[ pad->children[i] ] ; temparray[i] = child ; } /* now sort the subroots or leaves to obey both order constraints */ /* and permutation constraints. Otherwise try to sort by opt. pos.*/ Yquicksort( &(temparray[1]), howmany, sizeof(PADBOXPTR), sort_by_pos ) ; /* now that we have subroots or leaves in correct order */ /* look at next level down */ for( i = 1 ;i <= howmany ; i++ ){ child = temparray[ i ] ; install_pad_groups( child, position ) ; } Yvector_free( temparray, 1, sizeof(PADBOXPTR) ) ; } } /* end install_pad_groups */ /* ***************************************************************** */ static void permute_pads( pad ) PADBOXPTR pad ; { INT tmp ; /* used to reverse permutable pads */ INT j, k ; /* used to reverse pads */ INT i ; /* padcounter */ INT howmany ; /* number of children in current padgroup */ INT max_pos ; /* max. value of the ideal positions of pad in pg */ INT min_pos ; /* min. value of the ideal positions of pad in pg */ INT forward_cost ; /* cost to place pads in current order */ INT bakward_cost ; /* cost to place pads in reverse order */ INT proposed_fpos ; /* proposed uniformly spaced pos in forward order */ INT proposed_bpos ; /* proposed uniformly spaced pos in bakward order */ INT *array ; /* sort the children */ DOUBLE spacing ; /* spacing if we place pads in pg uniformly */ PADBOXPTR child ; /* current child */ if( pad->permute ){ /* first calculate span of padgroup */ howmany = pad->children[HOWMANY] ; ASSERTNRETURN( howmany >= 2,"permute_pads", "Must have at least 2 pads in a padgroup\n"); child = padarrayG[pad->children[1]]; min_pos = child->position ; max_pos = child->position ; for( i = 2; i <= howmany ; i++ ){ child = padarrayG[pad->children[i]]; min_pos = MIN( child->position, min_pos ) ; max_pos = MAX( child->position, max_pos ) ; } /* now find the cost if we evenly space the pads over that region */ spacing = (DOUBLE) (max_pos - min_pos) / (DOUBLE) (howmany - 1) ; forward_cost = 0 ; bakward_cost = 0 ; for( i = 1; i <= howmany ; i++ ){ child = padarrayG[pad->children[i]]; proposed_fpos = min_pos + ROUND( (i - 1) * spacing ) ; proposed_bpos = max_pos - ROUND( (i - 1) * spacing ) ; forward_cost += ABS( child->position - proposed_fpos ) ; bakward_cost += ABS( child->position - proposed_bpos ) ; } if( bakward_cost < forward_cost ) { /* we need to reverse the permutation */ array = pad->children + 1; j = howmany - 1; k = 0; while( k < j ){ tmp = array[j]; array[j--] = array[k]; array[k++] = tmp; } } } /*** NEED TO CHECK THE CHILDREN REGARDLESS OF THE PERMUTABILITY OF THE PARENT ROOT */ for( i = 1; i <= pad->children[HOWMANY]; i++ ){ child = padarrayG[pad->children[i]]; if( child->hierarchy == SUBROOT){ permute_pads( child ) ; } } } /* end permute_pads */ /* ***************************************************************** */ graywolf-0.1.4+20170307gite1bf319/src/twsc/sortpin.c000066400000000000000000000176321305746555600214060ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * Copyright (C) 2015 Tim Edwards * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: sortpin.c DESCRIPTION:pin sorting functions. CONTENTS: sortpin() sortpin1( cell ) INT cell ; sortpin2( cella, cellb ) INT cella, cellb ; shellsort( term , n ) PINBOXPTR term[] ; INT n ; shellsortx( term , n ) PINBOXPTR term[] ; INT n ; shellsorty( term , n ) PINBOXPTR term[] ; INT n ; shellsort_referx( worker , head , n ) FEED_SEG_PTR worker[] ; INT n ; DATE: Mar 27, 1989 REVISIONS: Apr 1, 1990 - rewrote the structure of sortpin to call sortpin1 which is used during a gateswap. Also added new sortpin2 for gateswap between two cells. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) sortpin.c (Yale) version 4.3 9/7/90" ; #endif #endif #include "standard.h" #include "groute.h" #include "feeds.h" static PINBOXPTR *sortArrayS ; /* the normal array for sorting */ static PINBOXPTR *sortArraySwapS ; sortpin() { INT cell ; /* current cell */ INT maxpins ; /* maximum numpins over all pins */ CBOXPTR ptr ; /* current cell */ BOOL pin_groups ; /* true if swappable gates occur */ INT i; /* find the maximum number of pins on a cell for allocation */ /* also see if pin groups exist on any of the cells */ maxpins = INT_MIN ; pin_groups = FALSE ; for( cell = 1; cell <= numcellsG; cell++ ){ ptr = carrayG[cell] ; maxpins = MAX( ptr->numterms, maxpins ) ; if( ptr->num_swap_group > 0 ) { for (i = 0; i < ptr->num_swap_group; i++) { SGLIST *sglistptr; sglistptr = ptr->swapgroups + i; if( sglistptr->num_pin_group > 0 ){ pin_groups = TRUE ; break; } } } } sortArrayS = (PINBOXPTR *) Ysafe_malloc( (maxpins+2)*sizeof(PINBOXPTR) ); for( cell = 1 ; cell <= numcellsG ; cell++ ) { sortpin1( cell ) ; } if( pin_groups ){ /* we we have swappable gates we need to create second array */ /* and leave first one allocated */ sortArraySwapS = (PINBOXPTR *) Ysafe_malloc( (maxpins+2)*sizeof(PINBOXPTR) ); } else { /* in the normal case we are done with sorting free array */ Ysafe_free( sortArrayS ) ; } } /* end sortpin */ /* sort the pins of a single cell by net */ sortpin1( cell ) INT cell ; { INT j , n ; CBOXPTR ptr ; PINBOXPTR pinptr ; ptr = carrayG[ cell ] ; if( ptr->numterms == 0 ) { return ; } n = 0 ; for( pinptr = ptr->pins ; pinptr; pinptr = pinptr->nextpin ) { sortArrayS[ ++n ] = pinptr ; } shellsort( sortArrayS , n ) ; sortArrayS[ n + 1 ] = PINNULL ; ptr->pins = sortArrayS[ 1 ] ; for( j = 1 ; j <= n ; j++ ) { sortArrayS[j]->nextpin = sortArrayS[j+1] ; } return ; } /* end sortpin1 */ sortpin2( cella, cellb ) INT cella, cellb ; { INT j ; /* counter */ INT numpins_a ; /* number pins of cell a */ INT numpins_b ; /* number pins of cell b */ CBOXPTR aptr ; /* pointer to cell a info */ CBOXPTR bptr ; /* pointer to cell b info */ PINBOXPTR pin ; /* the current pin */ aptr = carrayG[ cella ] ; bptr = carrayG[ cellb ] ; numpins_a = 0 ; numpins_b = 0 ; /* first set pins currently in cell to correct sort arrays */ /* sortArrayS holds all the pins of cell a */ /* sortArraySwap holds all the pins of cell b */ for( pin = aptr->pins ; pin; pin = pin->nextpin ) { if( pin->cell == cella ){ sortArrayS[ ++numpins_a ] = pin ; } else if( pin->cell == cellb ){ sortArraySwapS[ ++numpins_b ] = pin ; } else { fprintf( stderr, "Trouble with sortpin2\n" ) ; } } for( pin = bptr->pins ; pin; pin = pin->nextpin ) { if( pin->cell == cella ){ sortArrayS[ ++numpins_a ] = pin ; } else if( pin->cell == cellb ){ sortArraySwapS[ ++numpins_b ] = pin ; } else { fprintf( stderr, "Trouble with sortpin2\n" ) ; } } /* now sort cell a's pins */ shellsort( sortArrayS , numpins_a ) ; sortArrayS[ numpins_a + 1 ] = PINNULL ; aptr->pins = sortArrayS[ 1 ] ; for( j = 1 ; j <= numpins_a ; j++ ) { sortArrayS[j]->nextpin = sortArrayS[j+1] ; } /* now sort cell b's pins */ shellsort( sortArraySwapS , numpins_b ) ; sortArraySwapS[ numpins_b + 1 ] = PINNULL ; bptr->pins = sortArraySwapS[ 1 ] ; for( j = 1 ; j <= numpins_b ; j++ ) { sortArraySwapS[j]->nextpin = sortArraySwapS[j+1] ; } return ; } /* end sortpin2 */ shellsort( term , n ) PINBOXPTR term[] ; INT n ; { PINBOXPTR ptr ; INT incr , i , j ; for( incr = n / 2 ; incr > 0 ; incr /= 2 ) { for( i = incr + 1 ; i <= n ; i++ ) { for( j = i - incr ; j > 0 && (term[j]->net > term[j+incr]->net) ; j -= incr ) { ptr = term[j] ; term[j] = term[j+incr] ; term[j+incr] = ptr ; } } } } shellsortx( term , n ) PINBOXPTR term[] ; INT n ; { PINBOXPTR pin ; INT incr , i , j ; for( incr = (n+1)/ 2 ; incr > 0 ; incr /= 2 ) { for( i = incr ; i <= n ; i++ ) { for( j = i - incr ; j >= 0 && (term[j]->xpos > term[j+incr]->xpos) ; j -= incr ) { pin = term[j] ; term[j] = term[j+incr] ; term[j+incr] = pin ; } } } } shellsorty( term , n ) PINBOXPTR term[] ; INT n ; { PINBOXPTR pin ; INT incr , i , j ; for( incr = (n+1)/ 2 ; incr > 0 ; incr /= 2 ) { for( i = incr ; i <= n ; i++ ) { for( j = i - incr ; j >= 0 && term[j]->newy > term[j+incr]->newy ; j -= incr ) { pin = term[j] ; term[j] = term[j+incr] ; term[j+incr] = pin ; } } } } shellsort_referx( worker , head , n ) FEED_SEG_PTR worker[] ; INT n ; { FEED_SEG_PTR ptr ; INT incr , i , j , mhead , endi , x1 , x2 ; mhead = head - 1 ; for( incr = n / 2 ; incr > 0 ; incr /= 2 ) { endi = n + mhead ; for( i = mhead + incr + 1 ; i <= endi ; i++ ) { for( j = i - incr ; j > mhead ; j -= incr ) { if( worker[j]->refer ) { /* not a steiner poINT */ x1 = worker[j]->refer->xpos ; } else { x1 = worker[j]->netptr->xpos ; } if( worker[j+incr]->refer ) { /* not a steiner poINT */ x2 = worker[j+incr]->refer->xpos ; } else { x2 = worker[j+incr]->netptr->xpos ; } if( x1 > x2 ) { ptr = worker[j] ; worker[j] = worker[j+incr] ; worker[j+incr] = ptr ; } } } } } graywolf-0.1.4+20170307gite1bf319/src/twsc/src_list000066400000000000000000000013611305746555600213010ustar00rootroot00000000000000acceptt.c buildimp.c cell_width.c cglbroute.c changrid.c coarseglb.c config.h configpads.c configure.c countf.c crossbus.c debug.c debug2.c dimbox.c feedest.c feeds.h findcost.c findcostf.c findrcost.c findunlap.c gateswap.c globe.c globroute.c graphics.c groute.h main.c main.h menus.h mergeseg.c netgraph.c newtemp.c outcm.c outpins.c outpins1.c output.c overlap.c pads.h parser.c parser.h paths.c placepads.c readblck.c readblck.h readcell.c readcell.h readcell.l readcell.y readnets.h readnets.l readnets.y readpar.c readpar.h reconfig.c rmoverlap.c rowevener.c savewolf.c sc_menu seagate.c sort.c sortpad.c sortpin.c standard.h steiner.c uc0.c ucxx1.c ucxx2.c ucxxglb.h ucxxo1.c ucxxo2.c ucxxp.c uloop.c unlap.c upair.c urcost.c utemp.c xpickint.c graywolf-0.1.4+20170307gite1bf319/src/twsc/standard.h000066400000000000000000000212141305746555600215040ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) standard.h (Yale) version 4.16 4/2/92" FILE: standard.h DESCRIPTION:TimberwolfSC main insert file. CONTENTS: DATE: Mar 27, 1989 REVISIONS: Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. Thu Dec 20 00:05:40 EST 1990 - made timing values doubles for more accuracy. Thu Jan 24 16:34:51 PST 1991 - added user initialization. Fri Mar 22 15:20:24 CST 1991 - added SHORT_LONG definitions for large designs. Tue Mar 26 11:33:47 EST 1991 - added NO_FEED_INSTANCES conditional compile. ----------------------------------------------------------------- */ #ifndef YSTANDARD_H #define YSTANDARD_H #ifdef VMS #define lINT #endif /* a cheap way of avoiding the inclusions of the sccs stuff for VMS systems */ #include #ifndef NO_FEED_INSTANCES #define FEED_INSTANCES /* ---selection of this keyword will cause */ /* each feed-through cell to have */ /* a distinct (instance) name */ #endif /* NO_FEED_INSTANCES */ /* I/O macros */ #include /* Pin list includes an embedded hash table */ #include #ifdef MAIN_VARS #define EXTERN #else #define EXTERN extern #endif /* ***********LEAVE THE BELOW UNCHANGED *************************** */ /* remove graphics lines of code if compile switch is on */ #ifdef NOGRAPHICS #define G(x_xz) #else #define G(x_xz) x_xz #endif /* NOGRAPHICS */ #define MAXINT 0x7FFFFFFF #define ALLOC(type) ( (type *) Ysafe_malloc ( sizeof(type) ) ) #define SetBin(x) (( (TrybinG=((x)-binOffstG)/binWidthG)<0 ) ? 0 : \ ((TrybinG>numBinsG) ? numBinsG : TrybinG )) #ifdef USER_DEFS /* allow user to add custom interface */ #define USER_INITIALIZATION() User_initialization() #define USER_NEXT_METER() User_next_meter() #define USER_INCR_METER() User_incr_meter() #define USER_SEND_VALUE( a ) User_send_value( a ) #else /* NO USER DEFINITIONS */ #define USER_INITIALIZATION() #define USER_NEXT_METER() #define USER_INCR_METER() #define USER_SEND_VALUE( a ) #endif /* USER_DEFINITIONS */ #define CULLNULL (CBOXPTR) NULL #define PINNULL (PINBOXPTR) NULL #define DIMNULL (DBOXPTR) NULL #define TILENULL (TIBOXPTR) NULL #define LEFT_MOST 0 #define RITE_MOST 1 #define FEED_FLAG 2 #define NOT_DONE -2 #define NO_PINS -1000 #define BIG_NUMBER 32000 #define TW_PRIME 49999 #define TW_PRIME2 1009 #define GATE_ARRAY_MAGIC_CONSTANT -1000001 /* used to describe pin location */ #define LEFTCELL 1 /* was -2 */ #define BOTCELL 2 /* was -1 */ #define NEITHER 3 /* was 0 */ #define TOPCELL 4 /* was 1 */ #define RITECELL 5 /* was 2 */ #define PINLOC_OFFSET 3 /* diff needed to make field positive */ typedef struct blockbox { INT bxcenter ; INT bycenter ; INT bleft ; INT bright ; INT desire ; INT blength ; INT oldsize ; INT newsize ; INT orig_desire ; INT bbottom ; INT btop ; INT bheight ; SHORT bclass ; SHORT borient ; } *BBOXPTR, BBOX ; typedef struct glistbox { /* generic list */ union { INT net ; /* make code easier to read */ INT path ; INT cell ; } p ; struct glistbox *next ; } GLISTBOX , *GLISTPTR ; typedef struct equiv_box { char *pinname ; char unequiv ; char txoff ; SHORT_LONG typos ; } EQ_NBOX , *EQ_NBOXPTR ; typedef struct pinbox { struct pinbox *next ; /* next pin on this net */ struct pinbox *nextpin ; /* next pin on this cell */ char *pinname ; INT terminal ; INT xpos ; /* global positions */ INT ypos ; INT newx ; INT newy ; SHORT_LONG txpos[2] ; /* cell relative position */ SHORT_LONG typos[2] ; /* cell relative position */ INT cell ; INT net ; SHORT row ; char pinloc ; char flag ; struct adjacent_seg *adjptr ; struct equiv_box *eqptr ; } *PINBOXPTR, PINBOX ; typedef struct pathbox { INT path_len ; /* bound on the calculated half perim */ INT new_path_len ; /* new path */ INT priority ; INT upper_bound ; INT lower_bound ; GLISTPTR nets ; struct pathbox *next ; /* build a list first then array for speed */ } PATHBOX , *PATHPTR ; typedef struct tilebox { SHORT_LONG left ; SHORT_LONG right ; SHORT_LONG bottom ; SHORT_LONG top ; } *TIBOXPTR, TIBOX ; // Each cell defines any number of swap groups. // Each swap group has a record containing the // swap group number and the number of pin groups // in the cell belonging to that swap group. // // The most common uses are clock/buffer tree // optimization and scan chain optimization. // For these, num_pin_group is normally 1. // // Note that this record does not specify // where in the swap group to find the pin // group(s). typedef struct swapgrouplist { SHORT swap_group ; SHORT num_pin_group ; } *SGLISTPTR, SGLIST ; typedef struct cellbox { char *cname ; char corient ; char orflag ; char ECO_flag ; INT cxcenter ; INT cycenter ; INT border ; INT cclass ; UNSIGNED_INT cbclass[8] ; SHORT_LONG cheight ; SHORT_LONG clength ; SHORT cblock ; SHORT numterms ; SHORT num_swap_group ; SGLISTPTR swapgroups ; GLISTPTR paths ; /* timing paths of a cell */ struct pad_rec *padptr; struct fencebox *fence; struct imp_box *imptr ; PINBOXPTR pins ; /* the pins of the cell */ TIBOXPTR tileptr ; } *CBOXPTR, CBOX ; typedef struct fencebox { INT min_block ; INT max_block ; INT min_xpos ; INT max_xpos ; struct fencebox *next_fence ; } *FENCEBOXPTR, FENCEBOX ; typedef struct dimbox { PINBOXPTR pins ; /* pins of the net */ char *name ; char dflag ; char feedflag ; char ignore ; INT xmin ; INT newxmin ; INT xmax ; INT newxmax ; INT ymin ; INT newymin ; INT ymax ; INT newymax ; SHORT Lnum ; SHORT newLnum ; SHORT Rnum ; SHORT newRnum ; SHORT Bnum ; SHORT newBnum ; SHORT Tnum ; SHORT newTnum ; SHORT numpins ; GLISTPTR paths ; /* paths which this net belongs */ INT newhalfPx ; /* new half perimeter bounding box */ INT newhalfPy ; /* new half perimeter: y portion */ INT halfPx ; /* current half perimeter bounding box */ INT halfPy ; /* current half perimeter: y portion */ } *DBOXPTR, DBOX ; typedef struct hash { char *hname ; INT hnum ; struct hash *hnext ; } HASHBOX, *HASHPTR ; typedef struct binbox { INT left ; INT right ; INT *cell ; INT penalty ; INT nupenalty ; } BINBOX, *BINPTR ; typedef struct pin_list { /* list of pins */ PINBOXPTR swap_pin ; struct pin_list *next ; /* Next pin in pin group */ struct pin_list *next_grp ; /* Next pin group in same cell */ } PINLIST, *PINLISTPTR ; typedef struct swapbox { /* list of list of pins to be swapped */ INT num_pin_grps ; YHASHPTR pin_grp_hash ; } SWAPBOX ; /* ****************** GLOBALS ************************** */ /* THE MAJOR PARTS OF THE DATA STRUCTURES */ EXTERN CBOXPTR *carrayG ; EXTERN DBOXPTR *netarrayG ; EXTERN PINBOXPTR *tearrayG ; EXTERN BBOXPTR *barrayG ; EXTERN BINBOX ***binptrG ; EXTERN PATHPTR *patharrayG ; /* array of timing paths */ EXTERN DOUBLE vertical_path_weightG ; EXTERN DOUBLE horizontal_path_weightG ; EXTERN DOUBLE vertical_wire_weightG ; /* the configuration */ EXTERN INT numcellsG ; EXTERN INT numtermsG ; EXTERN INT numnetsG ; EXTERN INT numpadgrpsG ; EXTERN INT lastpadG ; EXTERN INT maxtermG ; EXTERN INT numRowsG ; EXTERN INT numChansG ; EXTERN INT numpathsG ; EXTERN INT numBinsG ; EXTERN INT binWidthG ; EXTERN INT binOffstG ; EXTERN INT TotRegPinsG ; EXTERN INT implicit_feed_countG ; /* for the penalties */ EXTERN INT TrybinG ; EXTERN INT binpenalG ; EXTERN INT funccostG ; EXTERN INT newbinpenalG ; EXTERN INT newrowpenalG ; EXTERN INT penaltyG ; EXTERN INT rowpenalG ; EXTERN INT timingcostG ; EXTERN DOUBLE binpenConG ; EXTERN DOUBLE roLenConG ; EXTERN DOUBLE timeFactorG ; #undef EXTERN /* *********************** PROTOTYPES FOR TWSC ******************** */ extern init_table( P1(void) ) ; extern BOOL acceptt( P3(INT d_wire,INT d_time,INT d_penal) ) ; extern BOOL accept_greedy( P3(INT d_wire,INT d_time,INT d_penal) ) ; #endif /* YSTANDARD_H */ graywolf-0.1.4+20170307gite1bf319/src/twsc/steiner.c000066400000000000000000000271551305746555600213620ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: steiner.c DESCRIPTION:steiner tree functions. CONTENTS: steiner() make_net_Tree( startptr ) PINBOXPTR startptr ; redo_steiner() DATE: Mar 27, 1989 REVISIONS: Sat Dec 15 22:08:21 EST 1990 - modified pinloc values so that it will always be positive. Sun Jan 20 21:47:52 PST 1991 - ported to AIX. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) steiner.c (Yale) version 4.7 1/20/91" ; #endif #endif #include "standard.h" #include "groute.h" #include "feeds.h" /* global variables */ INT Max_numPinsG ; INT *add_st_flagG ; INT enough_built_in_feedG ; /* global references */ extern INT *rowfeed_penaltyG ; extern BOOL absolute_minimum_feedsG ; SEGBOXPTR makeseg() ; /* static definitions */ static PINBOXPTR *vertexS ; static INT **costS , *lowcostS , *closestS , *components , max_pinS ; steiner() { DBOXPTR dptr ; PINBOXPTR netptr ; SEGBOXPTR segptr ; INT net , row , i ; max_pinS = 0 ; for( net = 1 ; net <= numnetsG ; net++ ) { if( netarrayG[net]->numpins > max_pinS ) { max_pinS = netarrayG[net]->numpins ; } } max_pinS++ ; Max_numPinsG = 2 * (max_pinS + 3 * numRowsG) ; netsegHeadG = (SEGBOXPTR *)Ysafe_malloc( ( numnetsG+1 ) * sizeof( SEGBOXPTR ) ) ; steinerHeadG = (PINBOXPTR *)Ysafe_malloc( ( numnetsG+1 ) * sizeof( PINBOXPTR ) ) ; for( net = 1 ; net <= numnetsG ; net++ ) { netsegHeadG[net] = (SEGBOXPTR)Ysafe_calloc( 1, sizeof(SEGBOX) ) ; steinerHeadG[net]= (PINBOXPTR)Ysafe_calloc( 1, sizeof(PINBOX) ) ; } costS = (INT **)Ysafe_malloc( max_pinS * sizeof(INT *) ) ; for( i = 1 ; i < max_pinS ; i++ ) { costS[i] = (INT *)Ysafe_malloc( max_pinS * sizeof( INT ) ) ; } vertexS = (PINBOXPTR *)Ysafe_malloc( max_pinS * sizeof( PINBOXPTR ) ) ; lowcostS = (INT *)Ysafe_calloc( max_pinS, sizeof(INT) ) ; closestS = (INT *)Ysafe_calloc( max_pinS, sizeof(INT) ) ; components = (INT *)Ysafe_malloc( max_pinS * sizeof(INT) ) ; for( net = 1 ; net <= numnetsG ; net++ ) { dptr = netarrayG[net] ; if(!(dptr->pins)){ continue ; } switch( dptr->numpins ) { case 0 : break ; case 1 : break ; case 2 : netptr = dptr->pins ; makeseg( netptr , netptr->next ) ; break ; default : make_net_Tree( dptr->pins ) ; update_feedest( net ) ; break ; } } #ifdef CARL_NEW add_st_flagG = (int *)Ysafe_malloc( ( numChans + 1 ) * sizeof(int) ) ; if( !absolute_minimum_feeds ) { enough_built_in_feed = 1 ; for( row = 1 ; row <= numRows ; row++ ) { add_st_flagG[row] = TRUE ; if( FeedInRow[row] == 0 ) { enough_built_in_feed = 0 ; } } } else { enough_built_in_feed = 0 ; for( row = 1 ; row <= numRows ; row++ ) { add_st_flagG[row] = FALSE ; } } #else add_st_flagG = (INT *)Ysafe_malloc( ( numChansG + 1 ) * sizeof(INT) ) ; if( !absolute_minimum_feedsG ) { enough_built_in_feedG = TRUE ; for( row = 1 ; row <= numRowsG ; row++ ) { if( FeedInRowG[row] > 0 ) { add_st_flagG[row] = TRUE ; } else { add_st_flagG[row] = FALSE ; enough_built_in_feedG = FALSE ; } } } else { enough_built_in_feedG = FALSE ; for( row = 1 ; row <= numRowsG ; row++ ) { add_st_flagG[row] = FALSE ; } } #endif for( net = 1 ; net <= numnetsG ; net++ ) { dptr = netarrayG[net] ; if( dptr->numpins <= 2 ) { continue ; } for( netptr = dptr->pins ; netptr ; netptr = netptr->next ) { netptr->newy = 3 * netptr->row + netptr->pinloc - PINLOC_OFFSET ; } for( netptr = dptr->pins ; netptr ; netptr = netptr->next ) { if( netptr->adjptr->next->next != NULL ) { mergeseg( netptr ) ; } } for( segptr = netsegHeadG[net] ; segptr->next ; segptr = segptr->next ) { segptr->next->prev = segptr ; } } #define EVEN_ROW #ifndef EVEN_ROW for( i = 1 ; i < max_pinS ; i++ ) { Ysafe_free( costS[i] ) ; } Ysafe_free( costS ) ; Ysafe_free( vertexS ) ; Ysafe_free( lowcostS ) ; Ysafe_free( closestS ) ; Ysafe_free( components ) ; Ysafe_free( add_st_flagG ) ; #endif } make_net_Tree( startptr ) PINBOXPTR startptr ; { PINBOXPTR netptr , iptr , jptr ; INT i , j , k , n , c , row , irow , jrow ; INT x_diff , min_costS , first_new ; n = 0 ; for( netptr = startptr ; netptr ; netptr = netptr->next ) { vertexS[ ++n ] = netptr ; } for( i = 1 ; i <= n ; i++ ) { costS[i][i] = INFINITY ; iptr = vertexS[i] ; for( j = i+1 ; j <= n ; j++ ) { jptr = vertexS[j] ; x_diff = ABS( iptr->xpos - jptr->xpos ) ; if( iptr->row == jptr->row ) { if( iptr->pinloc == NEITHER && jptr->pinloc == NEITHER ) { costS[i][j] = x_diff ; } else { if( ABS( iptr->pinloc - jptr->pinloc ) <= 1 ) { costS[i][j] = x_diff * 5 / 2 ; } else { costS[i][j] = x_diff * 5 / 2 + rowfeed_penaltyG[iptr->row] ; } } } else { c = 0 ; irow = iptr->row ; jrow = jptr->row ; if( irow < jrow ) { for( row = irow + 1 ; row < jrow ; row++ ) { c += rowfeed_penaltyG[row] ; } } else { for( row = jrow + 1 ; row < irow ; row++ ) { c += rowfeed_penaltyG[row] ; } } if( iptr->pinloc == NEITHER && jptr->pinloc == NEITHER ) { if( x_diff < average_feed_sepG ) { costS[i][j] = x_diff + c ; } else { costS[i][j] = x_diff + c + ( rowfeed_penaltyG[irow] + rowfeed_penaltyG[jrow] ) / 2 ; } } else { if( irow < jrow ) { if( iptr->pinloc >= NEITHER && jptr->pinloc <= NEITHER ) { if( jptr->pinloc <= NEITHER ) { costS[i][j] = x_diff * 5 / 2 + c ; } else { costS[i][j] = x_diff * 5 / 2 + c + rowfeed_penaltyG[jrow] ; } } else { if( jptr->pinloc <= NEITHER ) { costS[i][j] = x_diff * 5 / 2 + c + rowfeed_penaltyG[irow] ; } else { costS[i][j] = x_diff * 5 / 2 + c + rowfeed_penaltyG[irow] + rowfeed_penaltyG[jrow] ; } } } else { if( jptr->pinloc >= NEITHER && iptr->pinloc <= NEITHER ) { if( iptr->pinloc <= NEITHER ) { costS[i][j] = x_diff * 5 / 2 + c ; } else { costS[i][j] = x_diff * 5 / 2 + c + rowfeed_penaltyG[irow] ; } } else { if( iptr->pinloc <= NEITHER ) { costS[i][j] = x_diff * 5 / 2 + c + rowfeed_penaltyG[jrow] ; } else { costS[i][j] = x_diff * 5 / 2 + c + rowfeed_penaltyG[irow] + rowfeed_penaltyG[jrow] ; } } } } } costS[j][i] = costS[i][j] ; } } /* **************************************************************** * suppose V = { 1 , 2 , ... , n } , initially U is set to {1} * * At each step, it finds a shortest edge ( u, v ) that connects * * U and V-U and then adds v , the vertexS in V-U , to U. * * It repeats this step until U = V. * * This is the Prim's algorithm for Minimum Spanning Tree. * ******************************************************************/ components[1] = OLD ; for( i = 2 ; i <= n ; i++ ) { lowcostS[i] = costS[1][i] ; closestS[i] = 1 ; components[i] = NEW ; /* initialize with only vertexS 1 in the set U. * * closestS[i] gives the vertexS in U that is currently closestS * * to vertexS i in V-U . lowcostS[i] gives the costS of the edge * * ( i , closestS[i] ). */ } for( i = 2 ; i <= n ; i++ ) { for( j = 2 ; j <= n ; j++ ) { if( components[j] ) { min_costS = lowcostS[j] ; first_new = k = j ; break ; } } for( j++ ; j <= n ; j++ ) { if( components[j] && lowcostS[j] < min_costS ) { min_costS = lowcostS[j] ; k = j ; } } c = closestS[k] ; /* for vertexS k in V-U , c is the closestS vertexS in U to k */ components[k] = OLD ; makeseg( vertexS[c] , vertexS[k] ) ; for( j = first_new ; j <= n ; j++ ) { if( components[j] && costS[k][j] < lowcostS[j] ) { lowcostS[j] = costS[k][j] ; closestS[j] = k ; } } } /* ******************* Prim's algorithm ends ******************** */ } #ifdef EVEN_ROW redo_steiner() { INT net , i ; DBOXPTR dptr ; PINBOXPTR netptr , nextptr ; ADJASEGPTR adjptr , saveptr ; SEGBOXPTR segptr , nextseg ; for( net = 1 ; net <= numnetsG ; net++ ) { dptr = netarrayG[net] ; if( dptr->numpins <= 1 ) { continue ; } for( segptr = netsegHeadG[net]->next ; segptr ; segptr = nextseg ) { nextseg = segptr->next ; Ysafe_free( segptr ) ; } netsegHeadG[net]->next = NULL ; for( netptr = dptr->pins ; netptr ; netptr = netptr->next ) { for( adjptr = netptr->adjptr->next ; adjptr ; adjptr = saveptr ) { saveptr = adjptr->next ; Ysafe_free( adjptr ) ; } netptr->adjptr->next = NULL ; } for( netptr = steinerHeadG[net]->next ; netptr ; netptr = netptr->next ) { for( adjptr = netptr->adjptr->next ; adjptr ; adjptr = saveptr ) { saveptr = adjptr->next ; Ysafe_free( adjptr ) ; } netptr->adjptr->next = NULL ; } for( netptr = steinerHeadG[net]->next ; netptr ; netptr = nextptr ) { nextptr = netptr->next ; Ysafe_free( netptr ) ; } steinerHeadG[net]->next = NULL ; } re_estimate_feed_penalty() ; for( net = 1 ; net <= numnetsG ; net++ ) { dptr = netarrayG[net] ; switch( dptr->numpins ) { case 0 : break ; case 1 : break ; case 2 : netptr = dptr->pins ; makeseg( netptr , netptr->next ) ; break ; default : make_net_Tree( dptr->pins ) ; break ; } } for( net = 1 ; net <= numnetsG ; net++ ) { dptr = netarrayG[net] ; if( dptr->numpins <= 1 ) { continue ; } else if( dptr->numpins == 2 ) { netsegHeadG[net]->next->prev = netsegHeadG[net] ; continue ; } for( netptr = dptr->pins ; netptr ; netptr = netptr->next ) { netptr->newy = 3 * netptr->row + netptr->pinloc - PINLOC_OFFSET ; } for( netptr = dptr->pins ; netptr ; netptr = netptr->next ) { if( netptr->adjptr->next->next != NULL ) { mergeseg( netptr ) ; } } for( segptr = netsegHeadG[net] ; segptr->next ; segptr = segptr->next ) { segptr->next->prev = segptr ; } } for( i = 1 ; i < max_pinS ; i++ ) { Ysafe_free( costS[i] ) ; } Ysafe_free( costS ) ; Ysafe_free( vertexS ) ; Ysafe_free( lowcostS ) ; Ysafe_free( closestS ) ; Ysafe_free( components ) ; Ysafe_free( add_st_flagG ) ; free_up_feedest_malloc() ; } #endif graywolf-0.1.4+20170307gite1bf319/src/twsc/uc0.c000066400000000000000000000056671305746555600204040ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: uc0.c DESCRIPTION:orientation change. CONTENTS: uc0( a , newaor ) INT a , newaor ; DATE: Mar 27, 1989 REVISIONS: Mon Aug 12 17:01:03 CDT 1991 - changed timing ASSERTIONS to D( ) constructs to speed execution time during debug mode. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) uc0.c (Yale) version 4.6 2/23/92" ; #endif #endif #include "standard.h" #include uc0( a , newaor ) INT a , newaor ; { CBOXPTR acellptr ; PINBOXPTR antrmptr ; INT cost , truth ; INT newtimepenal ; acellptr = carrayG[ a ] ; antrmptr = acellptr->pins ; term_newpos( antrmptr, acellptr->cxcenter, acellptr->cycenter, newaor ); cost = funccostG ; clear_net_set() ; /* reset set to mark nets that have changed position */ /* dimbox routines mark the nets that have changed */ new_dbox( antrmptr , &cost ) ; newtimepenal = timingcostG ; newtimepenal += calc_incr_time( a ) ; D( "twsc/check_timing", ASSERT( dcalc_full_penalty(newtimepenal),"uc0","time problem") ; ) ; truth = acceptt( funccostG - cost, timingcostG - newtimepenal, 0 ) ; if( truth ) { dbox_pos( antrmptr ) ; update_time( a ) ; acellptr->corient = newaor ; funccostG = cost ; timingcostG = newtimepenal ; G( graphics_cell_update( a ) ) ; } else { G( graphics_cell_attempt( a ) ) ; } return ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/ucxx1.c000066400000000000000000000115271305746555600207550ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: ucxx1.c DESCRIPTION:single cell move. CONTENTS: ucxx1( bxcenter , bycenter ) INT bxcenter , bycenter ; DATE: Mar 27, 1989 REVISIONS: Mon Aug 12 17:01:03 CDT 1991 - changed timing ASSERTIONS to D( ) constructs to speed execution time during debug mode. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) ucxx1.c (Yale) version 4.7 2/23/92" ; #endif #endif #include "ucxxglb.h" #include ucxx1( bxcenter , bycenter ) INT bxcenter , bycenter ; { CBOXPTR acellptr ; TIBOXPTR atileptr ; PINBOXPTR atermptr ; INT cost , error_light_is_on ; INT axcenter ; INT aleft , aright ; INT a1LoBin , a1HiBin , b1LoBin , b1HiBin ; INT startxa1 , endxa1 , startxb1 , endxb1 ; INT truth , aorient ; INT newpenal, newtimepenal ; acellptr = carrayG[ aG ] ; aorient = acellptr->corient ; axcenter = acellptr->cxcenter ; atileptr = acellptr->tileptr ; aleft = atileptr->left ; aright = atileptr->right ; atermptr = acellptr->pins ; newbinpenalG = binpenalG ; newrowpenalG = rowpenalG ; new_old( aleft-aright ) ; a1LoBin = SetBin( startxa1 = axcenter + aleft ) ; a1HiBin = SetBin( endxa1 = axcenter + aright ) ; b1LoBin = SetBin( startxb1 = bxcenter + aleft ) ; b1HiBin = SetBin( endxb1 = bxcenter + aright ) ; old_assgnto_new1( a1LoBin , a1HiBin , b1LoBin , b1HiBin ) ; sub_penal( startxa1 , endxa1 , ablockG , a1LoBin , a1HiBin ) ; add_penal( startxb1 , endxb1 , bblockG , b1LoBin , b1HiBin ) ; newpenal = (INT)(roLenConG * (DOUBLE) newrowpenalG + binpenConG * (DOUBLE) newbinpenalG ) ; error_light_is_on = 0 ; if( newpenal - penaltyG > P_limitG ) { if( potential_errorsG < 100 ) { ++potential_errorsG ; error_light_is_on = 1 ; } else { earlyRejG++ ; return( -1 ) ; } } term_newpos( atermptr , bxcenter , bycenter , aorient ) ; cost = funccostG ; clear_net_set() ; /* reset set to mark nets that have changed position */ /* dimbox routines mark the nets that have changed */ new_dbox( atermptr , &cost ) ; newtimepenal = timingcostG ; newtimepenal += calc_incr_time( aG ) ; D( "twsc/check_timing", ASSERT( dcalc_full_penalty( newtimepenal ),"ucxx1","time problem") ; ) ; truth = acceptt( funccostG-cost, timingcostG-newtimepenal, penaltyG-newpenal ) ; if( truth ) { if( error_light_is_on ) { error_countG++ ; } new_assgnto_old1( a1LoBin , a1HiBin , b1LoBin , b1HiBin ) ; dbox_pos( atermptr ) ; update_time( aG ) ; /* ****************************************************** */ remv_cell( cellaptrG , ApostG ) ; add_cell( &binptrG[bblockG][ SetBin(bxcenter) ]->cell , aG ) ; /* ****************************************************** */ G( erase_a_cell( aG, acellptr->cxcenter, acellptr->cycenter ) ) ; acellptr->cblock = bblockG ; acellptr->cxcenter = bxcenter ; acellptr->cycenter = bycenter ; funccostG = cost ; binpenalG = newbinpenalG ; rowpenalG = newrowpenalG ; penaltyG = newpenal ; timingcostG = newtimepenal ; if( ablockG != bblockG ) { barrayG[ablockG]->oldsize = barrayG[ablockG]->newsize ; barrayG[bblockG]->oldsize = barrayG[bblockG]->newsize ; } G( graphics_cell_update( aG ) ) ; return( 1 ) ; } else { G( graphics_cell_attempt( aG ) ) ; return( 0 ) ; } } graywolf-0.1.4+20170307gite1bf319/src/twsc/ucxx2.c000066400000000000000000000231131305746555600207500ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: ucxx2.c DESCRIPTION:pairwise exchange. CONTENTS: ucxx2( ) find_new_pos() add_cell( cellptr , c ) INT **cellptr , c ; DATE: Mar 27, 1989 REVISIONS: Mon Aug 12 17:01:03 CDT 1991 - changed timing ASSERTIONS to D( ) constructs to speed execution time during debug mode. Thu Aug 22 22:31:52 CDT 1991 - Carl made change to fence case. Thu Sep 19 14:15:51 EDT 1991 - added equal width cell capability. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) ucxx2.c (Yale) version 4.10 4/2/92" ; #endif #endif #include "ucxxglb.h" #include "readpar.h" #include static INT anxcenterS , bnxcenterS ; ucxx2( ) { CBOXPTR acellptr , bcellptr ; TIBOXPTR atileptr , btileptr ; PINBOXPTR atermptr , btermptr ; INT error_light_is_on ; INT cost ; INT aorient , borient ; INT a1LoBin, a1HiBin, b1LoBin, b1HiBin ; INT a2LoBin, a2HiBin, b2LoBin, b2HiBin ; INT startxa1 , endxa1 , startxa2 , endxa2 ; INT startxb1 , endxb1 , startxb2 , endxb2 ; INT newtimepenal ; INT newpenal ; INT anbin , bnbin , i ; INT truth ; INT wire_chg ; DOUBLE temp ; INT abin, bbin ; /* temporary */ acellptr = carrayG[ aG ] ; axcenterG = acellptr->cxcenter ; aycenterG = acellptr->cycenter ; aorient = acellptr->corient ; atileptr = acellptr->tileptr ; aleftG = atileptr->left ; arightG = atileptr->right ; atermptr = acellptr->pins ; bcellptr = carrayG[ bG ] ; bxcenterG = bcellptr->cxcenter ; bycenterG = bcellptr->cycenter ; borient = bcellptr->corient ; btileptr = bcellptr->tileptr ; bleftG = btileptr->left ; brightG = btileptr->right ; btermptr = bcellptr->pins ; newbinpenalG = binpenalG ; newrowpenalG = rowpenalG ; /*----------- exchange the centers of both cells -------------*/ if( Equal_Width_CellsG ){ newpenal = 0 ; anxcenterS = bxcenterG ; bnxcenterS = axcenterG ; } else { new_old( brightG-bleftG-arightG+aleftG ) ; find_new_pos() ; a1LoBin = SetBin( startxa1 = axcenterG + aleftG ) ; a1HiBin = SetBin( endxa1 = axcenterG + arightG ) ; b1LoBin = SetBin( startxb1 = bxcenterG + bleftG ) ; b1HiBin = SetBin( endxb1 = bxcenterG + brightG ) ; a2LoBin = SetBin( startxa2 = anxcenterS + aleftG ) ; a2HiBin = SetBin( endxa2 = anxcenterS + arightG ) ; b2LoBin = SetBin( startxb2 = bnxcenterS + bleftG ) ; b2HiBin = SetBin( endxb2 = bnxcenterS + brightG ) ; old_assgnto_new2( a1LoBin , a1HiBin , b1LoBin , b1HiBin , a2LoBin , a2HiBin , b2LoBin , b2HiBin ) ; sub_penal( startxa1 , endxa1 , ablockG , a1LoBin , a1HiBin ) ; sub_penal( startxb1 , endxb1 , bblockG , b1LoBin , b1HiBin ) ; add_penal( startxa2 , endxa2 , bblockG , a2LoBin , a2HiBin ) ; add_penal( startxb2 , endxb2 , ablockG , b2LoBin , b2HiBin ) ; newpenal = (INT)( roLenConG * (DOUBLE) newrowpenalG + binpenConG * (DOUBLE) newbinpenalG ) ; error_light_is_on = 0 ; if( newpenal - penaltyG > P_limitG ) { if( potential_errorsG < 100 ) { ++potential_errorsG ; error_light_is_on = 1 ; } else { earlyRejG++ ; return( -1 ) ; } } } term_newpos( atermptr , anxcenterS , bycenterG , aorient ) ; term_newpos( btermptr , bnxcenterS , aycenterG , borient ) ; cost = funccostG ; clear_net_set() ; /* reset set to mark nets that have changed position */ /* dimbox routines mark the nets that have changed */ new_dbox2( atermptr , btermptr , &cost ) ; newtimepenal = timingcostG ; newtimepenal += calc_incr_time2( aG, bG ) ; D( "twsc/check_timing", ASSERT( dcalc_full_penalty(newtimepenal),NULL,"time problem") ; ) ; wire_chg = (cost - funccostG) + (newtimepenal - timingcostG) ; truth = acceptt( funccostG-cost, timingcostG-newtimepenal,penaltyG-newpenal ); if( truth ) { if(!(Equal_Width_CellsG)){ if( error_light_is_on ) { error_countG++ ; } new_assgnto_old2( a1LoBin , a1HiBin , b1LoBin , b1HiBin , a2LoBin , a2HiBin , b2LoBin , b2HiBin ) ; } dbox_pos( atermptr ) ; dbox_pos( btermptr ) ; update_time2() ; anbin = SetBin( anxcenterS ) ; bnbin = SetBin( bnxcenterS ) ; if( cellaptrG != cellbptrG ) { remv_cell( cellaptrG , ApostG ) ; remv_cell( cellbptrG , BpostG ) ; add_cell( &binptrG[bblockG][anbin]->cell , aG ) ; add_cell( &binptrG[ablockG][bnbin]->cell , bG ) ; } else { /* This will never happen for Equal_Width_Cells */ remv_cell( cellaptrG , ApostG ) ; for( i = 1 ; i <= *cellaptrG ; i++ ) { if( cellaptrG[i] == bG ) { break ; } } remv_cell( cellaptrG , i ) ; add_cell( &binptrG[ablockG][anbin]->cell , aG ) ; add_cell( &binptrG[ablockG][bnbin]->cell , bG ) ; } if( wire_chg < 0 ) { temp = (DOUBLE) - wire_chg ; total_wire_chgG += temp ; sigma_wire_chgG += (temp - mean_wire_chgG) * (temp - mean_wire_chgG) ; wire_chgsG++ ; } G( erase_a_cell( aG, axcenterG, aycenterG ) ) ; G( erase_a_cell( bG, bxcenterG, bycenterG ) ) ; acellptr->cblock = bblockG ; acellptr->cxcenter = anxcenterS ; acellptr->cycenter = bycenterG ; bcellptr->cblock = ablockG ; bcellptr->cxcenter = bnxcenterS ; bcellptr->cycenter = aycenterG ; funccostG = cost ; binpenalG = newbinpenalG ; rowpenalG = newrowpenalG ; penaltyG = newpenal ; timingcostG = newtimepenal ; if( ablockG != bblockG ) { barrayG[ablockG]->oldsize = barrayG[ablockG]->newsize ; barrayG[bblockG]->oldsize = barrayG[bblockG]->newsize ; } G( graphics_cell_update( aG ) ) ; G( graphics_cell_update( bG ) ) ; return( 1 ) ; } else { G( graphics_cell_attempt( aG ) ) ; G( graphics_cell_attempt( bG ) ) ; return( 0 ) ; } } find_new_pos() { INT newA_l , newA_r , newB_l , newB_r ; INT oldA_l , oldA_r , oldB_l , oldB_r ; INT span , target , target_l , target_r , blkLeft , blkRite ; INT dist1 , dist2 ; newA_l = bxcenterG + aleftG ; newA_r = bxcenterG + arightG ; newB_l = axcenterG + bleftG ; newB_r = axcenterG + brightG ; if( (ablockG == bblockG) && (!( (newA_l >= newB_r) || (newB_l >= newA_r)))){ /* * Then some overlapping will exist in the new positions */ oldA_l = axcenterG + aleftG ; oldA_r = axcenterG + arightG ; oldB_l = bxcenterG + bleftG ; oldB_r = bxcenterG + brightG ; if( !( (oldA_l >= oldB_r) || (oldB_l >= oldA_r) ) ) { /* * There was also initial overlap; therefore * move cells apart. Find the minimum distance * necessary to pull them apart. */ span = arightG - aleftG + brightG - bleftG ; target = ( ((oldA_l <= oldB_l) ? oldA_l : oldB_l) + ((oldA_r >= oldB_r) ? oldA_r : oldB_r) ) / 2 ; target_l = target - span / 2 ; target_r = target_l + span ; blkLeft = barrayG[ablockG]->bxcenter + barrayG[ablockG]->bleft ; blkRite = blkLeft + barrayG[ablockG]->desire ; if( target_l < blkLeft ) { target_l += blkLeft - target_l ; target_r += blkLeft - target_l ; } else if( target_r > blkRite ) { target_l -= target_r - blkRite ; target_r -= target_r - blkRite ; } dist1 = newA_r - newB_l ; dist2 = newB_r - newA_l ; if( dist1 <= dist2 ) { anxcenterS = target_l - aleftG ; bnxcenterS = target_r - brightG ; } else { anxcenterS = target_r - arightG ; bnxcenterS = target_l - bleftG ; } } else { /* * No initial overlap, but some would be created * as it stands now. Eliminate the possibility of * overlap by maintaining the original left * bound and the original right bound. */ if( oldA_l <= oldB_l ) { bnxcenterS = oldA_l - bleftG ; anxcenterS = oldB_r - arightG ; } else { anxcenterS = oldB_l - aleftG ; bnxcenterS = oldA_r - brightG ; } } } else { anxcenterS = bxcenterG ; bnxcenterS = axcenterG ; } return ; } add_cell( cellptr , c ) INT **cellptr , c ; { INT k ; if( (k = ++(**cellptr)) % 10 == 0 ) { *cellptr = (INT *) Ysafe_realloc( *cellptr, (k + 10) * sizeof(INT)); } (*cellptr)[k] = c ; return ; } /* remv_cell( cellptr , post ) INT *cellptr , post ; { if( *cellptr != post ) { cellptr[ post ] = cellptr[ *cellptr ] ; } (*cellptr)-- ; } */ graywolf-0.1.4+20170307gite1bf319/src/twsc/ucxxglb.h000066400000000000000000000025311305746555600213610ustar00rootroot00000000000000/* ----------------------------------------------------------------- "@(#) ucxxglb.h (Yale) version 4.4 9/19/91" FILE: ucxxglb.h DESCRIPTION:insert file for cell moves. CONTENTS: macros and global defs for cell moves. DATE: Mar 27, 1989 REVISIONS: Thu Sep 19 14:15:51 EDT 1991 - added equal width cell capability. ----------------------------------------------------------------- */ #ifndef UCXXGLB_H #define UCXXGLB_H #include "standard.h" #define MASK 0x3ff #define remv_cell( cellptr , post ) (\ ( *cellptr != post ) ? (cellptr[ post ] = cellptr[ *cellptr ],\ (*cellptr)-- ) : (*cellptr)-- ) /* #define add_cell( cellptr , c ) ( cellptr[ ++(*cellptr) ] = c ) */ /* global variables defined for main */ #ifdef UCXXGLB_VARS #define EXTERN #else #define EXTERN extern #endif EXTERN INT ablockG , bblockG ; EXTERN INT aG , bG ; EXTERN INT ApostG , BpostG ; EXTERN INT *cellaptrG , *cellbptrG ; EXTERN INT earlyRejG , Rej_errorG ; EXTERN INT axcenterG , aycenterG , bxcenterG , bycenterG ; EXTERN INT aleftG , arightG , bleftG , brightG ; EXTERN INT attemptsG ; EXTERN INT potential_errorsG , error_countG , P_limitG ; EXTERN DOUBLE total_wire_chgG ; EXTERN DOUBLE sigma_wire_chgG ; EXTERN DOUBLE mean_wire_chgG ; EXTERN INT wire_chgsG ; EXTERN DOUBLE fraction_doneG ; #undef EXTERN #endif /* UCXXGLB_H */ graywolf-0.1.4+20170307gite1bf319/src/twsc/ucxxo1.c000066400000000000000000000116721305746555600211350ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: ucxxo1.c DESCRIPTION:single cell move with orientation change. CONTENTS: ucxxo1( bxcenter , bycenter , newaor ) INT bxcenter , bycenter , newaor ; DATE: Mar 27, 1989 REVISIONS: Mon Aug 12 17:01:03 CDT 1991 - changed timing ASSERTIONS to D( ) constructs to speed execution time during debug mode. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) ucxxo1.c (Yale) version 4.7 2/23/92" ; #endif #endif #include "ucxxglb.h" #include /* INT potential_errors , error_count , P_limit ; */ ucxxo1( bxcenter , bycenter , newaor ) INT bxcenter , bycenter , newaor ; { CBOXPTR acellptr ; TIBOXPTR atileptr ; PINBOXPTR antrmptr ; INT cost , error_light_is_on ; INT axcenter ; INT aleft , aright ; INT a1LoBin, a1HiBin, b1LoBin, b1HiBin ; INT startxa1 , endxa1 , startxb1 , endxb1 ; INT truth ; INT newtimepenal ; INT newpenal ; acellptr = carrayG[ aG ] ; axcenter = acellptr->cxcenter ; atileptr = acellptr->tileptr ; aleft = atileptr->left ; aright = atileptr->right ; antrmptr = acellptr->pins ; newbinpenalG = binpenalG ; newrowpenalG = rowpenalG ; new_old( aleft - aright ) ; a1LoBin = SetBin( startxa1 = axcenter + aleft ) ; a1HiBin = SetBin( endxa1 = axcenter + aright ) ; b1LoBin = SetBin( startxb1 = bxcenter + aleft ) ; b1HiBin = SetBin( endxb1 = bxcenter + aright ) ; old_assgnto_new1( a1LoBin , a1HiBin , b1LoBin , b1HiBin ) ; sub_penal( startxa1 , endxa1 , ablockG , a1LoBin , a1HiBin ) ; add_penal( startxb1 , endxb1 , bblockG , b1LoBin , b1HiBin ) ; newpenal = (INT)(roLenConG * (DOUBLE) newrowpenalG + binpenConG * (DOUBLE) newbinpenalG ); error_light_is_on = 0 ; if( newpenal - penaltyG > P_limitG ) { if( potential_errorsG < 100 ) { ++potential_errorsG ; error_light_is_on = 1 ; } else { earlyRejG++ ; return( -1 ) ; } } term_newpos( antrmptr , bxcenter , bycenter , newaor ) ; cost = funccostG ; clear_net_set() ; /* reset set to mark nets that have changed position */ /* dimbox routines mark the nets that have changed */ new_dbox( antrmptr , &cost ) ; newtimepenal = timingcostG ; newtimepenal += calc_incr_time( aG ) ; D( "twsc/check_timing", ASSERT( dcalc_full_penalty(newtimepenal),NULL,"time problem") ; ) ; truth = acceptt( funccostG-cost,timingcostG-newtimepenal,penaltyG-newpenal ) ; if( truth ) { if( error_light_is_on ) { error_countG++ ; } new_assgnto_old1( a1LoBin , a1HiBin , b1LoBin , b1HiBin ) ; dbox_pos( antrmptr ) ; update_time( aG ) ; /* ****************************************************** */ remv_cell( cellaptrG , ApostG ) ; add_cell( &binptrG[bblockG][ SetBin(bxcenter) ]->cell , aG ) ; /* ****************************************************** */ G( erase_a_cell( aG, axcenter, acellptr->cycenter ) ) ; acellptr->cblock = bblockG ; acellptr->cxcenter = bxcenter ; acellptr->cycenter = bycenter ; acellptr->corient = newaor ; funccostG = cost ; binpenalG = newbinpenalG ; rowpenalG = newrowpenalG ; penaltyG = newpenal ; timingcostG = newtimepenal ; if( ablockG != bblockG ) { barrayG[ablockG]->oldsize = barrayG[ablockG]->newsize ; barrayG[bblockG]->oldsize = barrayG[bblockG]->newsize ; } G( graphics_cell_update( aG ) ) ; return( 1 ) ; } else { G( graphics_cell_attempt( aG ) ) ; return( 0 ) ; } } graywolf-0.1.4+20170307gite1bf319/src/twsc/ucxxo2.c000066400000000000000000000152571305746555600211410ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: ucxxo2.c DESCRIPTION:pairwise exchange with oriention change. CONTENTS: ucxxo2( newaor , newbor ) INT newaor , newbor ; DATE: Mar 27, 1989 REVISIONS: Mon Aug 12 17:01:03 CDT 1991 - changed timing ASSERTIONS to D( ) constructs to speed execution time during debug mode. Thu Sep 19 14:15:51 EDT 1991 - added equal width cell capability. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) ucxxo2.c (Yale) version 4.8 2/23/92" ; #endif #endif #include "ucxxglb.h" #include "readpar.h" #include ucxxo2( newaor , newbor ) INT newaor , newbor ; { CBOXPTR acellptr , bcellptr ; TIBOXPTR atileptr , btileptr ; PINBOXPTR antrmptr , bntrmptr ; DOUBLE temp ; INT cost , error_light_is_on ; INT axcenter , aycenter , bxcenter , bycenter ; INT aleft , aright ; INT bleft , bright ; INT a1LoBin, a2LoBin, b1LoBin, b2LoBin ; INT a1HiBin, a2HiBin, b1HiBin, b2HiBin ; INT startxa1 , endxa1 , startxa2 , endxa2 ; INT startxb1 , endxb1 , startxb2 , endxb2 ; INT truth ; INT newtimepenal ; INT newpenal ; INT wire_chg ; acellptr = carrayG[ aG ] ; axcenter = acellptr->cxcenter ; aycenter = acellptr->cycenter ; atileptr = acellptr->tileptr ; aleft = atileptr->left ; aright = atileptr->right ; antrmptr = acellptr->pins ; bcellptr = carrayG[ bG ] ; bxcenter = bcellptr->cxcenter ; bycenter = bcellptr->cycenter ; btileptr = bcellptr->tileptr ; bleft = btileptr->left ; bright = btileptr->right ; bntrmptr = bcellptr->pins ; newbinpenalG = binpenalG ; newrowpenalG = rowpenalG ; if( Equal_Width_CellsG ){ newpenal = 0 ; } else { new_old( bright - bleft - aright + aleft ) ; a1LoBin = SetBin( startxa1 = axcenter + aleft ) ; a1HiBin = SetBin( endxa1 = axcenter + aright ) ; b1LoBin = SetBin( startxb1 = bxcenter + bleft ) ; b1HiBin = SetBin( endxb1 = bxcenter + bright ) ; a2LoBin = SetBin( startxa2 = bxcenter + aleft ) ; a2HiBin = SetBin( endxa2 = bxcenter + aright ) ; b2LoBin = SetBin( startxb2 = axcenter + bleft ) ; b2HiBin = SetBin( endxb2 = axcenter + bright ) ; old_assgnto_new2( a1LoBin , a1HiBin , b1LoBin , b1HiBin , a2LoBin , a2HiBin , b2LoBin , b2HiBin ) ; sub_penal( startxa1 , endxa1 , ablockG , a1LoBin , a1HiBin ) ; sub_penal( startxb1 , endxb1 , bblockG , b1LoBin , b1HiBin ) ; add_penal( startxa2 , endxa2 , bblockG , a2LoBin , a2HiBin ) ; add_penal( startxb2 , endxb2 , ablockG , b2LoBin , b2HiBin ) ; newpenal = (INT)( roLenConG * (DOUBLE) newrowpenalG + binpenConG * (DOUBLE) newbinpenalG ) ; error_light_is_on = 0 ; if( newpenal - penaltyG > P_limitG ) { if( potential_errorsG < 100 ) { ++potential_errorsG ; error_light_is_on = 1 ; } else { earlyRejG++ ; return( -1 ) ; } } } /* end !Equal_Width_CellsG */ term_newpos( antrmptr , bxcenter , bycenter , newaor ) ; term_newpos( bntrmptr , axcenter , aycenter , newbor ) ; cost = funccostG ; clear_net_set() ; /* reset set to mark nets that have changed position */ /* dimbox routines mark the nets that have changed */ new_dbox2( antrmptr , bntrmptr , &cost ) ; newtimepenal = timingcostG ; newtimepenal += calc_incr_time2( aG, bG ) ; D( "twsc/check_timing", ASSERT( dcalc_full_penalty(newtimepenal),NULL,"time problem") ; ) ; wire_chg = (cost - funccostG) + (newtimepenal - timingcostG) ; truth = acceptt( funccostG-cost,timingcostG-newtimepenal, penaltyG-newpenal ) ; if( truth ) { if(!(Equal_Width_CellsG)){ if( error_light_is_on ) { error_countG++ ; } new_assgnto_old2( a1LoBin , a1HiBin , b1LoBin , b1HiBin , a2LoBin , a2HiBin , b2LoBin , b2HiBin ) ; } dbox_pos( antrmptr ) ; dbox_pos( bntrmptr ) ; update_time2() ; if( cellaptrG != cellbptrG ) { remv_cell( cellaptrG , ApostG ) ; remv_cell( cellbptrG , BpostG ) ; add_cell( &binptrG[bblockG][ SetBin(bxcenter) ]->cell , aG ) ; add_cell( &binptrG[ablockG][ SetBin(axcenter) ]->cell , bG ) ; } if( wire_chg < 0 ) { temp = (DOUBLE) - wire_chg ; total_wire_chgG += temp ; sigma_wire_chgG += (temp - mean_wire_chgG) * (temp - mean_wire_chgG) ; wire_chgsG++ ; } /* if( wire_chg < max_wire_chg ) { max_wire_chg = wire_chg ; } */ G( erase_a_cell( aG, axcenter, aycenter ) ) ; G( erase_a_cell( bG, bxcenter, bycenter ) ) ; acellptr->cblock = bblockG ; acellptr->cxcenter = bxcenter ; acellptr->cycenter = bycenter ; bcellptr->cblock = ablockG ; bcellptr->cxcenter = axcenter ; bcellptr->cycenter = aycenter ; acellptr->corient = newaor ; bcellptr->corient = newbor ; funccostG = cost ; binpenalG = newbinpenalG ; rowpenalG = newrowpenalG ; penaltyG = newpenal ; timingcostG = newtimepenal ; if( ablockG != bblockG ) { barrayG[ablockG]->oldsize = barrayG[ablockG]->newsize ; barrayG[bblockG]->oldsize = barrayG[bblockG]->newsize ; } G( graphics_cell_update( aG ) ) ; G( graphics_cell_update( bG ) ) ; return( 1 ) ; } else { G( graphics_cell_attempt( aG ) ) ; G( graphics_cell_attempt( bG ) ) ; return( 0 ) ; } } graywolf-0.1.4+20170307gite1bf319/src/twsc/ucxxp.c000066400000000000000000000070521305746555600210520ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: ucxxp.c DESCRIPTION:pairwise exchange. CONTENTS: ucxxp( a , b , anxcenter , bnxcenter ) INT a , b , anxcenter , bnxcenter ; DATE: Mar 27, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) ucxxp.c (Yale) version 4.6 2/23/92" ; #endif #endif #include "ucxxglb.h" #include ucxxp( a , b , anxcenter , bnxcenter ) INT a , b , anxcenter , bnxcenter ; { CBOXPTR acellptr , bcellptr ; PINBOXPTR atermptr , btermptr ; INT cost ; INT aorient , borient ; INT aycenter , bycenter ; INT newtimepenal ; acellptr = carrayG[ a ] ; aycenter = acellptr->cycenter ; aorient = acellptr->corient ; atermptr = acellptr->pins ; bcellptr = carrayG[ b ] ; bycenter = bcellptr->cycenter ; borient = bcellptr->corient ; btermptr = bcellptr->pins ; term_newpos( atermptr , anxcenter , bycenter , aorient ) ; term_newpos( btermptr , bnxcenter , aycenter , borient ) ; cost = funccostG ; clear_net_set() ; /* reset set to mark nets that have changed position */ /* dimbox routines mark the nets that have changed */ new_dbox2( atermptr , btermptr , &cost ) ; newtimepenal = timingcostG ; newtimepenal += calc_incr_time2( a, b ) ; D( "twsc/check_timing", ASSERT( dcalc_full_penalty(newtimepenal),NULL,"time problem") ; ) ; if( acceptt( funccostG - cost, timingcostG - newtimepenal, 0 ) ){ dbox_pos( atermptr ) ; dbox_pos( btermptr ) ; update_time2() ; G( erase_a_cell( a, acellptr->cxcenter, aycenter ) ) ; G( erase_a_cell( b, bcellptr->cxcenter, bycenter ) ) ; acellptr->cxcenter = anxcenter ; acellptr->cycenter = bycenter ; bcellptr->cxcenter = bnxcenter ; bcellptr->cycenter = aycenter ; funccostG = cost ; timingcostG = newtimepenal ; G( graphics_cell_update( a ) ) ; G( graphics_cell_update( b ) ) ; return( 1 ) ; } else { G( graphics_cell_attempt( a ) ) ; G( graphics_cell_attempt( b ) ) ; return( 0 ) ; } } graywolf-0.1.4+20170307gite1bf319/src/twsc/uloop.c000066400000000000000000001101631305746555600210370ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * Copyright (C) 2015 Tim Edwards * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: uloop.c DESCRIPTION:inner loop of simulated annealing algorithm. CONTENTS: save_control( fp ) FILE *fp ; read_control( fp ) FILE *fp ; INT eval_ratio(t) DOUBLE *t; init_uloop() init_control(first) INT first; pick_position(x,y,ox,oy,scale) INT *x,*y,ox,oy; DOUBLE scale ; update_window_size( iternum ) DOUBLE iternum ; uloop() rowcon() DOUBLE partition( C_initial,k_initial,p_initial,R_initial ) INT C_initial , k_initial , p_initial , R_initial ; DOUBLE expected_value(C_initial,k_initial,p_initial,R_initial) INT C_initial , k_initial , p_initial , R_initial ; DOUBLE expected_svalue(C_initial,k_initial, p_initial,R_initial ) INT C_initial , k_initial , p_initial , R_initial ; DOUBLE compute_and_combination( C , k , p , R ) INT C , k , p , R ; DOUBLE combination( numerator , denominator ) INT numerator , denominator ; sanity_check() sanity_check2() sanity_check3() DATE: Mar 27, 1989 REVISIONS: Mar 29, 1989 - removed vertical / horz wire weighting. Apr 1, 1990 - removed vertical wire weight from table. Wed Jun 5 16:48:31 CDT 1991 - fixed problem with T controller initialization for zero delta costs. Thu Sep 19 14:15:51 EDT 1991 - added equal width cell capability. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) uloop.c (Yale) version 4.14 3/23/92" ; #endif #endif #define UCXXGLB_VARS #include "standard.h" #include "ucxxglb.h" #include "main.h" #include "readpar.h" #include "parser.h" #include "yalecad/message.h" #include "yalecad/debug.h" #define INITRATIO 0.95 #define AC0 0.90 #define AC1 0.44 #define AC2 0.06 #define AC3 0.10 #define AC4 0.10 #define PT1 0.15 #define PT2 0.52 #define PT3 1.00 #define LAC1 (log(AC1)) #define LAC2 (log(AC2)) #define STEPSPERCEL 0.01 #define TABLIMIT 4096 /* simple table lookup for log. */ #define TABSHIFT 19 #define TABMASK 0xfff #define TABOFFSET 0x40000 #define RANDFACT (1.0 / MAXINT) #define CHANCE(n) (!(RAND % n)) /* #define START_ITER 81 if you change this one, */ /* do the same in utemp */ /* Note: If you change definitions here, check newtemp.c */ #define ACCEPTDAMPFACTOR 0.025 /* damping factor for acceptance rate*/ #define ACCEPTDAMPFACTOR2 0.25 /* damping factor for low temp's */ #define HIGHTEMP 23.0 /* (15.0) end of high temperature regime */ #define MEDTEMP 81.0 /* (52.0) end of range limiter regime */ #define TURNOFFT 125.0 /* (100) iterationG of negative feedback turnoff */ #define LASTTEMP 155.00 /* last iterationG */ #define NUMTUPDATES 400 /* maximum number of T updates per iterationG */ #define PICK_INT(l,u) (((l)<(u)) ? ((RAND % ((u)-(l)+1))+(l)) : (l)) /* global variables */ BOOL fences_existG ; DOUBLE avg_timeG ; /* average random time penalty */ DOUBLE avg_funcG ; /* average random wirelength penalty */ DOUBLE start_timeG ;/* initial target value for the time penalty */ DOUBLE end_timeG ; /* final target value for the time penalty - obviously zero */ DOUBLE ratioG = 1.0 ; DOUBLE finalRowControlG ; DOUBLE initialRowControlG ; /* global references */ extern INT totalRG ; extern INT minxspanG ; extern BOOL pairtestG ; extern BOOL no_feed_estG ; extern BOOL good_initial_placementG ; /* function calls */ DOUBLE expected_svalue() ; DOUBLE expected_value() ; DOUBLE partition() ; DOUBLE compute_and_combination() ; DOUBLE combination() ; INT eval_ratio() ; /* static variables */ static INT acc_cntS = 0 ; static INT move_cntS = 0 ; static INT f_cntS = 0; static INT cost_vectorS[13] = { 0,0,0,0,0,0,0,0,0,0,0,0,0 } ; static BOOL not_doneS = TRUE ; static BOOL first_fdsS = TRUE ; static BOOL first_capS = TRUE ; static BOOL called_rowconS = FALSE ; static BOOL P_limit_setS = FALSE ; static DOUBLE xadjustmentS,xalS,min_xalphaS,max_xalphaS;/* x control */ static DOUBLE yadjustmentS,yalS,min_yalphaS,max_yalphaS;/* y control */ static DOUBLE tauXS, tauYS ; /* exp. decay time constants for window */ static DOUBLE stepS ; static DOUBLE num_penalS ; static DOUBLE avg_rowpenalS ; static DOUBLE f_meanS = 0.0; static DOUBLE total_stepS ; static DOUBLE fp_ratioS = 1.0 ; static DOUBLE log_tabS[TABLIMIT]; static DOUBLE bin_capS = 99.0 ; static DOUBLE row_capS = 99.0 ; static DOUBLE a_ratioS; static DOUBLE total_costS; init_uloop() { not_doneS = 1; acc_cntS = move_cntS ; ratioG = 1.0; } /* end init_uloop */ uloop() { FENCEBOXPTR fence ; CBOXPTR acellptr, bcellptr ; BBOXPTR ablckptr , bblckptr ; INT flips , rejects , do_single_cell_move , bit_class ; INT axcenter , bxcenter , bycenter ; INT aorient , borient ; INT blk , pairflips ; INT i , j , t , count , swaps, index, shift ; INT abin , bbin , fds , done , single_swap ; DOUBLE target_row_penalty ; DOUBLE target_bin_penalty ; DOUBLE temp , percent_error ; DOUBLE dCp, delta , gswap_ratio ; INT m1,m2, trials ; INT num_accepts , gate_switches , gate_attempts ; INT last_flips , delta_func , delta_time ; INT temp_timer, time_to_update ; /* keeps track of when to update T */ DOUBLE iter_time, accept_deviation, calc_acceptance_ratio() ; DOUBLE num_time, num_func ; DOUBLE calc_time_factor() ; /* commented out variables INT reset_T ; DOUBLE old_T ; */ attemptsG = 0 ; flips = 0 ; rejects = 0 ; pairflips = 0 ; earlyRejG = 0 ; Rej_errorG = 0 ; G( reset_heat_index() ) ; potential_errorsG = 0 ; error_countG = 0 ; if( !P_limit_setS || iterationG <= 0 ) { P_limitG = 999999; if( iterationG > 0 ) { P_limit_setS = TRUE ; } } else { if( wire_chgsG > 0 ) { mean_wire_chgG = total_wire_chgG / (DOUBLE) wire_chgsG ; if( iterationG > 1 ) { sigma_wire_chgG = sqrt( sigma_wire_chgG / (DOUBLE) wire_chgsG); } else { sigma_wire_chgG = 3.0 * mean_wire_chgG ; } } else { mean_wire_chgG = 0.0 ; sigma_wire_chgG = 0.0 ; } P_limitG = mean_wire_chgG + 3.0 * sigma_wire_chgG + TG ; if (P_limitG > 999999) P_limitG = 999999; } sigma_wire_chgG = 0.0 ; total_wire_chgG = 0.0 ; wire_chgsG = 0 ; m1 = m2 = 1; dCp = 0.0; fds = reconfig() ; avg_rowpenalS = 0.0 ; num_penalS = 0.0 ; if( iterationG < 0 ) { avg_timeG = 0.0 ; num_time = 0.0 ; avg_funcG = 0.0 ; num_func = 0.0 ; } /* number of moves before temperature update */ time_to_update = attmaxG / NUMTUPDATES ; if( time_to_update <= 14 ) { time_to_update = 14 ; } temp_timer = 0 ; /* initialize timer */ num_accepts = 0 ; last_flips = 0 ; gate_switches = 0 ; gate_attempts = 0 ; /* ------------------------------------------------------------------------ The back bone of the program the "while-loop" begins from here ... ------------------------------------------------------------------------ */ while( attemptsG < attmaxG ) { /* ------------- pick up a number at random --------------- */ aG = PICK_INT( 1 , numcellsG - extra_cellsG ) ; /* ------------- get the structure for cell# aG ------------- */ acellptr = carrayG[ aG ] ; ablockG = acellptr->cblock ; axcenter = acellptr->cxcenter ; /* ------------------------------------------------------------------------ If two cells have the same swap_group then parts of the cells are interchangable. Below we check if the cell#aG belongs to a swap_group ------------------------------------------------------------------------ */ if( acellptr->num_swap_group > 0 ) { INT sgroup; SGLISTPTR sglistptr; i = PICK_INT( 0 , acellptr->num_swap_group - 1 ) ; sglistptr = acellptr->swapgroups + i; sgroup = sglistptr->swap_group; trials = 0 ; /*--- number of max trials (heuristically)=50 ---*/ do { /* ----------------------------------------------------------------- pick_position picks up a new position for the cell#aG, it returns the bxcenter and blk where the cell could be moved ... -----------------------------------------------------------------*/ pick_position(&bxcenter,&blk,axcenter,ablockG,8.0); bbin = SetBin( bxcenter ) ; /* ----------------------------------------------------------------- the field "cell" in binptrG[blk][bbin]->cell contains a list of all the cells in that bin. But cell[0] contains the total number of cells in the bin (hard-coded) isn't it ... -----------------------------------------------------------------*/ cellbptrG = binptrG[blk][bbin]->cell ; if( *cellbptrG > 0 ) { if( Equal_Width_CellsG ){ BpostG = 1 ; } else { BpostG = PICK_INT( 1 , *cellbptrG ) ; } bG = cellbptrG[ BpostG ] ; bcellptr = carrayG[bG] ; } else { bG = 0 ; } if( bG != 0 && aG != bG ) { for (j = 0; j < bcellptr->num_swap_group; j++) { sglistptr = bcellptr->swapgroups + j; if (sglistptr->swap_group == sgroup) break; } if (j < bcellptr->num_swap_group) { break ; } else { trials++ ; } } else { trials++ ; } } while( trials <= 50 ) ; if( trials <= 50 ) { for( swaps = 1 ; swaps <= 4 ; swaps++ ) { /* -- gate_swap evaluates the proposed gate swaps --*/ gate_switches += gate_swap( 1, i, j ) ; gate_attempts++ ; } } sglistptr = acellptr->swapgroups + i; // If a cell has more than one pin group in the same // swap group, then it can permute pin groups within // itself. if( sglistptr->num_pin_group > 1 ) { for( swaps = 1 ; swaps <= 4 ; swaps++ ) { gate_swap( 0, i, j ) ; } } } if( acellptr->cclass < -1 ) { /*---- for rigid cells, continue ----*/ continue ; } ablckptr = barrayG[ ablockG ] ; aorient = acellptr->corient ; abin = SetBin( axcenter ) ; cellaptrG = binptrG[ablockG][abin]->cell ; if( Equal_Width_CellsG ){ ApostG = 1 ; } else { for( i = 1 ; i <= *cellaptrG ; i++ ) { if( cellaptrG[i] == aG ) { ApostG = i ; break ; } } } /* * select block for cell a to be placed in */ if( acellptr->fence == NULL ) { /* cclass -1 cells won't enter here */ bblockG = 0 ; for (i=0; i<10; i++) { pick_position(&bxcenter,&blk,axcenter,ablockG,1.0); bblckptr = barrayG[ blk ] ; /* if cell "a" can't legally enter this row, keep looking */ if( ablockG == blk || acellptr->cclass == 0 ) { /* cell "a" will remain in the same row, or: */ /* cell "a" can go anywhere it pleases */ break ; } else if( acellptr->cclass > 0 ) { /* it cannot go anywhere it pleases */ bit_class = 1 ; index = (bblckptr->bclass - 1) / 32 ; shift = bblckptr->bclass - 32 * index ; bit_class <<= (shift - 1) ; if( bit_class & acellptr->cbclass[index] ) { /* "a" is allowed in a row with this block_class */ break ; } /* else, keep searching for a legal row */ } } } else { /* * select block for cell a to be placed in */ bblockG = 0 ; for (i=0; i<10; i++) { fence = acellptr->fence ; if( fence->next_fence != NULL ) { count = 0 ; for( ; fence; fence = fence->next_fence){ count++ ; } j = PICK_INT( 1 , count ) ; count = 0 ; fence = acellptr->fence ; for( ; fence; fence = fence->next_fence ) { if( ++count == j ) { break ; } } } pick_fence_position(&bxcenter,&blk,fence) ; bblckptr = barrayG[ blk ] ; /* if cell "a" can't legally enter this row, keep looking */ if( ablockG == blk || acellptr->cclass <= 0 ) { /* cell "a" will remain in the same row, or: */ /* cell "a" can go anywhere it pleases */ break ; } else if( acellptr->cclass > 0 ) { /* it cannot go anywhere it pleases */ bit_class = 1 ; index = (bblckptr->bclass - 1) / 32 ; shift = bblckptr->bclass - 32 * index ; bit_class <<= (shift - 1) ; if( bit_class & acellptr->cbclass[index] ) { /* "a" is allowed in a row with this block_class */ break ; } /* else, keep searching for a legal row */ } } }/* end else -- acellptr->fence != NULL -- cclass -1 cells won't enter here */ if (i == 10) continue; /*-- get out of the while-loop --*/ /*------- Now get the target block's structure and target bin -------*/ bblockG = blk; bycenter = bblckptr->bycenter ; bbin = SetBin( bxcenter ) ; cellbptrG = binptrG[bblockG][bbin]->cell ; if( *cellbptrG > 0 ) { count = 0 ; get_b: if( Equal_Width_CellsG ){ BpostG = 1 ; } else { BpostG = PICK_INT( 1 , *cellbptrG ) ; } bG = cellbptrG[ BpostG ] ; if( aG == bG ) { continue ; } bcellptr = carrayG[bG] ; if( fences_existG ) { done = 0 ; if( (fence = bcellptr->fence) != NULL ) { while(1) { /*------- make sure cell aG's block is outside the block bG's fence -------*/ if( ablockG >= fence->min_block && ablockG <= fence->max_block && axcenter >= fence->min_xpos && axcenter <= fence->max_xpos ) { done = 1 ; break ; } else { fence = fence->next_fence ; if( fence == NULL ) { if( ++count < *cellbptrG ) { goto get_b ; } else { break ; } } } } if( !done ) { continue ; } } } if( bcellptr->cclass < -1 ) { do_single_cell_move = 1 ; } else if( ablockG != bblockG && bcellptr->cclass > 0 ) { bit_class = 1 ; index = (ablckptr->bclass - 1) / 32 ; shift = ablckptr->bclass - 32 * index ; bit_class <<= (shift - 1) ; if( !(bit_class & bcellptr->cbclass[index]) ) { /* "b" is not allowed in a row with this block_class */ continue ; } do_single_cell_move = 0 ; borient = bcellptr->corient ; } else { do_single_cell_move = 0 ; borient = bcellptr->corient ; } } else { do_single_cell_move = 1 ; } delta_func = funccostG ; delta_time = timingcostG ; if( do_single_cell_move ) { if( Equal_Width_CellsG ) { continue ; } /* reset_T = 0 ; if( acellptr->fence != NULL ) { if( ablockG < acellptr->fence->min_block || ablockG > acellptr->fence->max_block ) { reset_T = 1 ; old_T = T ; T = 1000000.0 ; } } */ if( ablckptr->borient == 1 ) { if( bblckptr->borient == 1 ) { t = ucxx1( bxcenter, bycenter) ; if( t != 1 ) { rejects++ ; if( rejects % 6 == 0 && acellptr->orflag != 0){ uc0( aG , (aorient == 0) ? 2 : 0 ); } } else { /* if( t == 1 ) */ flips++ ; acc_cntS ++; } } else { /* bblckptr->borient == 2 */ t = ucxxo1( bxcenter,bycenter,(aorient == 0) ? 1 : 3 ) ; if( t != 1 ) { rejects++ ; if( rejects % 6 == 0 && acellptr->orflag != 0){ uc0( aG , (aorient == 0) ? 2 : 0 ); } } else { /* if( t == 1 ) */ flips++ ; acc_cntS ++; } } } else { /* ablockGptr->borient == 2 */ if( bblckptr->borient == 1 ) { t = ucxxo1( bxcenter, bycenter, (aorient == 1) ? 0 : 2) ; if( t != 1 ) { rejects++ ; if( rejects % 6 == 0 && acellptr->orflag != 0){ uc0( aG , (aorient == 1) ? 3 : 1 ); } } else { /* if( t == 1 ) */ flips++ ; acc_cntS ++; } } else { /* bblckptr->borient == 2 */ t = ucxx1( bxcenter, bycenter) ; if( t != 1 ) { rejects++ ; if( rejects % 6 == 0 && acellptr->orflag != 0){ uc0( aG , (aorient == 1) ? 3 : 1 ); } } else { /* if( t == 1 ) */ flips++ ; acc_cntS ++; } } } /* if( reset_T ) { T = old_T ; } */ } else { /* pairwise interchange */ if( ablckptr->borient == 1 ) { if( bblckptr->borient == 1 ) { t = ucxx2() ; if( t != 1 ) { rejects++ ; if( rejects % 6 == 0 && acellptr->orflag != 0){ uc0( aG , (aorient == 0) ? 2 : 0 ); } } else { /* if( t == 1 ) */ pairflips++ ; acc_cntS ++; } } else { /* bblockG->orient == 2 */ t = ucxxo2( (aorient == 0) ? 1:3, (borient == 1) ? 0:2); if( t != 1 ) { rejects++ ; if( rejects % 6 == 0 && acellptr->orflag != 0){ uc0( aG , (aorient == 0) ? 2 : 0 ); } } else { /* if( t == 1 ) */ pairflips++ ; acc_cntS ++; } } } else { /* ablockG->borient == 2 */ if( bblckptr->borient == 1 ) { t = ucxxo2( (aorient == 1) ? 0:2, (borient == 0) ? 1:3); if( t != 1 ) { rejects++ ; if( rejects % 6 == 0 && acellptr->orflag != 0){ uc0( aG , (aorient == 1) ? 3 : 1 ); } } else { /* if( t == 1 ) */ pairflips++ ; acc_cntS ++; } } else { /* bblockG->borient == 2 */ t = ucxx2( ) ; if( t != 1 ) { rejects++ ; if( rejects % 6 == 0 && acellptr->orflag != 0){ uc0( aG , (aorient == 1) ? 3 : 1 ); } } else { /* if( t == 1 ) */ pairflips++ ; acc_cntS ++; } } } } num_penalS += 1.0 ; avg_rowpenalS = (avg_rowpenalS * (num_penalS - 1.0) + (DOUBLE) rowpenalG) / num_penalS ; attemptsG++ ; /* draw the data */ G( check_graphics(FALSE) ) ; if (iterationG <= 0) { if( iterationG == 0 ) continue; /* calculate a running average of (delta) timing penalty */ delta_time = abs( delta_time - timingcostG ) ; if( delta_time != 0 ) { num_time += 1.0 ; avg_timeG = (avg_timeG * (num_time - 1.0) + (DOUBLE) delta_time) / num_time ; /* calculate a running average of (delta) wirelength penalty */ delta_func = abs( delta_func - funccostG ) ; num_func += 1.0 ; avg_funcG = (avg_funcG * (num_func - 1.0) + (DOUBLE) delta_func) / num_func ; } if (d_costG >= 0){ m1 ++; /* d_cost is the -ve of the actual d_cost */ } else { dCp -= d_costG; m2 ++; } temp = (INITRATIO * attemptsG - m1) / m2; if (temp <= 0.0) { TG *= 0.9; } else { TG = -dCp / (m2 * log(temp)); } continue; /* initialization phase */ } /* ----------------------------------------------------------------- Update temperature using negative feedback to control the acceptance ratio in accordance to curve fit schedule. Calc_acceptance_ratio returns desired acceptance ratio give the iterationG. The damped error term (deviation) is then applied to correct the temperature T. Update_window_size controls the range limiter. We avoid updating T during initialization, we use exact schedule to compute starting T. The temp_timer allows us to update temperature inside the inner loop of the annealing algorithm. We use counter to avoid use of mod function for speed. ------------------------------------------------------------------ */ num_accepts += pairflips + flips - last_flips ; last_flips = pairflips + flips ; if( ++temp_timer >= time_to_update || (attemptsG >= attmaxG && temp_timer >= 50) ) { ratioG = ((DOUBLE)(num_accepts)) / (DOUBLE) temp_timer ; temp_timer = 0 ; /* reset counter */ num_accepts = 0 ; iter_time = (DOUBLE) iterationG + (DOUBLE) attemptsG / (DOUBLE) attmaxG ; accept_deviation = (calc_acceptance_ratio( iter_time ) - ratioG ) ; if( (DOUBLE) iterationG < TURNOFFT ) { accept_deviation *= ACCEPTDAMPFACTOR ; } else { accept_deviation *= ACCEPTDAMPFACTOR2 ; } TG *= 1.0 + accept_deviation ; update_window_size( (DOUBLE) iterationG + (DOUBLE) attemptsG / (DOUBLE) attmaxG ) ; } } /* end of inner loop */ D( "uloop", check_cost() ; ) ; f_meanS = 0.0; f_cntS = 0; if( ratioG < AC3 ){ if( iterationG >= LASTTEMP || (tw_frozen( funccostG ) && (iterationG >= LASTTEMP - 5)) ) { pairtestG = TRUE ; } } if( potential_errorsG > 0 ) { percent_error = (DOUBLE) error_countG / (DOUBLE) potential_errorsG ; } else { percent_error = 0.0 ; } percent_error *= 100.0 ; if( pairflips > 0.0001 ) { fp_ratioS = (DOUBLE)flips/(DOUBLE)pairflips ; } else { fp_ratioS = 1.0 ; } ratioG = ((DOUBLE)(pairflips+flips)) / attemptsG; if(iterationG >= 0 || good_initial_placementG ) { if( !gate_arrayG ) { sprintf(YmsgG,"%3d: %6.2le %6ld %-8ld %-6ld %-8ld", iterationG,TG,fds,funccostG,rowpenalG,timingcostG); M( MSG, NULL, YmsgG ) ; } else { sprintf(YmsgG,"%3d: %6.2le %6ld %-8ld %-6ld %-8ld", iterationG,TG,fds,funccostG,rowpenalG,timingcostG); M( MSG, NULL, YmsgG ) ; } sprintf(YmsgG,"%6ld %4.2lf %4.2lf %5.2lf %5.2lf ", P_limitG,percent_error/100.0,binpenConG,roLenConG,timeFactorG); M( MSG, NULL, YmsgG ) ; if( swappable_gates_existG ) { if( gate_attempts > 0 ) { gswap_ratio = (DOUBLE) gate_switches / (DOUBLE) gate_attempts ; } else { gswap_ratio = 0 ; } sprintf(YmsgG,"%4.2lf %4.2lf %5.3lf %4.2lf\n", fp_ratioS,((DOUBLE) earlyRejG)/attemptsG,ratioG, gswap_ratio ); M( MSG, NULL, YmsgG ) ; } else { sprintf(YmsgG,"%4.2lf %4.2lf %5.3lf\n", fp_ratioS,((DOUBLE) earlyRejG)/attemptsG,ratioG ); M( MSG, NULL, YmsgG ) ; } Ymessage_flush(); } if( !called_rowconS && !(Equal_Width_CellsG)) { rowcon() ; called_rowconS = TRUE ; } /* A Negative-Feedback Approach */ if( not_doneS || good_initial_placementG ) { not_doneS = eval_ratio(&fraction_doneG); if (first_capS && (!first_fdsS)) { first_capS = 0; } if( Equal_Width_CellsG ){ /*----------------- No row or bin penalty -----------------*/ target_bin_penalty = 0 ; target_row_penalty = 0 ; binpenConG = 0 ; roLenConG = 0 ; penaltyG = 0 ; /*---------------------------------------------------------*/ } else { target_bin_penalty = (1.25 - 1.00 * fraction_doneG) * (DOUBLE)totalRG ; target_row_penalty = (initialRowControlG - (initialRowControlG - finalRowControlG) * (fraction_doneG) ) * (DOUBLE) totalRG ; binpenConG += ((DOUBLE) binpenalG - target_bin_penalty) / (DOUBLE) totalRG ; binpenConG = (binpenConG > 1.0) ? binpenConG : 1.0 ; if( good_initial_placementG ) { binpenConG = (binpenConG > 4.0) ? 4.0 : binpenConG ; } delta = ((DOUBLE) rowpenalG - target_row_penalty) / target_row_penalty ; if( fraction_doneG > PT1 && fraction_doneG < PT2 ) { roLenConG += ( (fraction_doneG - PT1) / (PT2 - PT1) ) * delta; } else if( fraction_doneG <= PT1 && roLenConG + delta > 6.0 ) { roLenConG = 6.0 ; } else { roLenConG += delta ; if( good_initial_placementG ) { roLenConG = (roLenConG > 5.0) ? 5.0 : roLenConG ; } } roLenConG = (roLenConG > 1.0) ? roLenConG : 1.0 ; penaltyG = (INT)( binpenConG * (DOUBLE) binpenalG + roLenConG * (DOUBLE) rowpenalG ) ; } /* end !Equal_Width_CellsG */ timeFactorG = calc_time_factor() ; } return ; } /* end uloop */ rowcon() { INT C , R , p_first , totalCells , cellsPerRow , temp_R ; INT over, under ; DOUBLE states , value , expect , variance ; DOUBLE expectedExtraRowLength , rowControl , x , minDev ; if( numcellsG > 5000 ) { rowControl = 0.008 ; /* rowControl = 0.012 ; */ initialRowControlG = 6.0 * rowControl ; /* initialRowControlG = 5.5 * rowControl ; */ finalRowControlG = rowControl ; } else { totalCells = numcellsG - extra_cellsG ; /* totalCells = 0 ; for( i = 1 ; i <= numcellsG - extra_cellsG ; i++ ) { if( carrayG[i]->cclass >= 0 ) { totalCells++ ; } } */ R = numRowsG ; cellsPerRow = totalCells / R ; temp_R = R - R / 3 ; rowControl = 0.0 ; do { rowControl += 0.001 ; C = (INT)( rowControl * (DOUBLE) totalCells / 2.0 ) ; if( 2.0 * (DOUBLE)(C+1) - rowControl * totalCells <= rowControl * totalCells - 2.0 * (DOUBLE) C ) { C++ ; } } while( 2 * C < temp_R ) ; p_first = C / R ; if( p_first * R < C ) { p_first++ ; } R -= R / 3 ; under = 0 ; over = 0 ; for( ; ; ) { value = expected_value( C , 0 , p_first , R ) ; states = combination( C+R-1, C ) ; expect = value / states ; expectedExtraRowLength = 100.0 * expect / (DOUBLE) cellsPerRow ; value = expected_svalue( C , 0 , p_first , R ) ; variance = value / states - (expect * expect) ; x = 100.0 * sqrt( variance ) / (DOUBLE) cellsPerRow ; minDev = 100.0 / (DOUBLE) cellsPerRow ; value = x+expectedExtraRowLength - minDev ; if( !resume_runG ) { fprintf(fpoG,"rowControl:%6.3f ", rowControl ) ; fprintf(fpoG,"expected deviation above minimum:%6.2f\n",value); } if( value > 2.7 && value < 3.3 ) { rowControl += 0.001 ; break ; } else if( value <= 2.7 ) { rowControl += 0.001 ; if( !over ) { under = 1 ; } else { break ; } } else if( value >= 3.3 ) { if( !under ) { rowControl -= 0.001 ; over = 1 ; } else { break ; } } C = (INT)( rowControl * (DOUBLE) totalCells / 2.0 ) ; if( 2.0 * (DOUBLE)(C+1) - rowControl * totalCells <= rowControl * totalCells - 2.0 * (DOUBLE) C ) { C++ ; } p_first = C / R ; if( p_first * R < C ) { p_first++ ; } } initialRowControlG = 5.5 * rowControl ; /* initialRowControlG = 5.5 * rowControl ; */ finalRowControlG = rowControl ; } return ; } DOUBLE partition( C_initial , k_initial , p_initial , R_initial ) INT C_initial , k_initial , p_initial , R_initial ; { INT R , C , k , p , k_limit , p_limit ; DOUBLE states , equivs ; states = 0.0 ; R = k_limit = R_initial - k_initial ; C = C_initial - p_initial * k_initial ; for( k = 1 ; k <= k_limit ; k++ ) { equivs = combination( R , k ) ; p_limit = C / k ; for( p = p_initial ; p <= p_limit ; p++ ) { if( C - (p-1)*R > k ) { ; continue ; } states += equivs * (compute_and_combination( C , k , p , R ) - partition( C , k , p , R ) ) ; continue ; } } return( states ) ; } DOUBLE expected_value( C_initial , k_initial , p_initial , R_initial ) INT C_initial , k_initial , p_initial , R_initial ; { INT R , C , k , p , k_limit , p_limit ; DOUBLE value , equivs ; value = 0.0 ; R = k_limit = R_initial - k_initial ; C = C_initial - p_initial * k_initial ; for( k = 1 ; k <= k_limit ; k++ ) { equivs = combination( R , k ) ; p_limit = C / k ; for( p = p_initial ; p <= p_limit ; p++ ) { if( C - (p-1)*R > k ) { ; continue ; } value += (DOUBLE) p * equivs * (compute_and_combination( C , k , p , R ) - partition( C , k , p , R ) ) ; } } return( value ) ; } DOUBLE expected_svalue( C_initial , k_initial , p_initial , R_initial ) INT C_initial , k_initial , p_initial , R_initial ; { INT R , C , k , p , k_limit , p_limit ; DOUBLE value , equivs ; value = 0.0 ; R = k_limit = R_initial - k_initial ; C = C_initial - p_initial * k_initial ; for( k = 1 ; k <= k_limit ; k++ ) { equivs = combination( R , k ) ; p_limit = C / k ; for( p = p_initial ; p <= p_limit ; p++ ) { if( C - (p-1)*R > k ) { ; continue ; } value += (DOUBLE)(p * p) * equivs * (compute_and_combination( C , k , p , R ) - partition( C , k , p , R ) ) ; } } return( value ) ; } DOUBLE compute_and_combination( C , k , p , R ) INT C , k , p , R ; { INT numerator , denom1 , denom2 , temp ; DOUBLE states ; states = 1.0 ; numerator = C - k*p + R - k - 1 ; denom1 = C - k*p ; denom2 = R - k - 1 ; if( denom1 > denom2 ) { temp = denom1 ; denom1 = denom2 ; denom2 = temp ; } for( ; numerator > denom2 ; numerator-- , denom1-- ) { states *= (DOUBLE) numerator ; states /= (DOUBLE) denom1 ; } return( states ) ; } DOUBLE combination( numerator , denominator ) INT numerator , denominator ; { DOUBLE states ; INT temp , denom1 , denom2 ; states = 1.0 ; denom1 = denominator ; denom2 = numerator - denominator ; if( denom1 > denom2 ) { temp = denom1 ; denom1 = denom2 ; denom2 = temp ; } for( ; numerator > denom2 ; numerator-- , denom1-- ) { states *= (DOUBLE) numerator ; states /= (DOUBLE) denom1 ; } return( states ) ; } sanity_check() { INT *cellxptr , cell , center , block , bin , i ; for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { center = carrayG[cell]->cxcenter ; block = carrayG[cell]->cblock ; bin = SetBin( center ) ; cellxptr = binptrG[block][bin]->cell ; for( i = 1 ; i <= *cellxptr ; i++ ) { if( cellxptr[i] == cell ) { break ; } } if( i > *cellxptr ) { return(cell); } } return(0); } sanity_check2() { INT *cellxptr , *clist ; INT block , bin , cell , i ; clist = (INT *) Ysafe_malloc( (1 + numcellsG - extra_cellsG ) * sizeof( INT ) ) ; for( i = 1 ; i <= numcellsG - extra_cellsG ; i++ ) { clist[i] = 0 ; } for( block = 1 ; block <= numRowsG ; block++ ) { for( bin = 0 ; bin <= numBinsG ; bin++ ) { cellxptr = binptrG[block][bin]->cell ; for( i = 1 ; i <= *cellxptr ; i++ ) { cell = cellxptr[i] ; if( clist[cell] == 1 ) { printf("cell %d appears twice in clist\n",cell); fflush(stdout); return(cell); } else { clist[cell] = 1 ; } } } } for( i = 1 ; i <= numcellsG - extra_cellsG ; i++ ) { if( clist[i] == 0 ) { printf("cell %d appears NEVER in clist\n",i); fflush(stdout); return(i); } } Ysafe_free( clist ) ; return(0); } sanity_check3() { INT *cellxptr ; INT block , bin , cell , i ; for( block = 1 ; block <= numRowsG ; block++ ) { for( bin = 0 ; bin <= numBinsG ; bin++ ) { cellxptr = binptrG[block][bin]->cell ; for( i = 1 ; i <= *cellxptr ; i++ ) { cell = cellxptr[i] ; if( carrayG[cell]->cblock != block ) { printf("cell %d has inconsistent block\n",cell); fflush(stdout); return(cell); } if( SetBin( carrayG[cell]->cxcenter ) != bin ) { printf("cell %d has inconsistent bin\n",cell); fflush(stdout); return(cell); } } } } return(0); } /* new evaluate ratio is a linear function of iterationG */ INT eval_ratio( t ) DOUBLE *t; { if( iterationG >= TURNOFFT ){ *t = 1.0 ; } else if( iterationG < 0 ){ *t = 0.0 ; } else { *t = (DOUBLE) iterationG / TURNOFFT ; } return((ratioG < AC4) ? 0 : 1); } init_control(first) INT first; { INT i; DOUBLE tmp ; /* initialize move generation parameters */ min_xalphaS = 0.5 * minxspanG; /* average min. window size */ min_yalphaS = 0.75; if( intelG ) { min_yalphaS = 1.5; } max_xalphaS = blkxspanG; /* average max. window size */ max_yalphaS = numRowsG; total_stepS = STEPSPERCEL * (numcellsG - extra_cellsG) ; xadjustmentS = (max_xalphaS - min_xalphaS) / total_stepS; yadjustmentS = (max_yalphaS - min_yalphaS) / total_stepS; if( first == 1 ) { /* stepS = (init_ratioG >= 0.44) ? 0.0 : 1.0; */ xalS = max_xalphaS; yalS = max_yalphaS; } /* determine tauXS & tauYS - exponential decay of range limiter */ tauXS = - log( (min_xalphaS/max_xalphaS) ) / (MEDTEMP - HIGHTEMP) ; tauYS = - log( (min_yalphaS/max_yalphaS) ) / (MEDTEMP - HIGHTEMP) ; /* prepare lookup table */ for (i=0; imin_block , fence->max_block ) ; bblckptr = barrayG[*y] ; left = fence->min_xpos ; if( left < bblckptr->bxcenter + bblckptr->bleft ) { left = bblckptr->bxcenter + bblckptr->bleft ; } right = fence->max_xpos ; if( right > bblckptr->bxcenter + bblckptr->bright ) { right = bblckptr->bxcenter + bblckptr->bright ; } *x = PICK_INT( left , right ) ; return; } pick_position(x,y,ox,oy,scale) INT *x,*y,ox,oy; DOUBLE scale ; { register INT i,m,n,bleft,bright; DOUBLE tmp ; BBOXPTR bblckptr ; m = RAND; tmp = yalS * scale ; if( tmp > max_yalphaS ) { tmp = max_yalphaS ; } n = -tmp * log_tabS[(m >> TABSHIFT) & TABMASK] + 0.5; if (m & 0x10000) n = -n; n += oy; if (n < 1) n = PICK_INT(1,oy); else if (n > numRowsG) n = PICK_INT(oy,numRowsG); *y = n; bblckptr = barrayG[n] ; for (i=0; i<2; i++) { m = RAND; tmp = xalS * scale ; if( tmp > max_xalphaS ) { tmp = max_xalphaS ; } n = -tmp * log_tabS[(m >> TABSHIFT) & TABMASK]; if (m & 0x10000) n = -n; n += ox; bleft = bblckptr->bxcenter + bblckptr->bleft ; bright = bblckptr->bxcenter + bblckptr->bright ; if (n < bleft || n > bright) continue; *x = n; return; } if (n < bleft) { if (ox > bright) ox = bright; else if (ox < bleft) ox = bleft; n = PICK_INT(bleft,ox); } else if (n > bright) { if (ox < bleft) ox = bleft; else if (ox > bright) ox = bright; n = PICK_INT(ox,bright); } *x = n; } /* change range limiter according to iterationG number */ update_window_size( iternum ) DOUBLE iternum ; { /* commented out variables CBOXPTR ptr ; INT cell ; */ if( iternum <= HIGHTEMP ){ xalS = max_xalphaS ; yalS = max_yalphaS ; } else if( iternum <= MEDTEMP ){ /* exponential decay xalS and yalS */ /* -------------------------------------------------------- xalS = max_xalphaS * exp( - tauXS * ( iternum - HIGHTEMP )) yalS = max_yalphaS * exp( - tauYS * ( iternum - HIGHTEMP )) -------------------------------------------------------- */ xalS = yalS = iternum - HIGHTEMP ; xalS *= - tauXS ; xalS = max_xalphaS * exp( xalS ) ; yalS *= - tauYS ; yalS = max_yalphaS * exp( yalS ) ; } else { /* low temp */ xalS = min_xalphaS ; yalS = min_yalphaS ; } /* for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { ptr = carrayG[cell] ; if( ptr->fence != NULL ) { ptr->fence->min_xpos = ptr->orig_xcenter - xalS ; ptr->fence->max_xpos = ptr->orig_xcenter + xalS ; if( yalS != min_yalphaS ) { ptr->fence->min_block = ptr->orig_row - (INT) yalS ; if( ptr->fence->min_block < 1 ) { ptr->fence->min_block = 1 ; } ptr->fence->max_block = ptr->orig_row + (INT) yalS ; if( ptr->fence->max_block > numRowsG ) { ptr->fence->max_block = numRowsG ; } } else { ptr->fence->min_block = ptr->orig_row ; ptr->fence->max_block = ptr->orig_row ; } } } */ } save_control( fp ) FILE *fp ; { fprintf(fp,"%d 0 %d\n",pairtestG,not_doneS); fprintf(fp,"%d %d %d %d\n",acc_cntS,move_cntS,first_fdsS,first_capS); fprintf(fp,"%f %f %f %f\n",stepS,xalS,yalS,a_ratioS); fprintf(fp,"%f %f\n",ratioG,total_costS); fprintf(fp,"%f %f\n",bin_capS,row_capS); fprintf(fp,"%f %f %f\n",avg_timeG, avg_funcG, timeFactorG); } read_control( fp ) FILE *fp ; { INT junk ; fscanf(fp,"%ld %ld %ld\n",&pairtestG,&junk,¬_doneS); fscanf(fp,"%ld %ld %ld %ld\n",&acc_cntS,&move_cntS,&first_fdsS,&first_capS); fscanf(fp,"%lf %lf %lf %lf\n",&stepS,&xalS,&yalS,&a_ratioS); fscanf(fp,"%lf %lf\n",&ratioG,&total_costS) ; fscanf(fp,"%lf %lf\n",&bin_capS,&row_capS); fscanf(fp,"%lf %lf %lf\n",&avg_timeG, &avg_funcG, &timeFactorG); } tw_frozen( cost ) INT cost ; { DOUBLE diff , avg_first_set , avg_second_set ; INT i ; if( cost_vectorS[0] >= 12 ) { for( i = 2 ; i <= 12 ; i++ ) { cost_vectorS[i-1] = cost_vectorS[i] ; } cost_vectorS[12] = cost ; avg_first_set = (DOUBLE)(cost_vectorS[1] + cost_vectorS[2] + cost_vectorS[3] + cost_vectorS[4]) / 4.0 ; avg_second_set = (DOUBLE)(cost_vectorS[9] + cost_vectorS[10] + cost_vectorS[11] + cost_vectorS[12]) / 4.0 ; diff = avg_first_set - avg_second_set ; if( diff <= 0.0 ) { return(1) ; } else { if( diff / avg_first_set < 0.004 ) { return(1) ; } else { return(0) ; } } } else { cost_vectorS[ ++(cost_vectorS[0]) ] = cost ; return(0) ; } } graywolf-0.1.4+20170307gite1bf319/src/twsc/unlap.c000066400000000000000000000167751305746555600210360ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: unlap.c DESCRIPTION:remove overlap between cells. CONTENTS: unlap(flag) INT flag ; DATE: Mar 27, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) unlap.c (Yale) version 4.5 10/14/90" ; #endif #endif #include "standard.h" #include "groute.h" /* global variables */ BOOL noPairsG ; /* global references */ extern INT actual_feed_thru_cells_addedG ; extern INT extra_cellsG ; extern BOOL no_feed_at_endG ; extern BOOL rigidly_fixed_cellsG ; unlap(flag) INT flag ; { CBOXPTR cellptr ; INT *num , i , cell_count , last , row , current , limit ; INT cell , block , k ; INT cell_left , left_edge , right_edge ; INT fixed , unfixed ; INT *left_queue , *right_queue , *center_queue ; INT max_cell_in_blk ; INT min_right_fixed_cell ; INT max_left_fixed_cell ; INT pair_array_index ; INT comparex() ; max_cell_in_blk = 0 ; num = (INT *) Ysafe_malloc( ( numRowsG + 1 ) * sizeof(INT) ) ; for( block = 0 ; block <= numRowsG ; block++ ) { num[block] = 0 ; } for( cell = 1 ; cell <= numcellsG ; cell++ ) { if( carrayG[cell]->clength > 0 && carrayG[cell]->cycenter != GATE_ARRAY_MAGIC_CONSTANT ) { num[ carrayG[cell]->cblock ]++ ; } } k = numcellsG + numtermsG + actual_feed_thru_cells_addedG ; for( cell = numcellsG + numtermsG + 1 ; cell <= k ; cell++ ) { num[ carrayG[cell]->cblock ]++ ; } for( block = 1 ; block <= numRowsG ; block++ ) { if( num[block] > max_cell_in_blk ) { max_cell_in_blk = num[block] ; } } pairArrayG = (INT **) Ysafe_malloc( ( numRowsG + 1 ) * sizeof(INT *) ) ; for( block = 1 ; block <= numRowsG ; block++ ) { limit = 5 * max_cell_in_blk + (extra_cellsG / numRowsG) * 4 ; pairArrayG[ block ] = (INT *) Ysafe_malloc( limit * sizeof( INT ) ) ; pairArrayG[block][0] = num[block] ; } left_queue = (INT *) Ysafe_malloc((max_cell_in_blk + 1) * sizeof(INT)); right_queue = (INT *) Ysafe_malloc((max_cell_in_blk + 1) * sizeof(INT)); center_queue = (INT *) Ysafe_malloc((max_cell_in_blk + 1) * sizeof(INT)); for( cell = 1 ; cell <= numcellsG ; cell++ ) { if( carrayG[cell]->clength > 0 && carrayG[cell]->cycenter != -1000001 ) { block = carrayG[cell]->cblock ; pairArrayG[block][ num[block]-- ] = cell ; } } k = numcellsG + numtermsG + actual_feed_thru_cells_addedG ; for( cell = numcellsG + numtermsG + 1 ; cell <= k ; cell++ ) { block = carrayG[cell]->cblock ; pairArrayG[block][ num[block]-- ] = cell ; } for( block = 1 ; block <= numRowsG ; block++ ) { Yquicksort( (char *) ( pairArrayG[block] + 1 ) , pairArrayG[block][0] , sizeof( INT ), comparex ) ; } /* ------- Guarantees fixed-cell orderings now ------- */ for( block = 1 ; block <= numRowsG ; block++ ) { left_edge = barrayG[block]->bxcenter + barrayG[block]->bleft ; right_edge = barrayG[block]->bxcenter + barrayG[block]->bright ; if( ( cell_count = pairArrayG[ block ][0] ) > 1 ) { noPairsG = 0 ; } fixed = FALSE ; unfixed = FALSE ; for( i = 1 ; i <= cell_count ; i++ ) { if( carrayG[pairArrayG[block][i]]->cclass < 0 ) { fixed = TRUE ; } else { unfixed = TRUE ; } } if( !rigidly_fixed_cellsG && fixed == TRUE && unfixed == TRUE ) { for( i = 0 ; i <= max_cell_in_blk ; i++ ) { left_queue[i] = 0 ; right_queue[i] = 0 ; center_queue[i] = 0 ; } max_left_fixed_cell = 0 ; for( i = 1 ; i <= cell_count ; i++ ) { cellptr = carrayG[ pairArrayG[block][i] ] ; if( cellptr->cclass < 0 ) { /* fixed left */ if( left_edge == cellptr->cxcenter + cellptr->tileptr->left ) { left_edge += cellptr->clength ; left_queue[++(*left_queue)] = pairArrayG[block][i]; max_left_fixed_cell = i ; } else { break ; } } } min_right_fixed_cell = cell_count + 1 ; for( i = cell_count ; i >= 1 ; i-- ) { cellptr = carrayG[ pairArrayG[block][i] ] ; if( cellptr->cclass < 0 ) { /* fixed right */ if( right_edge == cellptr->cxcenter + cellptr->tileptr->right ) { right_edge -= cellptr->clength ; right_queue[++(*right_queue)] = pairArrayG[block][i]; min_right_fixed_cell = i ; } else { break ; } } } for( i = 1 ; i <= cell_count ; i++ ) { cellptr = carrayG[ pairArrayG[block][i] ] ; if( (cellptr->cclass >= 0) || /* unfixed */ (cellptr->cclass < 0 && i > max_left_fixed_cell && i < min_right_fixed_cell)) { /* center-fixed */ center_queue[++(*center_queue)] = pairArrayG[block][i]; } } pair_array_index = 0 ; for( i = 1 ; i <= *left_queue ; i++ ) { pairArrayG[block][++pair_array_index] = left_queue[i] ; } for( i = 1 ; i <= *center_queue ; i++ ) { pairArrayG[block][++pair_array_index] = center_queue[i] ; } for( i = *right_queue ; i >= 1 ; i-- ) { pairArrayG[block][++pair_array_index] = right_queue[i] ; } } left_edge = barrayG[block]->bxcenter + barrayG[block]->bleft ; for( i = 1 ; i <= cell_count ; i++ ) { cellptr = carrayG[ pairArrayG[block][i] ] ; cell_left = cellptr->tileptr->left ; if( flag == 2 && cellptr->cxcenter != left_edge - cell_left ) { printf("ERROR cell %d\n", pairArrayG[block][i] ); } cellptr->cxcenter = left_edge - cell_left ; left_edge += cellptr->tileptr->right - cell_left ; } } Ysafe_free( num ) ; Ysafe_free( left_queue ) ; Ysafe_free( right_queue ) ; Ysafe_free( center_queue ) ; /* xcompact() ; */ #ifdef OLD_CRAP if( no_feed_at_end && flag == 1 ) { for( row = 1 ; row <= numRowsG ; row++ ) { last = pairArrayG[row][0] ; carrayG[ pairArrayG[row][1] ]->cclass = -2 ; for( current = 2 ; current <= last ; current++ ) { if( carrayG[ pairArrayG[row][current] ]->cclass >= 0 ) { break ; } carrayG[ pairArrayG[row][current] ]->cclass = -2 ; } carrayG[ pairArrayG[row][last] ]->cclass = -3 ; for( current = last - 1 ; current >= 1 ; current-- ) { if( carrayG[ pairArrayG[row][current] ]->cclass >= 0 ) { break ; } carrayG[ pairArrayG[row][current] ]->cclass = -3 ; } } } #endif return ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/upair.c000066400000000000000000000252061305746555600210240ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: upair.c DESCRIPTION:pairwise flips of cells. CONTENTS: upair() eval_range( acellptr , bcellptr, axc , anxc , bxc , bnxc ) CBOXPTR acellptr , bcellptr ; INT axc , anxc , bxc , bnxc ; DATE: Mar 27, 1989 REVISIONS: Fri Mar 22 16:23:46 CST 1991 - now avoid upair if there are no moveable cells. Fri Sep 6 15:20:48 CDT 1991 - now place pads during pairwise swaps. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) upair.c (Yale) version 4.12 5/12/92" ; #endif #endif #include "standard.h" #include "main.h" #include #include #define PICK_INT(l,u) (((l)<(u)) ? ((RAND % ((u)-(l)+1))+(l)) : (l)) /* global references */ extern INT **pairArrayG ; extern BOOL orientation_optimizationG ; extern BOOL placement_improveG ; upair() { CBOXPTR acellptr, bcellptr ; BBOXPTR ablckptr ; INT a , b , ablock , aorient ; INT flips , attempts , oattempts ; INT axcenter,anxcenter, bnxcenter ; INT aleft , aright ; INT startx1, endx1; INT cellleft, cellrite; INT leftEdge, riteEdge; INT aptr , one_cell_per_row , row ; INT free_cells, cells_in_row ; if(!(placement_improveG)){ return ; } flips = 0 ; attempts = 0 ; oattempts = 0 ; /* ************** place the pads ****************** */ setVirtualCore( TRUE ) ; placepads() ; funccostG = recompute_wirecost() ; timingcostG = recompute_timecost() ; /* assume conditions are true - prove otherwise */ one_cell_per_row = TRUE ; for( row = 1 ; row <= numRowsG ; row++ ) { cells_in_row = pairArrayG[row][0] ; if( cells_in_row > 1 ) { /* at least one row has more than one cell */ /* check to see if we have moveable cells in row */ free_cells = 0 ; for( a = 1; a <= cells_in_row; a++ ){ aptr = pairArrayG[row][a] ; acellptr = carrayG[ aptr ] ; if( acellptr->cclass >= 0 ) { free_cells++ ; } } if( free_cells >= 3 ){ /* need at least three cells to do meaningful work. */ /* otherwise we will spend more time looking for the cells */ one_cell_per_row = FALSE ; break ; } } } if( one_cell_per_row ) { return ; } while( attempts < attmaxG && oattempts < 2 * attmaxG ) { ablock = PICK_INT( 1 , numRowsG ) ; if( pairArrayG[ablock][0] <= 1 ) { continue ; } aptr = PICK_INT( 1 , pairArrayG[ablock][0] ) ; a = pairArrayG[ablock][aptr] ; acellptr = carrayG[ a ] ; if( acellptr->cclass < 0 ) { continue ; } aorient = acellptr->corient ; ablckptr = barrayG[ ablock ] ; axcenter = acellptr->cxcenter ; aleft = acellptr->tileptr->left ; aright = acellptr->tileptr->right ; startx1 = axcenter + aleft ; endx1 = axcenter + aright ; if( orientation_optimizationG ) { goto ort ; } if( aptr > 1 ) { cellleft = pairArrayG[ablock][aptr - 1] ; if( carrayG[cellleft]->cclass < 0 ) { cellleft = 0 ; } } else { cellleft = 0 ; } if( aptr < pairArrayG[ablock][0] ) { cellrite = pairArrayG[ablock][aptr + 1] ; if( carrayG[cellrite]->cclass < 0 ) { cellrite = 0 ; } } else { cellrite = 0 ; } /* if( intel || fences_exist ) { if( cellleft != 0 ) { bcellptr = carrayG[cellleft] ; leftEdge = bcellptr->cxcenter + bcellptr->tileptr->left ; anxcenter = leftEdge - aleft ; bnxcenter = endx1 - bcellptr->tileptr->right ; if( eval_range( acellptr, bcellptr, axcenter, anxcenter, bcellptr->cxcenter, bnxcenter ) == 0 ) { cellleft = 0 ; } } if( cellrite != 0 ) { bcellptr = carrayG[cellrite] ; riteEdge = bcellptr->cxcenter + bcellptr->tileptr->right ; anxcenter = riteEdge - aright ; bnxcenter = startx1 - bcellptr->tileptr->left ; if( eval_range( acellptr, bcellptr, axcenter, anxcenter, bcellptr->cxcenter, bnxcenter ) == 0 ) { cellrite = 0 ; } } } */ if( cellleft == 0 && cellrite == 0 ) { continue ; } if( cellleft != 0 && cellrite != 0 ) { if( PICK_INT(1 , 2) == 1 ){ /* * Take the left neighbor first. */ b = cellleft ; bcellptr = carrayG[b] ; leftEdge = bcellptr->cxcenter + bcellptr->tileptr->left ; anxcenter = leftEdge - aleft ; bnxcenter = endx1 - bcellptr->tileptr->right ; if( ucxxp( a, b, anxcenter, bnxcenter ) ) { flips++ ; attempts++ ; pairArrayG[ablock][aptr] = b ; pairArrayG[ablock][aptr - 1] = a ; } else { attempts++ ; b = cellrite ; bcellptr = carrayG[b] ; riteEdge = bcellptr->cxcenter + bcellptr->tileptr->right ; anxcenter = riteEdge - aright ; bnxcenter = startx1 - bcellptr->tileptr->left ; if( ucxxp( a, b, anxcenter, bnxcenter ) ) { flips++ ; pairArrayG[ablock][aptr] = b ; pairArrayG[ablock][aptr + 1] = a ; } attempts++ ; } } else { b = cellrite ; bcellptr = carrayG[b] ; riteEdge = bcellptr->cxcenter + bcellptr->tileptr->right ; anxcenter = riteEdge - aright ; bnxcenter = startx1 - bcellptr->tileptr->left ; if( ucxxp( a, b, anxcenter, bnxcenter ) ) { flips++ ; attempts++ ; pairArrayG[ablock][aptr] = b ; pairArrayG[ablock][aptr + 1] = a ; } else { attempts++ ; b = cellleft ; bcellptr = carrayG[b] ; leftEdge = bcellptr->cxcenter + bcellptr->tileptr->left; anxcenter = leftEdge - aleft ; bnxcenter = endx1 - bcellptr->tileptr->right ; if( ucxxp( a, b, anxcenter, bnxcenter ) ) { flips++ ; pairArrayG[ablock][aptr] = b ; pairArrayG[ablock][aptr - 1] = a ; } attempts++ ; } } } else { if( cellleft ) { b = cellleft ; bcellptr = carrayG[b] ; leftEdge = bcellptr->cxcenter + bcellptr->tileptr->left ; anxcenter = leftEdge - aleft ; bnxcenter = endx1 - bcellptr->tileptr->right ; if( ucxxp( a, b, anxcenter, bnxcenter ) ) { flips++ ; pairArrayG[ablock][aptr] = b ; pairArrayG[ablock][aptr - 1] = a ; } attempts++ ; } else if( cellrite != 0 && carrayG[cellrite]->cclass >= 0 && acellptr->cclass >= 0 ) { b = cellrite ; bcellptr = carrayG[b] ; riteEdge = bcellptr->cxcenter + bcellptr->tileptr->right ; anxcenter = riteEdge - aright ; bnxcenter = startx1 - bcellptr->tileptr->left ; if( ucxxp( a, b, anxcenter, bnxcenter ) ) { flips++ ; pairArrayG[ablock][aptr] = b ; pairArrayG[ablock][aptr + 1] = a ; } attempts++ ; } } ort:if( ablckptr->borient == 1 ) { if( acellptr->orflag != 0 ) { uc0( a , (aorient == 0) ? 2 : 0 ) ; oattempts++ ; } } else { if( acellptr->orflag != 0 ) { uc0( a , (aorient == 1) ? 3 : 1 ) ; oattempts++ ; } } D( "upair", check_cost() ; ) ; } sprintf( YmsgG, " %3d %6.3f %9d %3d%s %-8ld\n", iterationG+1, TG, funccostG, (INT)( 100.0 * (DOUBLE)(flips) / (DOUBLE)(attmaxG) ) , "%" , timingcostG ) ; M( MSG, NULL, YmsgG ) ; return; } eval_range( acellptr , bcellptr, axc , anxc , bxc , bnxc ) CBOXPTR acellptr , bcellptr ; INT axc , anxc , bxc , bnxc ; { FENCEBOXPTR fence ; INT a_current_penalty , a_new_penalty ; INT b_current_penalty , b_new_penalty ; if( (fence = acellptr->fence) == NULL ) { a_current_penalty = 0 ; } else { a_current_penalty = 10000000 ; } for( fence = acellptr->fence ; fence && a_current_penalty != 0 ; fence = fence->next_fence ) { if( axc < fence->min_xpos ) { if( fence->min_xpos - axc < a_current_penalty ) { a_current_penalty = fence->min_xpos - axc ; } } else if( axc > fence->max_xpos ) { if( axc - fence->max_xpos < a_current_penalty ) { a_current_penalty = axc - fence->max_xpos ; } } else { a_current_penalty = 0 ; } } if( (fence = bcellptr->fence) == NULL ) { b_current_penalty = 0 ; } else { b_current_penalty = 10000000 ; } for( ; fence && b_current_penalty != 0 ; fence = fence->next_fence ) { if( bxc < fence->min_xpos ) { if( fence->min_xpos - bxc < b_current_penalty ) { b_current_penalty = fence->min_xpos - bxc ; } } else if( bxc > fence->max_xpos ) { if( bxc - fence->max_xpos < b_current_penalty ) { b_current_penalty = bxc - fence->max_xpos ; } } else { b_current_penalty = 0 ; } } if( (fence = acellptr->fence) == NULL ) { a_new_penalty = 0 ; } else { a_new_penalty = 10000000 ; } for( ; fence && a_new_penalty != 0 ; fence = fence->next_fence ) { if( anxc < fence->min_xpos ) { if( fence->min_xpos - anxc < a_new_penalty ) { a_new_penalty = fence->min_xpos - anxc ; } } else if( anxc > fence->max_xpos ) { if( anxc - fence->max_xpos < a_new_penalty ) { a_new_penalty = anxc - fence->max_xpos ; } } else { a_new_penalty = 0 ; } } if( (fence = bcellptr->fence) == NULL ) { b_new_penalty = 0 ; } else { b_new_penalty = 10000000 ; } for( ; fence && b_new_penalty != 0 ; fence = fence->next_fence ) { if( bnxc < fence->min_xpos ) { if( fence->min_xpos - bnxc < b_new_penalty ) { b_new_penalty = fence->min_xpos - bnxc ; } } else if( bnxc > fence->max_xpos ) { if( bnxc - fence->max_xpos < b_new_penalty ) { b_new_penalty = bnxc - fence->max_xpos ; } } else { b_new_penalty = 0 ; } } if( a_new_penalty + b_new_penalty <= a_current_penalty + b_current_penalty ) { return(1) ; } else { return(0) ; } } graywolf-0.1.4+20170307gite1bf319/src/twsc/urcost.c000066400000000000000000000152771305746555600212320ustar00rootroot00000000000000/* * Copyright (C) 1989-1991 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: urcost.c DESCRIPTION:update global routing cost. CONTENTS: urcost( segptr ) SEGBOXPTR segptr ; DATE: Mar 27, 1989 REVISIONS: Tue Mar 19 16:22:56 CST 1991 - fixed crash when there are no routing tracks in a channel. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) urcost.c (Yale) version 4.4 3/19/91" ; #endif #endif #include "standard.h" #include "groute.h" #include urcost( segptr ) SEGBOXPTR segptr ; { CHANGRDPTR aptr1 , aptr2 , bptr1 , bptr2 , ptr ; DENSITYPTR denptr , headptr ; INT penalty , check ; INT x , achannel , bchannel , aMaxVal , bMaxVal ; INT maxaa , maxbb , pin1 , pin2 ; INT aoutside , binside ; INT ax1 , ax2 , bx1 , bx2 ; INT track ; penalty = 0 ; pin1 = segptr->pin1ptr->terminal ; pin2 = segptr->pin2ptr->terminal ; if( segptr->switchvalue == swUP ) { aptr1 = TgridG[pin1]->up ; aptr2 = TgridG[pin2]->up ; bptr1 = TgridG[pin1]->down ; bptr2 = TgridG[pin2]->down ; bchannel = segptr->pin1ptr->row ; achannel = bchannel + 1 ; } else { aptr1 = TgridG[pin1]->down ; aptr2 = TgridG[pin2]->down ; bptr1 = TgridG[pin1]->up ; bptr2 = TgridG[pin2]->up ; achannel = segptr->pin1ptr->row ; bchannel = achannel + 1 ; } aMaxVal = maxTrackG[achannel] ; bMaxVal = maxTrackG[bchannel] ; ax1 = aptr1->netptr->xpos ; ax2 = aptr2->netptr->xpos ; bx1 = bptr1->netptr->xpos ; bx2 = bptr2->netptr->xpos ; aoutside = 0 ; denptr = DboxHeadG[ achannel ][ aMaxVal ]->next ; for( ; denptr != DENSENULL ; denptr = denptr->next ) { x = denptr->grdptr->netptr->xpos ; if( !( ax1 <= x && ax2 >= x ) || denptr->grdptr->cross > 1 ) { aoutside = 1 ; break ; } } if( aoutside == 0 ) { penalty-- ; } binside = 0 ; denptr = DboxHeadG[ bchannel ][ bMaxVal ]->next ; for( ; denptr != DENSENULL ; denptr = denptr->next ) { x = denptr->grdptr->netptr->xpos ; if( bx1 <= x && bx2 >= x && denptr->grdptr->cross == 0 ) { binside = 1 ; break ; } } if( binside == 1 ) { penalty++ ; } while( aptr1->prevgrd ) { if( aptr1->prevgrd->netptr->xpos == ax1 ) { aptr1 = aptr1->prevgrd ; } else { break ; } } while( aptr2->nextgrd ) { if( aptr2->nextgrd->netptr->xpos == ax2 ) { aptr2 = aptr2->nextgrd ; } else { break ; } } while( bptr1->prevgrd ) { if( bptr1->prevgrd->netptr->xpos == bx1 ) { bptr1 = bptr1->prevgrd ; } else { break ; } } while( bptr2->nextgrd ) { if( bptr2->nextgrd->netptr->xpos == bx2 ) { bptr2 = bptr2->nextgrd ; } else { break ; } } aptr2 = aptr2->nextgrd ; bptr2 = bptr2->nextgrd ; if( penalty == 0 ) { if( binside == 1 && aoutside == 0 ) { /* check = (aMaxVal - 1) - (bMaxVal + 1) ; */ check = ABS(aMaxVal - bMaxVal - 2) - ABS(bMaxVal - aMaxVal) ; } else { maxaa = 0 ; maxbb = 0 ; for( ptr = aptr1 ; ptr != aptr2 ; ptr = ptr->nextgrd ) { if( ptr->tracks > maxaa ) { maxaa = ptr->tracks ; } } for( ptr = bptr1 ; ptr != bptr2 ; ptr = ptr->nextgrd ) { if( ptr->tracks > maxbb ) { maxbb = ptr->tracks ; } } /* maxaa = aMaxVal - maxaa + 1 ; */ /* maxbb = bMaxVal - maxbb - 1 ; */ /* check = maxaa - maxbb ; */ check = ABS(aMaxVal - maxaa - bMaxVal + maxbb + 2) - ABS(aMaxVal - maxaa - bMaxVal + maxbb) ; } } else { check = penalty ; } if( check <= 0 ) { for( ptr = aptr1 ; ptr != aptr2 ; ptr = ptr->nextgrd ) { denptr = ptr->dptr ; if( ptr->cross == 1 ) { ptr->cross = 0 ; if( denptr->next != DENSENULL ) { denptr->next->back = denptr->back ; } denptr->back->next = denptr->next ; track = --(ptr->tracks) ; if( track == -1 ){ track = 0 ; D( "twsc/urcost", fprintf( stderr, " track less than 1 reset to 0\n" ) ; ) ; } headptr = DboxHeadG[ achannel ][ track ]->next ; if( headptr != DENSENULL ) { DboxHeadG[ achannel ][ track ]->next = denptr ; denptr->next = headptr ; headptr->back = denptr ; denptr->back = DboxHeadG[ achannel ][ track ] ; } else { DboxHeadG[ achannel ][ track ]->next = denptr ; denptr->next = DENSENULL ; denptr->back = DboxHeadG[ achannel ][ track ]; } } else { ptr->cross-- ; } } if( aoutside == 0 ) { maxTrackG[achannel]-- ; } for( ptr = bptr1 ; ptr != bptr2 ; ptr = ptr->nextgrd ) { denptr = ptr->dptr ; if( ptr->cross == 0 ) { ptr->cross = 1 ; if( denptr->next != DENSENULL ) { denptr->next->back = denptr->back ; } denptr->back->next = denptr->next ; track = ++(ptr->tracks) ; headptr = DboxHeadG[ bchannel ][ track ]->next ; if( headptr != DENSENULL ) { DboxHeadG[ bchannel ][ track ]->next = denptr ; denptr->next = headptr ; headptr->back = denptr ; denptr->back = DboxHeadG[ bchannel ][ track ] ; } else { DboxHeadG[ bchannel ][ track ]->next = denptr ; denptr->next = DENSENULL ; denptr->back = DboxHeadG[ bchannel ][ track ]; } } else { ptr->cross++ ; } } if( binside == 1 ) { maxTrackG[bchannel]++ ; } if( segptr->switchvalue == swUP ) { segptr->switchvalue = swDOWN ; } else { segptr->switchvalue = swUP ; } tracksG += penalty ; return (1) ; } else { return (0) ; } } graywolf-0.1.4+20170307gite1bf319/src/twsc/utemp.c000066400000000000000000000532261305746555600210410ustar00rootroot00000000000000/* * Copyright (C) 1989-1992 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: utemp.c DESCRIPTION:outer loop of simulated annealing algorithm. CONTENTS: utemp() from_middle() from_beginning() INT compute_attprcel(flag) INT flag; rm_overlapping_feeds() refine_placement() simple_refine_placement() parametric_refine( k_max , k_limit ) INT k_max, k_limit ; route_only_critical_nets() elim_nets() DATE: Mar 27, 1989 REVISIONS: Fri Jan 25 23:45:25 PST 1991 - added user meter. Mon Aug 12 17:01:03 CDT 1991 - changed timing ASSERTIONS to D( ) constructs to speed execution time during debug mode. Thu Aug 22 22:27:18 CDT 1991 - Carl made changes for rigidly fixed cells. ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) utemp.c (Yale) version 4.19 4/5/92" ; #endif #endif #include "standard.h" #include "main.h" #include "groute.h" #include "ucxxglb.h" #include "readpar.h" #include "parser.h" #include #include /* global variables */ INT moveable_cellsG ; BOOL pairtestG; BOOL no_row_lengthsG ; /* global variable references */ extern INT attprcelG ; extern INT spacer_widthG ; extern INT orig_max_row_lengthG ; extern BOOL noPairsG ; extern BOOL good_initial_placementG ; extern BOOL orientation_optimizationG ; extern BOOL stand_cell_as_gate_arrayG ; extern BOOL prop_rigid_cellsG ; extern BOOL rigidly_fixed_cellsG ; extern DOUBLE finalRowControlG ; extern DOUBLE initialRowControlG ; extern DOUBLE ratioG; INT comparex() ; INT compute_attprcel() ; utemp() { INT check ; unsigned i2 ; INT i , freeze ; if( orientation_optimizationG ) { pairtestG = TRUE ; } fraction_doneG = 0.0 ; check = 0 ; freeze = 10000000 ; init_table() ; attprcelG = compute_attprcel(1); if( pairtestG == 0 ) { attmaxG = attprcelG * moveable_cellsG ; if( iterationG < 1 ) { resume_runG = 0 ; } if( !resume_runG && !good_initial_placementG ) { from_beginning() ; } else if( resume_runG ) { from_middle() ; } } for( ; ; ) { if( pairtestG == FALSE && TG >= 0.01 ) { uloop() ; savewolf(0) ; } else { D( "twsc/after_annealing", G( process_graphics() ) ; ) ; pairtestG = TRUE ; if( check == 0 ) { check = 1 ; savewolf(0) ; freeze = iterationG ; if( connection_machineG == TRUE ) { findunlap(0) ; outcm() ; } findunlap(0) ; #ifndef MITLL if( SGGRG || (!doglobalG) ) { even_the_rows(0,FALSE) ; M( MSG, NULL,"evening the row lengths\n") ; findunlap(0) ; } #else if( check_row_lengths() ) { gate_array_even_the_rows(0) ; M( MSG, NULL,"evening the row lengths\n") ; findunlap(0) ; for( i = 1 ; i <= 5 ; i++ ) { if( check_row_lengths() ) { sprintf(YmsgG,"evening the row lengths %d\n", i+1) ; M( MSG, NULL, YmsgG ) ; even_the_rows_2( i ) ; findunlap(0) ; } } } #endif penaltyG = 0 ; /* * This computes new wire costs for the compacted * placement (and feed insertion). It calls unlap() * which sorts and places the cells end-to-end */ M( MSG, NULL,"Removed the cell overlaps --- "); M( MSG, NULL,"Will do neighbor interchanges only now\n"); sprintf( YmsgG, "\nTOTAL INTERCONNECT LENGTH: %d\n",funccostG); M( MSG, NULL, YmsgG ) ; sprintf(YmsgG,"initialRowControl:%8.3f\n", initialRowControlG); M( MSG, NULL, YmsgG ) ; sprintf(YmsgG,"finalRowControl:%8.3f\n", finalRowControlG); M( MSG, NULL, YmsgG ) ; fflush(fpoG); attmaxG = 5 * moveable_cellsG ; if( noPairsG == 0 ) { TG = 0.001 ; M( MSG, NULL, "iter T Wire accept Time\n" ) ; upair() ; savewolf(1) ; } } else { if( noPairsG == 0 ) { TG = 0.001 ; upair() ; savewolf(1) ; } } print_paths() ; } if(!(Ymessage_get_mode() )){ /* if we aren't dumping everything to the screen */ /* show iteration number */ USER_INCR_METER() ; printf("%3d ", iterationG ); if( iterationG % 15 == 0 ) { printf("\n"); } } ++iterationG; fflush( stdout ) ; G( check_graphics(TRUE) ) ; if( iterationG >= freeze + 3 ) { ASSERT( dprint_error(), NULL, NULL ) ; if( doglobalG ) { execute_global_router() ; } else { findunlap(0) ; output() ; } sprintf(YmsgG,"FINAL TOTAL INTERCONNECT LENGTH: %d\n",funccostG); M( MSG, NULL, YmsgG ) ; sprintf(YmsgG,"FINAL OVERLAP PENALTY: %d ", penaltyG ); M( MSG, NULL, YmsgG ) ; sprintf(YmsgG, "FINAL VALUE OF TOTAL COST IS: %d\n", funccostG + penaltyG ) ; M( MSG, NULL, YmsgG ) ; sprintf(YmsgG,"MAX NUMBER OF ATTEMPTED FLIPS PER T:%8d\n",attmaxG); M( MSG, NULL, YmsgG ) ; break ; } } return ; } from_middle() { init_control(-1); /* set move generation controller. */ attmaxG = attprcelG * moveable_cellsG ; M( MSG, NULL, "\nIter T fds Wire Penal Time P_lim "); M( MSG, NULL, " err binC rowC timeC s/p rej. Acc.\n"); sprintf(YmsgG,"%3d: %6.2le %6ld %-8ld %-6ld %-6ld", iterationG++,0.0,0,funccostG,rowpenalG,timingcostG); M( MSG, NULL, YmsgG ) ; sprintf(YmsgG,"%6ld %4.2lf %4.2lf %5.2lf %4.2lf %4.2lf %4.2lf %5.3lf\n", P_limitG,0.0,binpenConG,roLenConG,timeFactorG,0.0,0.0,ratioG); M( MSG, NULL, YmsgG ) ; fflush(fpoG); } from_beginning() { init_uloop(); init_control(1); /* set move generation controller. */ attmaxG = attprcelG * moveable_cellsG ; iterationG = -1 ; TG = 1.0e10; /* set to VERY HIGH temperature. */ uloop(); if( moveable_cellsG < 300 ) { attmaxG *= 2; } /* collect statistics */ uloop(); /* discard old result and try again. */ /* init_parameters(attmax,ratio) ; */ attmaxG = attprcelG * moveable_cellsG ; M( MSG, NULL, "\nIter T fds Wire Penal Time P_lim "); if( swappable_gates_existG ) { M( MSG, NULL, " err binC rowC timeC s/p rej. Acc."); M( MSG, NULL, " g_sw Vwt\n"); } else { M( MSG, NULL, " err binC rowC timeC s/p rej. Acc. Vwt\n"); } sprintf(YmsgG,"%3d: %6.2le %6ld %-8ld %-6ld %-8ld", iterationG++,0.0,0,funccostG,rowpenalG,timingcostG ); M( MSG, NULL, YmsgG ) ; sprintf(YmsgG,"%6ld %4.2lf %4.2lf %5.2lf %5.2lf %4.2lf %4.2lf %5.3lf\n", P_limitG,0.0,binpenConG,roLenConG,timeFactorG,0.0,0.0,ratioG); M( MSG, NULL, YmsgG ) ; fflush(fpoG); } INT compute_attprcel(flag) INT flag; { INT cell, n; /* 1 March 1990 by Carl if( gate_array ) { for( cell = 1 ; cell <= numcellsG - extra_cellsG ; cell++ ) { if( !rigidly_fixed_cellsG ) { if( carrayG[cell]->cclass < 0 ) { continue ; } } moveable_cells++ ; } } else { for( cell = 1 ; cell <= numcellsG ; cell++ ) { if( !rigidly_fixed_cellsG ) { if( carrayG[cell]->cclass < 0 ) { continue ; } } moveable_cells++ ; } } */ moveable_cellsG = numcellsG - extra_cellsG ; if( moveable_cellsG <= 500 ) { if( moveable_cellsG <= 0 ){ M( ERRMSG, "compute_attprcel", "FATAL:no moveable cells\n" ) ; YexitPgm( PGMFAIL ) ; } n = 12500 / moveable_cellsG ; } else { /* n to the 4/3 power */ n = (INT)(25.0 * pow( (DOUBLE) moveable_cellsG / 500.0, 1.0 / 3.0 ) ) ; } if( flag && tw_fastG ) { n /= tw_fastG ; } else if( tw_slowG ) { n *= tw_slowG ; } return(n); } rm_overlapping_feeds() { INT row , cell , *rowptr , target ; INT cells_in_row , index , num_deleted ; IPBOXPTR imptr , save_ptr ; num_deleted = 0 ; for( row = 1 ; row <= numRowsG ; row++ ) { rowptr = pairArrayG[row] ; cells_in_row = pairArrayG[row][0] ; index = 0 ; while( ++index < cells_in_row ) { cell = rowptr[index] ; if( carrayG[cell]->corient <= 1 ) { /* delete the last feed */ target = carrayG[cell]->tileptr->right ; } else { /* delete the first feed */ target = carrayG[cell]->tileptr->left ; } imptr = carrayG[cell]->imptr ; if( imptr != NULL ) { if( imptr->txpos == target ) { save_ptr = imptr->next ; Ysafe_free( imptr ) ; num_deleted++ ; carrayG[cell]->imptr = save_ptr ; } else { while( imptr->next != NULL ) { if( imptr->next->txpos == target ) { save_ptr = imptr->next->next ; Ysafe_free( imptr->next ) ; num_deleted++ ; imptr->next = save_ptr ; break ; } imptr = imptr->next ; } } } } } return( num_deleted ) ; } route_only_critical_nets() { GLISTPTR pptr ; /* pointer to paths of a cell */ GLISTPTR net_of_path ; PATHPTR path ; INT path_num , net , cell ; for( net = 1 ; net <= numnetsG ; net++ ) { netarrayG[net]->ignore = -1 ; } for( cell = 1 ; cell <= numcellsG ; cell++ ) { for( pptr = carrayG[cell]->paths; pptr ; pptr = pptr->next ) { path_num = pptr->p.path ; path = patharrayG[path_num] ; for( net_of_path=path->nets;net_of_path; net_of_path=net_of_path->next ){ netarrayG[net_of_path->p.net]->ignore = 0 ; } } } elim_nets(0) ; return ; } elim_nets(print_flag) INT print_flag ; { DBOXPTR dimptr; /* bounding box for net */ PINBOXPTR netptr ; /* traverse the pins on a net */ PINBOXPTR pinptr ; /* traverse the pins on a cell */ PINBOXPTR freepin ; /* used to free the pin box record */ INT net , cell ; for( net = 1 ; net <= numnetsG ; net++ ) { dimptr = netarrayG[net] ; if( (INT) dimptr->ignore == -1 ) { /* we are not to global route this net */ /* therefore we eliminate this net from the data structures */ if( print_flag ) { sprintf(YmsgG,"Global router is eliminating net: <%s>\n", netarrayG[net]->name ) ; M( MSG, NULL, YmsgG ) ; } for( netptr = dimptr->pins ; netptr ; ) { cell = netptr->cell ; /* need to free all pins on netarray list and */ /* cell list of pins */ pinptr = carrayG[cell]->pins ; if( pinptr == NULL ) { /* this should never occur WPS */ sprintf( YmsgG, "cell:%d pinlist is null\n", cell ) ; M( ERRMSG, "elim_nets", YmsgG ) ; continue ; } /* look for matching pin in cell list of pins */ if( pinptr == netptr ) { /* eliminate this pin on the cell */ carrayG[cell]->pins = pinptr->nextpin ; } else { for( ; pinptr->nextpin ; pinptr = pinptr->nextpin ) { if( pinptr->nextpin == netptr ) { /* eliminate this pin on the cell */ pinptr->nextpin = pinptr->nextpin->nextpin; break ; } } } freepin = netptr ; netptr = netptr->next ; Ysafe_free( freepin ) ; } dimptr->pins = NULL ; /* null reference to list */ dimptr->numpins = 0 ; } } return ; } refine_fixed_placement() { CBOXPTR cellptr , cellptr1 ; PINBOXPTR termptr ; INT *rowptr , *rowptr1 , *rowptr2 , **p_array , *p_rowptr ; INT *spacer_list, *moveable_list, *next_limit, *next_index, *filled_to ; INT slack, row, last_index, i, index, count , limit ; INT cells_in_row, target, last_cell, ok, min, save_row ; INT save_m, min_slack, m, all_l_fit, cell, first_index, prev_cell ; INT success , filled_to_edge , target_edge , width , gap , shift ; INT block, start, end, max_row_length , right_boundary ; DOUBLE scale ; next_limit = (INT *) Ysafe_malloc( (1 + numRowsG) * sizeof(INT) ) ; next_index = (INT *) Ysafe_malloc( (1 + numRowsG) * sizeof(INT) ) ; filled_to = (INT *) Ysafe_malloc( (1 + numRowsG) * sizeof(INT) ) ; /* create list of spacer cells */ spacer_list = (INT *) Ysafe_malloc( (1 + extra_cellsG) * sizeof(INT) ) ; spacer_list[0] = extra_cellsG ; count = numcellsG + 1 ; for( i = 1 ; i <= extra_cellsG ; i++ ) { spacer_list[i] = --count ; carrayG[count]->clength = spacer_widthG ; carrayG[count]->cycenter = GATE_ARRAY_MAGIC_CONSTANT ; } limit = 1 ; for( row = 1 ; row <= numRowsG ; row++ ) { if( pairArrayG[row][0] > limit ) { limit = pairArrayG[row][0] ; } } limit += 1 + (extra_cellsG / numRowsG) * 4 ; /* create temporary pairArray */ p_array = (INT **) Ysafe_malloc( ( numRowsG + 1 ) * sizeof(INT *) ) ; for( row = 1 ; row <= numRowsG ; row++ ) { p_array[row] = (INT *) Ysafe_malloc( limit * sizeof( INT ) ) ; } /* begin the refinement process */ moveable_list = (INT *) Ysafe_malloc( (1 + numcellsG) * sizeof(INT) ) ; /* for Dick Davis of DEC */ if( prop_rigid_cellsG ) { /* find longest row */ max_row_length = 0 ; for( block = 1 ; block <= numRowsG ; block++ ) { start = carrayG[ pairArrayG[block][1] ]->cxcenter + carrayG[ pairArrayG[block][1] ]->tileptr->left ; end = carrayG[ pairArrayG[block][ pairArrayG[block][0] ] ]->cxcenter + carrayG[ pairArrayG[block][ pairArrayG[block][0] ] ]->tileptr->right ; if( max_row_length < end - start ) { max_row_length = end - start ; } } scale = (DOUBLE) max_row_length / (DOUBLE) orig_max_row_lengthG ; } for( row = 1 ; row <= numRowsG ; row++ ) { moveable_list[0] = 0 ; /* initialize p_array, the temporary pairArray */ cells_in_row = pairArrayG[row][0] ; last_cell = pairArrayG[row][cells_in_row] ; right_boundary = carrayG[last_cell]->cxcenter + carrayG[last_cell]->tileptr->right ; if( right_boundary < barrayG[row]->bxcenter + barrayG[row]->bright ) { right_boundary = barrayG[row]->bxcenter + barrayG[row]->bright ; } for( i = 0 ; i <= cells_in_row ; i++ ) { p_array[row][i] = pairArrayG[row][i] ; } /* leave only fixed cells in p_array at the start of the process */ rowptr = p_array[row] ; cells_in_row = rowptr[0] ; rowptr[0] = 0 ; for( i = 1 ; i <= cells_in_row ; i++ ) { cell = rowptr[i] ; cellptr = carrayG[cell] ; if( cellptr->cclass < 0 ) { /* was "== -5" */ if( cellptr->border >= 0 ) { if( prop_rigid_cellsG ) { target = (INT)( (DOUBLE) cellptr->border * scale ) ; if( gate_arrayG ) { while( target % spacer_widthG != 0 ) { target++ ; } } target += barrayG[row]->bxcenter + barrayG[row]->bleft ; } else { target = cellptr->border + barrayG[row]->bxcenter + barrayG[row]->bleft ; } } else if( cellptr->border < -1 ) { target = cellptr->border + right_boundary - cellptr->clength ; } else { target = right_boundary - cellptr->clength ; } /* cellptr->cxcenter = target - cellptr->tileptr->left ; */ shift = target - cellptr->tileptr->left - cellptr->cxcenter ; cellptr->cxcenter += shift ; /* ...update pin positions now..... */ for( termptr = cellptr->pins; termptr; termptr = termptr->nextpin ) { termptr->xpos += shift ; } rowptr[ ++rowptr[0] ] = cell ; } else { moveable_list[ ++moveable_list[0] ] = cell ; } } Yquicksort( (char *) ( rowptr + 1 ) , rowptr[0] , sizeof( INT ), comparex ) ; Yquicksort( (char *) ( moveable_list + 1 ) , moveable_list[0] , sizeof( INT ), comparex ) ; /* initialize filled_to[] and next_limit[] */ last_cell = p_array[row][0] ; filled_to[row] = barrayG[row]->bxcenter + barrayG[row]->bleft; i = 1 ; next_index[row] = 1 ; /* index yielding the next limit */ while( i <= last_cell ) { cellptr = carrayG[ p_array[row][i] ] ; next_limit[row] = cellptr->cxcenter+cellptr->tileptr->left; if( next_limit[row] == filled_to[row] ) { i++ ; filled_to[row] += cellptr->clength ; next_index[row]++ ; } else { break ; } } if( i > last_cell ) { next_index[row] = -1 ; next_limit[row] = 10000000 ; } /* begin the placement of the moveable cells */ while( moveable_list[0] > 0 ) { if( filled_to[row] == 10000000 ) { break ; } /* min_slack = 20000000 ; */ save_m = -1 ; /* all_l_fit = 1 ; */ /* look ahead by 1 cells in the moveable_list */ for( m = 1 ; m <= 1 ; m++ ) { if( m > moveable_list[0] ) { break ; } slack = next_limit[row] - (filled_to[row] + carrayG[ moveable_list[m] ]->clength) ; if( slack >= 0 ) { save_m = m ; break ; } /* if( slack < 0 ) { all_l_fit = 0 ; } if( slack >= 0 && slack < min_slack ) { min_slack = slack ; save_m = m ; } */ } /* if( all_l_fit && save_m > 0 ) { save_m = 1 ; } */ if( save_m == -1 ) { /* none fit */ if( next_index[row] != -1 ) { cellptr = carrayG[ p_array[row][ next_index[row] ] ]; gap = next_limit[row] - filled_to[row] ; /* New: 1 March 1990 by Carl */ if( cellptr->cclass != -5 ) { /* let it slide a bit */ cellptr->cxcenter -= gap ; /* ...update pin positions now..... */ for( termptr = cellptr->pins; termptr; termptr = termptr->nextpin ) { termptr->xpos -= gap ; } } filled_to[row] = cellptr->cxcenter + cellptr->tileptr->right ; last_cell = p_array[row][0] ; i = ++next_index[row] ; while( i <= last_cell ) { cellptr = carrayG[ p_array[row][i] ] ; next_limit[row] = cellptr->cxcenter + cellptr->tileptr->left; if( next_limit[row] == filled_to[row] ) { i++ ; filled_to[row] += cellptr->clength ; next_index[row]++ ; } else { break ; } } if( i > last_cell ) { next_index[row] = -1 ; next_limit[row] = 10000000 ; } } else { /* can't add to this row and can't get another limit */ filled_to[row] = 10000000 ; } } else { /* we can profitably add the cell to "row" */ cellptr = carrayG[ moveable_list[save_m] ] ; cellptr->cycenter = barrayG[row]->bycenter ; cellptr->cblock = row ; if( next_index[row] != -1 ) { last_index = next_index[row]++ ; first_index = p_array[row][0] ; index = first_index ; for( ; index >= last_index ; index-- ) { p_array[row][index+1] = p_array[row][index] ; } p_array[row][0]++ ; p_array[row][last_index] = moveable_list[save_m] ; } else { last_index = ++p_array[row][0] ; p_array[row][last_index] = moveable_list[save_m] ; } if( last_index > 1 ) { prev_cell = p_array[row][last_index-1] ; /* cellptr->cxcenter = carrayG[prev_cell]->cxcenter + carrayG[prev_cell]->tileptr->right - cellptr->tileptr->left ; */ shift = carrayG[prev_cell]->cxcenter + carrayG[prev_cell]->tileptr->right - cellptr->tileptr->left - cellptr->cxcenter ; cellptr->cxcenter += shift ; /* ...update pin positions now..... */ for( termptr = cellptr->pins; termptr; termptr = termptr->nextpin ) { termptr->xpos += shift ; } } else { /* cellptr->cxcenter = barrayG[row]->bxcenter + barrayG[row]->bleft - cellptr->tileptr->left; */ shift = barrayG[row]->bxcenter + barrayG[row]->bleft - cellptr->tileptr->left - cellptr->cxcenter ; cellptr->cxcenter += shift ; /* ...update pin positions now..... */ for( termptr = cellptr->pins; termptr; termptr = termptr->nextpin ) { termptr->xpos += shift ; } } filled_to[row] += cellptr->clength ; last_index = moveable_list[0] ; for( index = save_m + 1 ; index <= last_index ; index++ ) { moveable_list[index-1] = moveable_list[index] ; } moveable_list[0]-- ; } } } /* Now insert the spacers */ for( row = 1 ; row <= numRowsG ; row++ ) { filled_to_edge = barrayG[row]->bxcenter + barrayG[row]->bleft ; p_rowptr = p_array[row] ; rowptr = pairArrayG[row] ; rowptr[0] = 0 ; last_index = p_rowptr[0] ; for( index = 1 ; index <= last_index ; index++ ) { cellptr1 = carrayG[ p_rowptr[index] ] ; width = cellptr1->clength ; target_edge = cellptr1->cxcenter + cellptr1->tileptr->left ; if( rigidly_fixed_cellsG ) { while( filled_to_edge < target_edge ) { if( spacer_list[0] == 0 ) { /* attempt fails */ return(0); } cell = spacer_list[ spacer_list[0]-- ] ; rowptr[++rowptr[0]] = cell ; carrayG[cell]->cycenter = barrayG[row]->bycenter ; carrayG[cell]->cblock = row ; carrayG[cell]->cxcenter = filled_to_edge - carrayG[cell]->tileptr->left ; filled_to_edge += spacer_widthG ; } } rowptr[++rowptr[0]] = p_rowptr[index] ; filled_to_edge += width ; } } sprintf(YmsgG,"\nActually added %d gate array spacers\n", extra_cellsG - spacer_list[0] ) ; M( MSG, NULL, YmsgG ) ; /* nullify the other nonused spacer cells */ last_index = spacer_list[0] ; for( index = 1 ; index <= last_index ; index++ ) { carrayG[ spacer_list[index] ]->clength = 0 ; } Ysafe_free( spacer_list ) ; Ysafe_free( moveable_list ) ; for( row = 1 ; row <= numRowsG ; row++ ) { Ysafe_free( p_array[row] ) ; } Ysafe_free( p_array ) ; Ysafe_free( next_limit ) ; Ysafe_free( next_index ) ; Ysafe_free( filled_to ) ; return(1) ; } graywolf-0.1.4+20170307gite1bf319/src/twsc/xpickint.c000066400000000000000000000042301305746555600215270ustar00rootroot00000000000000/* * Copyright (C) 1989-1990 Yale University * * This work is distributed in the hope that it will be useful; you can * redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, * or any later version, on the following conditions: * * (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS * ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE, * SALE OR * OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY * PATENT OR * OTHER RIGHTS NOT VESTED IN YALE. * * (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND * WARRANTIES * WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED, * INCLUDING, * BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR * PURPOSE. * * (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES * WHATSOEVER TO * ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN * ARTICLE * (a) AND (b) above. * * (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS, * EMPLOYEES AND * AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR * INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE * ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE * POSSIBILITY OF THE FOREGOING. * */ /* ----------------------------------------------------------------- FILE: xpickint.c DESCRIPTION:pick a random number. CONTENTS: XPICK_INT( l , u , c ) INT l , u , c ; DATE: Mar 27, 1989 REVISIONS: ----------------------------------------------------------------- */ #ifndef VMS #ifndef lint static char SccsId[] = "@(#) xpickint.c (Yale) version 4.4 9/7/90" ; #endif #endif #include #define PICK_INT(l,u) (((l)<(u)) ? ((RAND % ((u)-(l)+1))+(l)) : (l)) XPICK_INT( l , u , c ) INT l , u , c ; { INT d ; if ( c < 0 ) { return(-c) ; } else { do { d = PICK_INT(l,u) ; } while ( d == c ) ; return(d) ; } }