Compare commits

..

No commits in common. "devel" and "devel_no_lemon" have entirely different histories.

8973 changed files with 129643 additions and 2188792 deletions

38
.dir-locals.el Normal file
View File

@ -0,0 +1,38 @@
((nil . ((company-clang-arguments
. ("-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/ccore/agds"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/ccore/alliance/ap"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/ccore/alliance/vst"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/ccore/bookshelf"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/ccore/cif"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/ccore/crlcore"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/ccore/lefdef"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/ccore/liberty"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/ccore/openaccess"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/ccore/spice"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/ccore/toolbox"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/cyclop"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/fonts"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/LibraryManager/crlcore"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/crlcore/src/pyCRL/crlcore"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/equinox/src/equinox"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/equinox/src/intervalTree/src/equinox"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/etesian/src/etesian"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/hurricane/src/hurricane/hurricane"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/hurricane/src/isobar/hurricane/isobar"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/hurricane/src/viewer/hurricane/viewer"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/hurricane/src/viewer/obsoletes"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/katabatic/src/katabatic"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/kite/src/kite"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/knik/src/knik"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/solstice/src/solstice"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/unicorn/src/unicorn"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/vlsisapd/src/agds/src/vlsisapd/agds"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/vlsisapd/src/bookshelf/src/vlsisapd/bookshelf"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/vlsisapd/src/cif/src/vlsisapd/cif"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/vlsisapd/src/configuration/src/vlsisapd/configuration"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/vlsisapd/src/dtr/src/vlsisapd/dtr"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/vlsisapd/src/liberty/src/vlsisapd/liberty"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/vlsisapd/src/openChams/src/vlsisapd/openChams"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/vlsisapd/src/spice/src/vlsisapd/spice"
"-I/dsk/l1/jpc/coriolis-2.x/src/coriolis/vlsisapd/src/utilities/src/vlsisapd/utilities"
)))))

7
.gitignore vendored
View File

@ -8,10 +8,7 @@ TAGS
GTAGS
GPATH
GRTAGS
.dir-locals.el
.projectile
lefdef/src/lef/lef/lef.tab.h
man/
rtf/
@ -37,7 +34,3 @@ documentation/RDS/RDS.pdf
documentation/RDS/RDS.tex
documentation/RDS/RDS.toc
cumulus/src/plugins/CoreToChip_c35b4.py
cumulus/src/plugins/core2chip/c35b4.py
/result*

View File

@ -1,54 +0,0 @@
linux:
image: python:3.8
# make a docker daemon available for cibuildwheel to use
services:
- name: docker:dind
entrypoint: ["env", "-u", "DOCKER_HOST"]
command: ["dockerd-entrypoint.sh"]
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
# See https://github.com/docker-library/docker/pull/166
DOCKER_TLS_CERTDIR: ""
script:
- curl -sSL https://get.docker.com/ | sh
- python -m pip install cibuildwheel==2.11.3
- cibuildwheel --output-dir wheelhouse
parallel:
matrix:
- CIBW_BUILD: [cp38-manylinux*, cp39-manylinux*, cp310-manylinux*, cp311-manylinux*]
CIBW_ARCHS_LINUX: [auto64]
artifacts:
paths:
- wheelhouse/
dist:
image: python:3.8
needs:
- job: linux
artifacts: true
except:
- merge_requests
variables:
TWINE_PASSWORD: '${CI_JOB_TOKEN}'
TWINE_USERNAME: 'gitlab-ci-token'
TWINE_REPOSITORY_URL: 'https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/pypi'
script:
- python -m pip install --upgrade build twine
- python -m twine check --strict wheelhouse/*
- python -m twine upload --verbose wheelhouse/*
#windows:
# image: mcr.microsoft.com/windows/servercore:1809
# before_script:
# - choco install python -y --version 3.8.6
# - choco install git.install -y
# - py -m pip install cibuildwheel==2.11.3
# script:
# - py -m cibuildwheel --output-dir wheelhouse --platform windows
# artifacts:
# paths:
# - wheelhouse/
# tags:
# - windows

6
.gitmodules vendored
View File

@ -1,6 +0,0 @@
[submodule "coloquinte"]
path = coloquinte
# url = git@github.com:Coloquinte/PlaceRoute.git
url = https://github.com/Coloquinte/PlaceRoute.git
branch = coriolis-submodule
update = merge

6
.projectile Normal file
View File

@ -0,0 +1,6 @@
-*.fig
-*.png
-*.eps
-*.pdf
-*.aux
-*.bb

View File

@ -1,28 +0,0 @@
=========
COPYRIGHT
=========
* The **LEF/DEF** components of Coriolis are copyrighted by: ::
Cadence Design Systems 2012-2017
And released under the Apache 2.0 license
* The **flute** component of Coriolis is copyrighted by: ::
Dr. Chris C. N. Chu 2004
Iowa State University
http://home.engineering.iastate.edu/~cnchu/
And released under it's own license (derived from BSD)
* The **Hurricane** component of Coriolis is copyrighted by: ::
Bull S.A. 2000-2021 (now ATOS)
And released under the LGPL license
* **All other components** of Coriolis are copyrighted by: ::
Sorbonne Université 2000-2021 (formerly UPMC)
And released under the GPLv2 license

View File

@ -1,35 +0,0 @@
#This is needed for poetry to recognise the top level module
import os
import sys
import subprocess
__version__ = "0.0.0"
#TODO not PEP302 complient -probably a big porting job
coriolis_package_dir = os.path.abspath(os.path.dirname(__file__))
os.environ["CORIOLIS_TOP"] = coriolis_package_dir
CORIOLIS_DATA = os.path.join(os.path.dirname(__file__), 'data')
CORIOLIS_BIN = os.path.join(CORIOLIS_DATA,"bin")
def _program(name, args):
return subprocess.call([os.path.join(CORIOLIS_BIN, name)] + args, close_fds=False)
def blif2vst():
raise SystemExit(_program("blif2vst.py", sys.argv[1:]))
def cx2y():
raise SystemExit(_program("cx2y", sys.argv[1:]))
def cyclop():
raise SystemExit(_program("cyclop", sys.argv[1:]))
def tutorial():
raise SystemExit(_program("tutorial", sys.argv[1:]))
def unittests():
raise SystemExit(_program("unittests", sys.argv[1:]))
def yosys_coriolis():
raise SystemExit(_program("yosys.py", sys.argv[1:]))

View File

@ -1,376 +0,0 @@
==========================
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.
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.
one line to give the program's name and an idea of what it does.
Copyright (C) yyyy name of author
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.
signature of Ty Coon, 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](https://www.gnu.org/licenses/lgpl.html) instead of this
License.

View File

@ -1,16 +1,15 @@
UNAME_S = $(shell uname -s)
UNAME_R = $(shell uname -r)
DEVTOOLSET_VERSION = 7
UNAME_S = $(shell uname -s)
UNAME_R = $(shell uname -r)
# We must use devtoolset only under RHEL6 & clones.
# We must use devtoolset-2 only under RHEL6 & clones.
DEVTOOLSET_OPTION =
ifeq ($(UNAME_S),Linux)
ifneq ($(findstring .el7.,$(UNAME_R)),)
DEVTOOLSET_OPTION = --devtoolset=$(DEVTOOLSET_VERSION)
ifneq ($(findstring .el6.,$(UNAME_R)),)
DEVTOOLSET_OPTION = --devtoolset-2
endif
ifneq ($(findstring .slsoc6.,$(UNAME_R)),)
DEVTOOLSET_OPTION = --devtoolset=$(DEVTOOLSET_VERSION)
DEVTOOLSET_OPTION = --devtoolset-2
endif
endif
@ -57,6 +56,7 @@ check_dir:
install: check_dir
@./bootstrap/ccb.py $(DEVTOOLSET_OPTION) --project=support --project=coriolis --make="$(SMP_FLAGS) install"
@./bootstrap/ccb.py $(DEVTOOLSET_OPTION) --project=support --project=coriolis --make="-j1 install" --doc
@echo ""; \
echo "============================================================================"; \
echo "Coriolis has been successfully built"; \

View File

@ -5,19 +5,20 @@
Coriolis README
===============
Coriolis is a free database, placement tool and routing tool for VLSI design.
Coriolis is a free database, placement tool and routing tool for VLSI designs.
Purpose
=======
Coriolis provides several tools to perform the layout of VLSI circuits. Its
main components are the Hurricane database, the Etesian placer and the Katana
main components are the Hurricane database, the Etesian placer and the Kite
router, but other tools can use the Hurricane database and the parsers
provided.
The user interface <cgt> is the prefered way to use Coriolis, but all
Coriolis tools are Python modules and thus scriptable.
Coriolis tools are Python modules and thus scriptables.
Documentation
@ -25,14 +26,14 @@ Documentation
The complete documentation is available here, both in pdf & html:
./documentation/output/html
./documentation/UsersGuide/UsersGuide.html
./documentation/UsersGuide/UsersGuide.pdf
The documentation of the latest *stable* version is also
available online. It may be quite outdated from the *devel*
version.
https://www-soc.lip6.fr/sesi-docs/coriolis2-docs/coriolis2/en/latex/users-guide/UsersGuide.pdf
https://soc-extras.lip6.fr/en/coriolis/coriolis2-users-guide/
Building Coriolis
@ -40,29 +41,35 @@ Building Coriolis
To build Coriolis, ensure the following prerequisites are met:
* Python 3,
* cmake,
* boost,
* bison & flex,
* Qt 4 or 5,
* libxml2,
* RapidJSON,
* Python 2.7.
* cmake.
* boost.
* bison & flex.
* Qt 4 or 5.
* libxml2.
* RapidJSON
* A C++11 compliant compiler.
The build system relies on a fixed directory tree from the root
of the user currently building it. Thus first step is to get a clone of
the repository in the right place. Proceed as follow: ::
ego@home:~$ mkdir -p ~/coriolis-2.x/src/
ego@home:~$ mkdir -p ~/coriolis-2.x/src/support
ego@home:~$ cd ~/coriolis-2.x/src/support
ego@home:~$ git clone http://github.com/miloyip/rapidjson
ego@home:~$ git checkout ec322005072076ef53984462fb4a1075c27c7dfd
ego@home:~$ cd ~/coriolis-2.x/src
ego@home:src$ git clone https://gitlab.lip6.fr/vlsi-eda/coriolis.git
ego@home:src$ git clone https://www-soc.lip6.fr/git/coriolis.git
ego@home:src$ cd coriolis
If you want to use the *devel* branch: ::
ego@home:coriolis$ git checkout devel
Then, build the tool: ::
ego@home:coriolis$ make install
If you encounter issues, please consult SUPPORT.rst for tips.
Coriolis gets installed at the root of the following tree: ::
~/coriolis-2.x/<OS>.<DISTRIB>/Release.Shared/install/
@ -78,11 +85,11 @@ The Coriolis main interface can be launched with the command: ::
ego@home:~: ~/coriolis-2.x/<OS>.<DISTRIB>/Release.Shared/install/bin/coriolis
The ``coriolis`` script detects its location and setups the UNIX
environment appropriately, then lauches ``cgt`` (or *any* command, with the
The ``coriolis`` script is tasked to guess it's location and setup appropriatly
the UNIX environment, then lauch ``cgt`` (or *any* command, with the
``--run=<COMMAND>`` option).
Conversely, you can setup the current shell environment for Coriolis by
Conversely, you can setup the current shell environement for Coriolis by
using the helper ``coriolisEnv.py``, then run any Coriolis tool: ::
ego@home:~$ eval `~/coriolis-2.x/src/coriolis/bootstrap/coriolisEnv.py`

View File

@ -1,27 +0,0 @@
=================
Help and tooltips
=================
Compilation errors
==================
This section is here to help you with the build process, and help you fix dependency issues or workaround compilation errors if it happens on your distribution.
RapidJson
---------
Some versions of RapidJson do not build with newer compilers, while others build only with newer ones.
The version provided in README.rst should work for older compilers. Otherwise, consider pulling a newer version.
Qt5
---
To use Qt5, you should add the --qt5 option to the ccb.py line in Makefile.
On some distributions, you may need to replace the lines in bootstrap/cmake_modules/FindBootstrap.cmake from ::
find_package(Qt5Core REQUIRED)
to ::
find_package(Qt5 COMPONENTS REQUIRED Core)

View File

@ -1,44 +0,0 @@
# -*- explicit-buffer-name: "CMakeLists.txt<Seabreeze>" -*-
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
project(SEABREEZE)
option(BUILD_DOC "Build the documentation (doxygen)" OFF)
option(CHECK_DATABASE "Run database in full check mode (very slow)" OFF)
option(USE_LIBBFD "Link with BFD libraries to print stack traces" OFF)
cmake_minimum_required(VERSION 3.16)
set(ignoreVariables "${BUILD_DOC} ${CMAKE_INSTALL_DIR}")
list(INSERT CMAKE_MODULE_PATH 0 "${DESTDIR}$ENV{CORIOLIS_TOP}/share/cmake/Modules/")
find_package(Bootstrap REQUIRED)
setup_project_paths(CORIOLIS)
set_cmake_policies()
setup_boost(program_options)
setup_qt()
setup_python()
find_package(Libexecinfo REQUIRED)
find_package(PythonSitePackages REQUIRED)
find_package(LEFDEF REQUIRED)
find_package(FLUTE REQUIRED)
find_package(HURRICANE REQUIRED)
find_package(CORIOLIS REQUIRED)
#find_package(ANABATIC REQUIRED)
#find_package(ETESIAN REQUIRED)
#find_package(COLOQUINTE REQUIRED)
find_package(Doxygen)
if(CHECK_DATABASE)
add_definitions(-DCHECK_DATABASE)
endif(CHECK_DATABASE)
if(CHECK_DETERMINISM)
add_definitions(-DCHECK_DETERMINISM)
endif(CHECK_DETERMINISM)
add_subdirectory(src)
#add_subdirectory(test)
add_subdirectory(cmake_modules)
#add_subdirectory(doc)

View File

@ -1,27 +0,0 @@
Fonctions dans Seabreeze.cpp :
---------------------------------------------------------------------
contFromNet ( Net* net )
{
ajouter les contacts dans net au set<Contact*> _conts;
}
buildTree ( RoutingPad* rp )
{
Construire l'arbre de rp, ça veux dire le contact trouvé dans rp sera la racine de l'arbre
}
build_from_Node ( Node* source, Segment* seg )
{
Après avoir crée le premier node / la racine dans buildTree, on va l'utiliser pour construire l'arbre.
}
build_branch ( double* R, double* C, Contact* contact )
{
Parcourir la branche et trouver le Node suivant de l'arbre
}
Set_RC ( double* R, double* C, Contact* ct, Segment* sm )
{
Calculer le RC de la branche ct-sm et ajouter la valeur dans R et C
}

View File

@ -1,2 +0,0 @@
install( FILES FindSEABREEZE.cmake DESTINATION share/cmake/Modules )

View File

@ -1,38 +0,0 @@
# - Find the Seabreeze includes and libraries.
# The following variables are set if Coriolis is found. If KATABATIC is not
# found, KATABATIC_FOUND is set to false.
# KATABATIC_FOUND - True when the Coriolis include directory is found.
# KATABATIC_INCLUDE_DIR - the path to where the Coriolis include files are.
# KATABATIC_LIBRARIES - The path to where the Coriolis library files are.
SET(SEABREEZE_INCLUDE_PATH_DESCRIPTION "directory containing the Katabatic include files. E.g /usr/local/include/coriolis2 or /asim/coriolis/include/coriolis2")
SET(SEABREEZE_DIR_MESSAGE "Set the SEABREEZE_INCLUDE_DIR cmake cache entry to the ${SEABREEZE_INCLUDE_PATH_DESCRIPTION}")
# don't even bother under WIN32
IF(UNIX)
#
# Look for an installation.
#
FIND_PATH(SEABREEZE_INCLUDE_PATH NAMES katabatic/KatabaticEngine.h PATHS
# Look in other places.
${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES include/coriolis2
# Help the user find it if we cannot.
DOC "The ${SEABREEZE_INCLUDE_PATH_DESCRIPTION}"
)
FIND_LIBRARY(SEABREEZE_LIBRARY_PATH
NAMES seabreeze
PATHS ${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES lib64 lib
# Help the user find it if we cannot.
DOC "The ${SEABREEZE_INCLUDE_PATH_DESCRIPTION}"
)
SET_LIBRARIES_PATH(SEABREEZE SEABREEZE)
HURRICANE_CHECK_LIBRARIES(SEABREEZE)
ENDIF(UNIX)

View File

@ -1,22 +0,0 @@
# -*- mode: CMAKE; explicit-buffer-name: # "CMakeLists.txt<Seabreeze/doc>" -*-
set ( htmlInstallDir share/doc/coriolis2/en/html/doc/Seabreeze )
set ( latexInstallDir share/doc/coriolis2/en/latex/Seabreeze )
set ( doxExtras customHierarchy.html
closed.png
open.png
tabs.css
)
if(BUILD_DOC AND DOXYGEN_FOUND)
add_custom_target ( doc ALL
cd ${SEABREEZE_SOURCE_DIR}/doc
&& ${DOXYGEN_EXECUTABLE} doxyfile
&& cp -f ${doxExtras} html
)
endif()
install ( DIRECTORY html/ DESTINATION ${htmlInstallDir} )
install ( DIRECTORY latex/ DESTINATION ${latexInstallDir} )
install ( FILES asimbook.cls DESTINATION ${latexInstallDir} )

View File

@ -1,49 +0,0 @@
// -*- C++ -*-
/*! \class Node
*! \brief Node description(\b API)
*
*/
/*! \var int Node::R
* The Resistor of a point in the circuit / node in the tree.
*/
/*! \var int Node::Rt
* The Resister "total" - the value of resistor that is used
* to compute the Elmore's delay.
*/
/*! \var int Node::C
* The Capacitor of a point in the circuit / node in the tree.
*/
/*! \var Node* Node::Np
* The parent node of current node
*/
/* \var std::vector<Node*> Node::Ne
* A list of children nodes of current node
*/
/*! \var int Node::label
* The label / Id of current node
*/
/*! \var int Node::ap
* A boolean variable to determine whether the current node
* is after or before node i at where we need to compute the
* Elmore's delay.
*/
/*! \function Node::Node();
* Default constructor.
*/
/*! \function Node::~Node();
* Default destructor.
*/

View File

@ -1,102 +0,0 @@
// -*- C++ -*-
namespace Seabreeze {
/*! \class Elmore
* \brief Main class for computing the Elmore's delay
*/
/*! \var vector<Contact*> Elmore::_conts
* The list of Contacts contained in the considered Net
*/
/*! \var vector<Contact*> Elmore::checker
* The list of Contacts that we have treated. It serves as a checker
* of circles. If a circle exists in the Net, Elmore's delay cannot be
* computed.
*/
/*! \var Tree Elmore::_tree
* The tree necessary to run the algorithm to compute Elmore's delay
*/
/*! \function Elmore::Elmore( Net* net = NULL )
* Constructor
*/
/*! \function Elmore::~Elmore()
* Default destructor
*/
/*! \function void Elmore::contFromNet( Net* net )
* Build the list _const from net
*/
/*! \function void Elmore::buildTree( Contact* ct )
* Build the _tree with ct as the root
*/
/*! \function void Elmore::clearTree()
* Clean the _tree and the list checker
*/
/*! \function Tree* Elmore::getTree()
* \Return the _tree
*/
/*! \function int Elmore::delayElmore()
* \Return the value of Elmore's delay
*/
/*! \function void Elmore::toTree( ostream& )
* Print the _tree to an output file
*/
/*! \class ElmoreProperty
*
*/
/*! \var Name ElmorerProperty::_name
*
*/
/*! \var Elmore ElmoreProperty::_elmore
*
*/
/*! \function ElmoreProperty::ElmoreProperty( Net* )
* Constructor
*/
/*! \function ElmoreProperty* ElmoreProperty::create( Net* net )
* \Return the ElmoreProperty created from the net
*/
/*! \function Name ElmoreProperty::getName()
* \Return the name of the property
*/
/*! \class ElmoreExtension
* \brief Useful to access to functions of Elmore class without having to calling it
*/
/*! \var Net* ElmoreExtension::Nets
*
*/
/*! \function void ElmoreExtension::destroyAll()
*
*/
/*! \function void ElmoreExtension::destroy()
*
*/
/*! \function Tree ElmoreExtension::getTree( Elmore* elmore )
* \Return the _tree of elmore
*/
/*! \function void ElmoreExtension::toTree( Elmore* elmore, std::ostream& out )
* Print the _tree of elmore to the output file out
*/
}

View File

@ -1,882 +0,0 @@
/*
* +-----------------------------------------------------------------+
* | HTML Standart Tags |
* +-----------------------------------------------------------------+
*/
html, body, th, td, tr, p, li, h1, h2, h3, h4, h5, h6 {
font-size: 11pt;
/* The Open Sans font family is supplied by TexLive. */
font-family: "Roboto", "Open Sans", Verdana, sans-serif;;
}
html {
background: #dddddd;
}
body {
color: black;
background: white;
background-color: white;
background-position: top left;
background-attachment: fixed;
background-repeat: no-repeat;
margin-top: 2em;
width: 600pt;
margin-right: auto;
margin-left: auto;
padding: 30pt;
/*
margin-right: 12%;
margin-left: 12%;
*/
}
hr {
height: 1px;
border: 0;
color: #004400;
background-color: #004400;
}
h1, h2, h3, h4, h5, h6 {
/*font-family: "URW Bookman L", "Liberation Serif", sans-serif;*/
font-family: "URW Bookman L";
}
h1.header { text-align: center; }
h1 { text-align: left; }
h2, h3, h4, h5, h6 { text-align: left;
padding-top: 11pt;
}
h1, h2, h3 { /*font-family: "Liberation Serif", sans-serif; */
/*color: #09550B;*/
}
h1 { font-weight: bold; font-size: 170%; /*letter-spacing:0.2em; word-spacing:0.4em;*/ }
h2 { font-weight: bold; font-size: 140%; /*letter-spacing:0.2em; word-spacing:0.4em;*/ }
h3 { font-weight: bold; font-size: 118%; /*letter-spacing:0.2em; word-spacing:0.4em;*/ }
h4 { font-weight: bold; font-size: 100%; }
h5 { font-style: italic; font-size: 100%; }
h6 { font-variant: small-caps; font-size: 100%; }
h2.classHierarchy {
/*border: 1px none #008500;*/
border: 1px none #000000;
border-top-width: 1px;
border-top-style: dotted;
padding-top: 1em;
}
.hide {
display: none;
color: white;
}
p {
margin-top: 0.6em;
margin-bottom: 0.6em;
margin-left: 0.0em;
margin-right: 0.0em;
}
address {
text-align: right;
font-weight: bold;
font-style: italic;
font-size: 80%;
}
caption { font-weight: bold }
blockquote {
margin-left: 4em;
margin-right: 4em;
margin-top: 0.8em;
margin-bottom: 0.8em;
font-style: italic;
color: #003300;
}
blockquote p {
margin-bottom: 0;
}
blockquote address {
margin: 0;
}
table {
border-collapse: collapse;
}
dt, dd { margin-top: 0; margin-bottom: 0; }
dt { font-weight: bold; }
pre, tt, code {
/*font-family: "andale mono", monospace;*/
font-size: 100%;
white-space: pre;
}
pre {
font-size: 80%;
/*border: dashed;*/
border-width: thin;
border-color: #003300;
/*background-color: #EEEEEE;*/
background-color: #FCFCE1;
padding: 0.5em;
margin-left: 2em;
margin-right: 2em
}
/*
tt { color: green; }
*/
em { font-style: italic;
font-weight: normal; }
strong { font-weight: bold; }
span.textit { font-style: italic; }
span.textbf { font-weight: bold; }
.small { font-size: 90%; }
.white { color: #FFFFFF; }
ul.toc {
list-style: disc;
list-style: none;
}
a:link img, a:visited img { border-style: none; }
a img { color: white; }
a {
color: black;
border-bottom: 1px solid black;
text-decoration: none;
}
a:link, a:active, a:visited {
/*color: #09550B;*/
/*text-decoration: none;*/
}
a:hover, a:focus {
/*color: #FF9900; */
border-bottom: 2px solid black;
}
/*
* +-----------------------------------------------------------------+
* | Doxygen Specific Classes |
* +-----------------------------------------------------------------+
*/
/* -------------------------------------------------------------------
* Header & Footer Classes (customized top page navigation bar).
*/
h1.header {
font-size: 200%;
/*font-family: times, verdana, sans-serif;*/
}
h2.memtitle {
display: none;
}
center.header {
background-color: #CCE6CA;
}
table.header {
/*width: 100%;*/
/*background-color: #EEEEEE;*/
background-color: #CCE6CA;
}
div.header {
text-align: center;
margin: 14pt 0pt 0pt 0pt;
}
div.summary {
color: white;
background-color: black;
border: 4px solid black;
}
div.summary a {
font-size: 90%;
color: white;
padding: 2px 0px;
text-align: center;
background-color: black;
border-bottom: none;
}
table.header td {
padding: 2px 14px;
text-align: center;
font-weight: bold;
/*font-family: verdana, sans-serif;*/
font-size: 110%;
}
table.UserDefined {
border: 1px solid;
}
table.UserDefined th {
border: 1px solid;
}
table.UserDefined td {
padding: 0px 5px;
}
table.DoxUser td, table.DoxUser th {
padding: 0px 5px;
border: 0px;
}
table.DoxUser th {
background-color: #CCE6CA;
}
table.footer1, table.footer2 { width: 100%; }
td.LFooter { text-align: left; }
td.RFooter { text-align: right; }
td.CFooter { text-align: center;}
table.footer2 td.RFooter { font-weight: bold; width: 35% }
table.footer2 td.CFooter { width: 30% }
table.footer2 td.LFooter { font-weight: bold; width: 35%; /*font-family: time;*/ }
table.classHierarchy {
border-collapse: separate;
border-spacing: 5px;
font-size: 110%;
}
table.classHierarchy a {
border-style: none;
border-bottom: none;
}
table.classHierarchy tr {
border: 1px solid blue;
}
table.classHierarchy td.normal {
border: 1px solid #dddddd;
width: 140pt;
text-align: center;
font-weight: bold;
background-color: #dddddd;
}
table.classHierarchy td.virtual {
border: 1px solid black;
width: 140pt;
text-align: center;
font-weight: bold;
}
table.classHierarchy td.wnormal {
border: 1px solid #dddddd;
width: 240pt;
text-align: center;
font-weight: bold;
background-color: #dddddd;
}
table.classHierarchy td.wvirtual {
border: 1px solid black;
width: 240pt;
text-align: center;
font-weight: bold;
}
div.ah, span.ah {
font-family: Times;
font-size: 300%;
font-weight: bold;
padding: 20px;
}
div.title {
text-align: center;
font-size: 200%;
font-weight: bold;
padding: 20px;
border: 2px solid black;
}
div.center, div.image {
text-align: center;
}
/* -------------------------------------------------------------------
* Top navigation lists.
*/
span.mlabels {
font-size: 90%;
font-style: italic;
padding-left: 10pt;
margin: 10pt;
border-left: 1px solid black
}
div.contents {
padding-top: 20pt;
}
div.tabs {
border-top: 1px solid black;
}
div.tabs, div.tabs1, div.tabs2, div.tabs3, div.tabs4 {
border-left: 1px solid black;
}
ul.tablist {
/*
padding: 5pt;
background-color: red;
*/
margin: 0pt;
padding: 0pt;
border-top: none;
border-bottom: none;
border-left: none;
border-right: none;
}
ul.tablist li {
/*
margin-left: auto;
margin-right: auto;
overflow: auto;
display: inline;
background-color: yellow;
*/
font-size: 90%;
border-top: none;
border-bottom: 1px solid black;
border-left: none;
border-right: 1px solid black;
display: table-cell;
text-align: center;
padding: 2pt;
width: 5%;
}
ul.tablist li:hover {
background-color: black;
color: white;
}
ul.tablist li:hover a {
background-color: black;
color: white;
}
ul.tablist * a { border-bottom: none; }
ul.tablist * a:link img, ul.tablist * a:visited img { border-style: none; border-bottom: none; }
ul.tablist * a:link, ul.tablist * a:visited {
color: black;
text-decoration: none;
}
ul.tablist * a:hover, ul.tablist * a:focus, ul.tablist * a:active {
color: white;
text-decoration: underline;
}
div.navpath {
padding: 5pt 0pt 0pt 0pt;
}
.navpath ul {
text-align: center;
}
.navpath ul li {
display: inline;
list-style-type: none;
padding-left: 20px;
padding-right: 10px;
background-image: url('closed.png');
background-repeat: no-repeat;
background-position: left;
color: #364D7C;
}
.navpath ul li a {
border: 2px solid black;
padding-left: 10px;
padding-right: 10px;
font-weight: bold;
color: black;
}
/* -------------------------------------------------------------------
* Quick Index Class (top page navigation bar).
*/
div.qindex, div.nav {
width: 100%-4px;
/*background-color: #DADAEF;*/
/*background-color: #eeeeff;*/
background-color: #cccccc;
/*background-color: #CCE6CA;*/
border: 0px solid #003300;
text-align: center;
margin: 0px;
padding: 2px;
line-height: 140%;
}
a.qindex, a.qindex:visited, a.qindex:hover, a.qindexHL, a.el, a.elRef {
text-decoration: none;
/*font-family: Courier;*/
font-weight: normal;
/*font-size: 110%;*/
}
a.qindex, a.qindex:visited {
/*color: #09550B;*/
color: black;
border: 2px solid #cccccc;
padding: 2px 2px;
border-bottom: none;
}
a.qindex:hover {
/*background-color: #ddddff;*/
font-weight: bold;
padding: 2px 2px;
border: 2px solid black;
}
a.qindexHL, a.qindexHL:hover, a.qindexHL:visited {
background-color: #0c780c;
color: #ffffff;
border: 1px double #9295C2;
}
a.code:link, a.code:visited, a.codeRef:link, a.codeRef:visited {
text-decoration: none;
font-weight: normal;
color: #0000ff;
}
.indexkey {
background-color: #eeeeff;
border: 1px solid #b0b0b0;
padding: 2px 15px;
}
.indexkey, .indexvalue {
background-color: #eeeeff;
border: 1px solid #b0b0b0;
padding: 2px 15px;
}
.indexkey {
width: 40%;
}
.indexvalue {
width: 80%;
}
h3 a[name="index__"],
h3 a[name="index_a"],
h3 a[name="index_b"],
h3 a[name="index_c"],
h3 a[name="index_d"],
h3 a[name="index_e"],
h3 a[name="index_f"],
h3 a[name="index_g"],
h3 a[name="index_h"],
h3 a[name="index_i"],
h3 a[name="index_j"],
h3 a[name="index_k"],
h3 a[name="index_l"],
h3 a[name="index_m"],
h3 a[name="index_n"],
h3 a[name="index_o"],
h3 a[name="index_p"],
h3 a[name="index_q"],
h3 a[name="index_r"],
h3 a[name="index_s"],
h3 a[name="index_t"],
h3 a[name="index_u"],
h3 a[name="index_v"],
h3 a[name="index_w"],
h3 a[name="index_x"],
h3 a[name="index_y"],
h3 a[name="index_z"],
h3 a[name="index_0"],
h3 a[name="index_1"],
h3 a[name="index_2"],
h3 a[name="index_3"],
h3 a[name="index_4"],
h3 a[name="index_5"],
h3 a[name="index_6"],
h3 a[name="index_7"],
h3 a[name="index_8"],
h3 a[name="index_9"]
h3 a[id="index__"],
h3 a#index_a,
h3 a#index_b,
h3 a#index_c,
h3 a#index_d,
h3 a#index_e,
h3 a#index_f,
h3 a#index_g,
h3 a#index_h,
h3 a#index_i,
h3 a#index_j,
h3 a#index_k,
h3 a#index_l,
h3 a#index_m,
h3 a#index_n,
h3 a#index_o,
h3 a#index_p,
h3 a#index_q,
h3 a#index_r,
h3 a#index_s,
h3 a#index_t,
h3 a#index_u,
h3 a#index_v,
h3 a#index_w,
h3 a#index_x,
h3 a#index_y,
h3 a#index_z,
h3 a#index_0,
h3 a#index_1,
h3 a#index_2,
h3 a#index_3,
h3 a#index_4,
h3 a#index_5,
h3 a#index_6,
h3 a#index_7,
h3 a#index_8,
h3 a#index_9,
h3 a#index_0x7e
{
font-family: time;
font-size: 250%;
text-align: center;
}
/* -------------------------------------------------------------------
* Verbatim Source Code / Examples.
*/
div.fragment {
font-family: "Roboto Mono", "Monospace";
font-size: 80%;
border: none;
/*border-width: thin; */
/*border-color: #003300;*/
/*background-color: #FCFCE1;*/
background-color: #fefefe;
padding: 0.5em;
margin-left: 5%;
margin-right: 5%
}
div.fragment a.code:link,
div.fragment a.code:visited,
div.fragment a.codeRef:link,
div.fragment a.codeRef:visited {
text-decoration: none;
font-weight: bold;
color: black;
border: none;
}
div.line {
white-space: pre;
padding: 0pt;
margin: 0pt;
}
span.keyword { color: #008000 }
span.keywordtype { color: #604020 }
span.keywordflow { color: #e08000 }
span.comment { color: #800000 }
span.preprocessor { color: #806020 }
span.stringliteral { color: #002080 }
span.charliteral { color: #008080 }
span.red { color: red }
/* -------------------------------------------------------------------
* Attributes Listing.
*/
a.el, a.elRef {
font-family: "Roboto Mono", Courier;
font-weight: bold;
font-size: 110%;
color: black;
border-bottom: none;
}
p.formulaDsp {
text-align: center;
}
.mdTable {
/*border: 1px solid #868686;*/
/*background-color: #DADAEF;*/
/*background-color: #F4F4FB;*/
border: 1px none #008500;
border-left-width: 1px;
border-left-style: solid;
/*background-color: #B8E6B8;*/
/*background-color: #CCE6CA;*/
margin-top: 25px;
font-size: 105%;
}
.mdRow {
padding: 5px 10px;
}
/* This Mozilla/Firefox bug has been corrected from v1.5.
* .mdname1 {
* padding: 3px 0px 0px 0px;
* }
*/
.mdescLeft, .mdescRight {
padding: 0px 8px 4px 8px;
font-size: 11px;
font-style: italic;
/*background-color: #FAFAFA;*/
border-top: 1px none #E0E0E0;
border-right: 1px none #E0E0E0;
border-bottom: 1px none #E0E0E0;
border-left: 1px none #E0E0E0;
margin: 0px;
}
.memitem {
margin-bottom: 30px;
border: 1px none #008500;
}
.memproto {
/*background-color: #CCE6CA;*/
background-color: #cccccc;
border-left-width: 4px;
border-left-style: solid;
/*border-color: #008500;*/
border-color: black;
}
.memname {
white-space: nowrap;
padding-left: 5px;
font-size: 105%;
}
table.memname * {
font-family: "Roboto Mono", "Monospace";
}
.memdoc{
padding-left: 5px;
/*margin-top: -8px;*/
border-left-width: 1px;
border-left-style: solid;
/*border-color: #008500;*/
border-color: black;
}
div.contents * table tr {
padding: 3px 3px 3px 8px;
}
.memSeparator {
font-size: 1pt;
}
.memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight {
vertical-align: top;
/*padding: 1px 0px 0px 8px;*/
padding: 3px 3px 3px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
/*
border-top-color: #0c0c0c;
border-right-color: #0c0c0c;
border-bottom-color: #0c0c0c;
border-left-color: #0c0c0c;
*/
border-top-style: none;
border-right-style: none;
/*
border-bottom-style: dotted;
*/
border-left-style: none;
/*background-color: #DADAEF;*/
/*background-color: #eeeeff;*/
/*background-color: #EEEEEE;*/
/*background-color: #CCE6CA;*/
font-family: "Roboto Mono", "Monospace";
}
.memTemplItemLeft, .memTemplItemRight {
border-bottom-width: 2px;
border-bottom-style: solid;
font-weight: bold;
}
.memItemLeft { font-size: 11px; width: 100pt; }
.memItemRight { font-size: 12px; }
.memTemplItemLeft { font-size: 11px; }
.memTemplItemRight { font-size: 12px; }
.memTemplParams {
color: #FFFFFF;
background-color: #000000;
font-size: 11px;
font-weight: bold;
}
.groupText, .groupHeader {
color: #09550B;
font-size: 130%;
font-weight: bold;
margin-top: 15px;
}
.groupHeader {
margin-bottom: -30pt;
}
.inherit {
display: none;
}
/* -------------------------------------------------------------------
* General Classes Index.
*/
span.icona {
margin-right: 10pt;
}
div.toc li.level1 {
margin-left: 0px;
}
div.toc li.level2 {
margin-left: 15px;
display: none;
}
div.toc li.level3 {
margin-left: 30px;
display: none;
}
div.toc li.level4 {
margin-left: 45px;
display: none;
}
.directory .levels {
white-space: nowrap;
width: 100%;
text-align: right;
font-size: 9pt;
}
.directory .levels span {
cursor: pointer;
padding-left: 2px;
padding-right: 2px;
color: #3D578C;
}
div.directory {
margin: 10px 0px;
border-top: 2px solid black;
border-bottom: 2px solid black;
width: 100%;
}
.directory table {
border-collapse: collapse;
}
.directory td {
margin: 0px;
padding: 0px;
vertical-align: top;
}
.directory td.entry {
white-space: nowrap;
padding-right: 6px;
padding-top: 3px;
}
.directory td.entry a {
outline: none;
}
.directory td.entry a img {
border: none;
}
.directory td.desc {
width: 100%;
padding-left: 6px;
padding-right: 6px;
padding-top: 3px;
border-left: 1px solid rgba(0,0,0,0.05);
}
.directory tr.even {
padding-left: 6px;
background-color: #F7F8FB;
}
.directory img {
vertical-align: -30%;
}

View File

@ -1,50 +0,0 @@
// -*- C++ -*-
/*! \class Tree
* \brief The tree contains all points of the circuit as its' nodes.
*/
/*! \var vector<Node*> Tree::nodes
* The list of nodes contained in the tree
*/
/*! \function Tree::Tree()
* Default constructor
*/
/*! \function Tree:~Tree()
* Default destructor
*/
/*! \function int Tree::get_N()
* Returns the number of nodes in the tree / points in the circuit
*/
/*! \function Node* Tree::get_node( int i )
* Returns node at index i in the tree
*/
/*! \function vector<Node*> get_node_list()
* Returns the list of nodes contained in the tree
*/
/*! \function void Tree::new_node()
* Create and add a new node to the tree
*/
/*! \function void Tree::After_i( Node* node_i )
* For each node in the tree, determine if they are after or before node_i.
* In other words, change the value of ap of each node to 0 or 1 accordingly.
*/
/*! \function set<int> Tree::Branch_i( int i )
* Returns a set of indexes of nodes who are on the same branch as node i.
*/
/*! \function int Tree::Delay_Elmore( int i)
* Computes the Elmore's delay and returns the result.
*/
/*! \function void Tree::print( ostream& out )
* Prints the tree to the output file.
*/

View File

@ -1,65 +0,0 @@
<br>
<p><b>The complete class hierarchy could be accessed <a href="hierarchy.html">here</a>.</b></p>
<p>All the classes below are in the <a href="namespaceSeabreeze.html">Seabreeze</a> namespace.</p>
<p>The inheritance tree has been splitted/simplificated.</p>
<b>Legend :</b><br>
<pre class="fragment">
<table class="classHierarchy">
<tr><td width="70"><td class="virtual"><a href="#pagetop">ClassA</a><td><b>&nbsp;&nbsp;<tt>ClassA</tt> is abstract</b></tr>
<tr><td width="70"><td class="normal"><a href="#pagetop">ClassB</a><td><b>&nbsp;&nbsp;<tt>ClassB</tt> is instanciable</b></tr>
</table>
</pre>
<br>
<h2 class="classHierarchy">Utilities</h2>
<table class="classHierarchy">
<tr><td width="70"><td class="virtual"><a href="classSeabreeze_1_1BaseObserver.html">BaseObserver</a>
</table>
<table class="classHierarchy">
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1Observer.html">Observer</a>
</table>
<table class="classHierarchy">
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1Observable.html">Observable</a>
</table>
<h2 class="classHierarchy">Seabreeze Engine</h2>
<table class="classHierarchy">
<tr><td width="70"><td class="normal"><a href="namespaceSeabreeze.html">Seabreeze</a>
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1ChipTools.html">ChipTools</a>
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1SeabreezeEngine.html">SeabreezeEngine</a>
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1Session.html">Session</a>
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1DataAlgorithm.html">DataAlgorithm</a>
</table>
<h2 class="classHierarchy">Contacts</h2>
<table class="classHierarchy">
<tr><td width="70"><td class="virtual"><a href="classSeabreeze_1_1AutoContact.html">AutoContact</a>
</table>
<table class="classHierarchy">
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1AutoContactTerminal.html">AutoContactTerminal</a>
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1AutoContactTurn.html">AutoContactTurn</a>
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1AutoContactHTee.html">AutoContactHTee</a>
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1AutoContactVTee.html">AutoContactVTee</a>
</table>
<h2 class="classHierarchy">Segments</h2>
<table class="classHierarchy">
<tr><td width="70"><td class="virtual"><a href="classSeabreeze_1_1AutoSegment.html">AutoSegment</a>
</table>
<table class="classHierarchy">
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1AutoHorizontal.html">AutoHorizontal</a>
<tr><td width="140"><td class="normal"><a href="classSeabreeze_1_1AutoVertical.html">AutoVertical</a>
</table>
<h2 class="classHierarchy">GCell</h2>
<table class="classHierarchy">
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1GCell.html">GCell</a>
<tr><td width="70"><td class="normal"><a href="classSeabreeze_1_1BaseGrid_1_1Axis.html">BaseGrid::Axis</a>
<tr><td width="70"><td class="virtual"><a href="classSeabreeze_1_1BaseGrid.html">BaseGrid</a>
</table>
<table class="classHierarchy">
<tr><td width="140"><td class="virtual"><a href="classSeabreeze_1_1Grid.html">Grid</a>
</table>
<table class="classHierarchy">
<tr><td width="210"><td class="normal"><a href="classSeabreeze_1_1GCellGrid.html">GCellGrid</a>
</table>

View File

@ -1,81 +0,0 @@
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN'>
<!-- $Id: customSummary.html,v 1.1 2007/09/15 13:10:13 jpc Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>Seabreeze Documentation</title>
<link href="SoC.css" rel="stylesheet" type="text/css">
</head>
<h1 class="header">Seabreeze Documentation</h1>
<center class="header">
<table class="header">
<tr>
<td><a href="customSummary.html">Summary</a></td>
<td><a href="namespaces.html">Namespaces</a></td>
<td><a href="customHierarchy.html">Class Hierarchy</a></td>
<td><a href="annotated.html">Classes</a></td>
<td><a href="functions.html">Member Index</a></td>
<!-- <td><a href="classes.html">Index2</a></td> -->
</tr>
</table>
</center>
<br>
<hr>
<body>
<h1>Seabreeze Documentation Summary</h1>
<br>
<p><b>The classical Doxygen module documentation could be accessed <a href="modules.html">here</a>.</b></p>
<!--
<h2>Seabreeze Concepts (internal)</h2>
<ol>
<li><a class="el" href="group__buildRules.html">Rules for building wires.</a>
<br>Rules for building AutoContacts. Global/Locals AutoSegments.
<li><a class="el" href="group__loadGlobalRouting.html">Global Routing Loading.</a>
<br>How the Knik global routing is loaded into Seabreeze data-base.
Details the wiring topologies used to complete the routing to the
terminals.
<li><a class="el" href="group__collapseCanonical.html">AutoSegment Collapse &amp; Canonical.</a>
<br>How to force alignment of AutoSegments.
<li><a class="el" href="group__layerAssign.html">Layer Assignment.</a>
<br>Simple strategy to put long wires on higher routing metals.
<li><a class="el" href="group__NetConstraints.html">Constraints Computations.</a>
<br>Compute the legal range of variation of each wire (note that the
constraints are stored on AutoContacts).
<li><a class="el" href="group__NetOptimals.html">AutoSegment Optimal Placement.</a>
<br>Compute the optimal range of variation of each wire.
<li><a class="el" href="group__katabaticSession.html">Seabreeze Update Session Mechanism.</a>
<br>The Session mechanism for modifying the Seabreeze data-base.
</ol>
-->
<h2>API documentations</h2>
<ul>
<li><b><a href="customHierarchy.html">Synthetic Class Hierarchy.</a></b>
<li><b><a href="hierarchy.html">Complete Class Hierarchy (doxygen).</a></b>
<li><b><a href="annotated.html">Class List (doxygen).</a></b>
<li><b><a href="classes.html">Class Index (doxygen).</a></b>
<li><b><a href="modules.html">Modules (raw concepts).</a></b>
<li><b><a href="functions.html">Member Functions Index (doxygen).</a></b>
<li><b><a href="namespaces.html">Namespaces (doxygen).</a></b>
</ul>
<br>
<hr>
<table class="footer1">
<tr>
<td class="LFooter"><small>Customized Concepts (a.k.a. modules)</small></td>
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
</tr>
</table>
<table class="footer2">
<tr>
<td class="LFooter">Seabreeze Documentation</td>
<td class="RFooter"><small>Copyright &#169; 2005-2007 LIP6. All rights reserved</small></td>
</tr>
</table>
</body>
</html>

View File

@ -1,276 +0,0 @@
# -*- explicit-buffer-name: "doxyfile<Seabreeze/doc>" -*-
# Doxyfile 1.3.4
# --------------------------------------------------------------------
# Project related configuration options
PROJECT_NAME = "Seabreeze - Routing Toolbox"
PROJECT_NUMBER = 1.0
OUTPUT_DIRECTORY = .
OUTPUT_LANGUAGE = English
MARKDOWN_SUPPORT = NO
#USE_WINDOWS_ENCODING = NO
LAYOUT_FILE = DoxygenLayout.xml
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
#DETAILS_AT_TOP = YES
INHERIT_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 2
ALIASES = "function=\fn"\
"important=\par Important:\n"\
"remark=\par Remark:\n"\
"sreturn=\b Returns:"\
"True=\b True"\
"true=\b true"\
"False=\b False"\
"false=\b false"\
"VERTICAL=\b VERTICAL"\
"HORIZONTAL=\b HORIZONTAL"\
"NULL=\c NULL"\
"vector=\c vector"\
"Collection=\c Collection"\
"Collections=\c Collections"\
"Box=\c Box"\
"box=\c box"\
"Layer=\c Layer"\
"Layers=\c Layers"\
"Net=\c Net"\
"Nets=\c Nets"\
"Pin=\c Pin"\
"Pins=\c Pins"\
"Plug=\c Plug"\
"Plugs=\c Plugs"\
"RoutingPad=\c RoutingPad"\
"RoutingPads=\c RoutingPads"\
"Cell=\c Cell"\
"Cells=\c Cells"\
"ToolEngine=\c ToolEngine"\
"ToolEngines=\c ToolEngines"\
"GCell=\c GCell"\
"GCells=\c GCells"\
"Splitter=\c Splitter"\
"Splitters=\c Splitters"\
"SplitterContact=\c SplitterContact"\
"SplitterContacts=\c SplitterContacts"\
"Hurricane=<a href='../hurricane/Index.html'>Hurricane</a>"\
"STL=<a href='http://www.sgi.com/tech/stl/'>STL</a>"\
"red{1}=<span class=\"red\">\1</span>"
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
SUBGROUPING = YES
# --------------------------------------------------------------------
# Build related configuration options
EXTRACT_ALL = NO
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_ANON_NSPACES = YES
HIDE_UNDOC_MEMBERS = YES
HIDE_UNDOC_CLASSES = YES
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = YES
SHOW_INCLUDE_FILES = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 1
SHOW_USED_FILES = YES
# --------------------------------------------------------------------
# Configuration options related to warning and progress messages
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = NO
WARN_IF_DOC_ERROR = YES
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
# --------------------------------------------------------------------
# Configuration options related to the input files
INPUT = \
Seabreeze.dox \
../src/Seabreeze/Node.h ../src/Node.cpp Node.dox \
../src/Seabreeze/Tree.h ../src/Tree.cpp Tree.dox \
../src/Seabreeze/Seabreeze.h ../src/Seabreeze.cpp Seabreeze.dox \
../src/katabatic/SeabreezeEngine.h ../src/SeabreezeEngine.cpp SeabreezeEngine.dox
FILE_PATTERNS = *.h \
*.cpp \
*.dox
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXAMPLE_PATH = .
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH = images
INPUT_FILTER =
FILTER_SOURCE_FILES = YES
# --------------------------------------------------------------------
# Configuration options related to source browsing
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
VERBATIM_HEADERS = YES
# --------------------------------------------------------------------
# Configuration options related to the alphabetical class index
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 2
IGNORE_PREFIX =
# --------------------------------------------------------------------
# Configuration options related to the HTML output
GENERATE_HTML = YES
#HTML_DYNAMIC_SECTIONS = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER = header.html
HTML_FOOTER = footer.html
HTML_STYLESHEET = SoC.css
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 1
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
# --------------------------------------------------------------------
# Configuration options related to the LaTeX output
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER = header.tex
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
# --------------------------------------------------------------------
# Configuration options related to the RTF output
GENERATE_RTF = YES
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
# --------------------------------------------------------------------
# Configuration options related to the man page output
GENERATE_MAN = YES
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
# --------------------------------------------------------------------
# Configuration options related to the XML output
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
# --------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
GENERATE_AUTOGEN_DEF = NO
# --------------------------------------------------------------------
# Configuration options related to the Perl module output
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
# --------------------------------------------------------------------
# Configuration options related to the preprocessor
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = __DOXYGEN__
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
# --------------------------------------------------------------------
# Configuration::addtions related to external references
TAGFILES = ../../hurricane/doc/hurricane/html/hurricane.tag=../hurricane \
../../hurricane/doc/viewer/html/viewer.tag=../viewer \
../../crlcore/doc/crlcore/html/crlcore.tag=../crlcore
GENERATE_TAGFILE = html/Seabreeze.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
# --------------------------------------------------------------------
# Configuration options related to the dot tool
CLASS_DIAGRAMS = NO
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
CLASS_GRAPH = YES
COLLABORATION_GRAPH = NO
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
GRAPHICAL_HIERARCHY = NO
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
#MAX_DOT_GRAPH_WIDTH = 512
#MAX_DOT_GRAPH_HEIGHT = 1024
#MAX_DOT_GRAPH_DEPTH = 0
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
# --------------------------------------------------------------------
# Configuration::addtions related to the search engine
SEARCHENGINE = NO

View File

@ -1,16 +0,0 @@
<br>
<hr>
<table class="footer1">
<tr>
<td class="LFooter"><small>Generated by doxygen $doxygenversion on $date</small></td>
<td class="RFooter"><a href='#pagetop'><small>Return to top of page</small></a></td>
</tr>
</table>
<table class="footer2">
<tr>
<td class="LFooter">Seabreeze - Routing Toolbox</td>
<td class="RFooter"><small>Copyright &#169; 2008-2020 Sorbonne Universite. All rights reserved</small></td>
</tr>
</table>
</body>
</html>

View File

@ -1,26 +0,0 @@
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN'>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>Katabatic Documentation</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="SoC.css" rel="stylesheet" type="text/css">
<link href="tabs.css" rel="stylesheet" type="text/css">
</head>
<h1 id="pagetop" class="header">Seabreeze - Routing Toolbox</h1>
<!--
<center class="header">
<table class="header">
<tr>
<td><a href="customSummary.html">Summary</a></td>
<td><a href="namespaces.html">Namespaces</a></td>
<td><a href="customHierarchy.html">Class Hierarchy</a></td>
<td><a href="annotated.html">Classes</a></td>
<td><a href="functions.html">Member Index</a></td>
</tr>
</table>
</center>
-->
<br>
<body onload="javascript:toggleLevel(1)">

View File

@ -1,558 +0,0 @@
.sm
{
position:relative;
z-index:9999
}
.sm,.sm ul,.sm li
{
display:block;
list-style:none;
margin:0;
padding:2pt 7pt;
line-height:normal;
direction:ltr;
text-align:left;
-webkit-tap-highlight-color:rgba(0,0,0,0)
}
.sm-rtl,.sm-rtl ul,.sm-rtl li
{
direction:rtl;
text-align:right
}
.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6
{
margin:0;
padding:0
}
.sm ul
{
display:none
}
.sm li,.sm a
{
position:relative
}
.sm a
{
display:block
}
.sm a.disabled
{
cursor:not-allowed
}
.sm:after
{
content:"\00a0";
display:block;
height:0;
font:0/0 serif;
clear:both;
visibility:hidden;
overflow:hidden
}
.sm,.sm *,.sm *:before,.sm *:after
{
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
box-sizing:border-box
}
#doc-content
{
overflow:auto;
display:block;
padding:0;
margin:0;
-webkit-overflow-scrolling:touch
}
/*
.sm-dox
{
background-image:url("tab_b.png")
}
*/
/*
.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active
{
padding:0 12px;
padding-right:43px;
font-family:"Lucida Grande","Geneva","Helvetica",Arial,sans-serif;
font-size:13px;
font-weight:bold;
line-height:36px;
text-decoration:none;
text-shadow:0 1px 1px rgba(255,255,255,0.9);
color:#283a5d;
outline:0
}
*/
/*
.sm-dox a:hover
{
background-image:url("tab_a.png");
background-repeat:repeat-x;
color:white;
text-shadow:0 1px 1px black
}
*/
.sm-dox a.current
{
color:#d23600
}
.sm-dox a.disabled
{
color:#bbb
}
.sm-dox a span.sub-arrow
{
position:absolute;
top:50%;
margin-top:-14px;
left:auto;
right:3px;
width:28px;
height:28px;
overflow:hidden;
font:bold 12px/28px monospace!important;
text-align:center;
text-shadow:none;
background:rgba(255,255,255,0.5);
-moz-border-radius:5px;
-webkit-border-radius:5px;
border-radius:5px
}
.sm-dox a.highlighted span.sub-arrow:before
{
display:block;
content:'-'
}
/*
.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a
{
-moz-border-radius:5px 5px 0 0;
-webkit-border-radius:5px;
border-radius:5px 5px 0 0
}
.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul
{
-moz-border-radius:0 0 5px 5px;
-webkit-border-radius:0;
border-radius:0 0 5px 5px
}
.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted
{
-moz-border-radius:0;
-webkit-border-radius:0;
border-radius:0
}
*/
/*
.sm-dox ul
{
background:rgba(162,162,162,0.1)
}
*/
/*
.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active
{
font-size:12px;
border-left:8px solid transparent;
line-height:36px;
text-shadow:none;
background-color:white;
background-image:none
}
*/
/*
.sm-dox ul a:hover
{
background-image:url("tab_a.png");
background-repeat:repeat-x;
color:white;
text-shadow:0 1px 1px black
}
*/
.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active
{
border-left:16px solid transparent
}
.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active
{
border-left:24px solid transparent
}
.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active
{
border-left:32px solid transparent
}
.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active
{
border-left:40px solid transparent
}
.sm-dox ul
{
position:absolute;
width:12em
}
/*
.sm-dox li
{
float:left
}
.sm-dox.sm-rtl li
{
float:right
}
.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li
{
float:none
}
*/
.sm-dox a
{
white-space:nowrap
}
.sm-dox ul a,.sm-dox.sm-vertical a
{
white-space:normal
}
.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a
{
white-space:nowrap
}
/*
.sm-dox
{
padding:0 10px;
background-image:url("tab_b.png");
line-height:36px
}
*/
.sm-dox a span.sub-arrow
{
top:50%;
margin-top:-2px;
right:12px;
width:0;
height:0;
border-width:4px;
border-style:solid dashed dashed dashed;
border-color:#283a5d transparent transparent transparent;
background:transparent;
-moz-border-radius:0;
-webkit-border-radius:0;
border-radius:0
}
/*
.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted
{
padding:0 12px;
background-image:url("tab_s.png");
background-repeat:no-repeat;
background-position:right;
-moz-border-radius:0!important;
-webkit-border-radius:0;
border-radius:0!important
}
.sm-dox a:hover
{
background-image:url("tab_a.png");
background-repeat:repeat-x;
color:white;
text-shadow:0 1px 1px black
}
*/
.sm-dox a:hover span.sub-arrow
{
border-color:white transparent transparent transparent
}
.sm-dox a.has-submenu
{
padding-right:24px
}
.sm-dox li
{
border-top:0
}
.sm-dox>li>ul:before,.sm-dox>li>ul:after
{
content:'';
position:absolute;
top:-18px;
left:30px;
width:0;
height:0;
overflow:hidden;
border-width:9px;
border-style:dashed dashed solid dashed;
border-color:transparent transparent #bbb transparent
}
.sm-dox>li>ul:after
{
top:-16px;
left:31px;
border-width:8px;
border-color:transparent transparent #fff transparent
}
.sm-dox ul
{
border:1px solid #bbb;
padding:5px 0;
background:#fff;
/*
-moz-border-radius:5px!important;
-webkit-border-radius:5px;
border-radius:5px!important;
*/
-moz-box-shadow:0 5px 9px rgba(0,0,0,0.2);
-webkit-box-shadow:0 5px 9px rgba(0,0,0,0.2);
box-shadow:0 5px 9px rgba(0,0,0,0.2)
}
.sm-dox ul a span.sub-arrow
{
right:8px;
top:50%;
margin-top:-5px;
border-width:5px;
border-color:transparent transparent transparent #555;
border-style:dashed dashed dashed solid
}
.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted
{
color:#555;
background-image:none;
border:0!important;
color:#555;
background-image:none
}
/*
.sm-dox ul a:hover
{
background-image:url("tab_a.png");
background-repeat:repeat-x;
color:white;
text-shadow:0 1px 1px black
}
*/
.sm-dox ul a:hover span.sub-arrow
{
border-color:transparent transparent transparent white
}
.sm-dox span.scroll-up,.sm-dox span.scroll-down
{
position:absolute;
display:none;
visibility:hidden;
overflow:hidden;
background:#fff;
height:36px
}
.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover
{
background:#eee
}
.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow
{
border-color:transparent transparent #d23600 transparent
}
.sm-dox span.scroll-down:hover span.scroll-down-arrow
{
border-color:#d23600 transparent transparent transparent
}
.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow
{
position:absolute;
top:0;
left:50%;
margin-left:-6px;
width:0;
height:0;
overflow:hidden;
border-width:6px;
border-style:dashed dashed solid dashed;
border-color:transparent transparent #555 transparent
}
.sm-dox span.scroll-down-arrow
{
top:8px;
border-style:solid dashed dashed dashed;
border-color:#555 transparent transparent transparent
}
.sm-dox.sm-rtl a.has-submenu
{
padding-right:12px;
padding-left:24px
}
.sm-dox.sm-rtl a span.sub-arrow
{
right:auto;
left:12px
}
.sm-dox.sm-rtl.sm-vertical a.has-submenu
{
padding:10px 20px
}
.sm-dox.sm-rtl.sm-vertical a span.sub-arrow
{
right:auto;
left:8px;
border-style:dashed solid dashed dashed;
border-color:transparent #555 transparent transparent
}
.sm-dox.sm-rtl>li>ul:before
{
left:auto;
right:30px
}
.sm-dox.sm-rtl>li>ul:after
{
left:auto;
right:31px
}
.sm-dox.sm-rtl ul a.has-submenu
{
padding:10px 20px!important
}
.sm-dox.sm-rtl ul a span.sub-arrow
{
right:auto;
left:8px;
border-style:dashed solid dashed dashed;
border-color:transparent #555 transparent transparent
}
.sm-dox.sm-vertical
{
padding:10px 0;
-moz-border-radius:5px;
-webkit-border-radius:5px;
border-radius:5px
}
.sm-dox.sm-vertical a
{
padding:10px 20px
}
.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted
{
background:#fff
}
.sm-dox.sm-vertical a.disabled
{
background-image:url("tab_b.png")
}
.sm-dox.sm-vertical a span.sub-arrow
{
right:8px;
top:50%;
margin-top:-5px;
border-width:5px;
border-style:dashed dashed dashed solid;
border-color:transparent transparent transparent #555
}
.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after
{
display:none
}
.sm-dox.sm-vertical ul a
{
padding:10px 20px
}
.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted
{
background:#eee
}
.sm-dox.sm-vertical ul a.disabled
{
background:#fff
}
/* SoC Customisation. */
div#main-nav {
margin: 0pt;
border: 0pt;
padding: 0pt;
}
div ul#main-menu {
margin: 0pt;
border: 0pt;
padding: 0pt;
}
/*
.sm ul {
visibility: hidden;
overflow: hidden;
height: 0;
width: 0;
}
*/
.sm li {
list-style: none;
}
ul#main-menu {
display: table;
width: 100%;
}
ul#main-menu > li {
display: table-cell;
text-align: center;
/*width: 20%;*/
border-top: 1px solid black;
border-bottom: 1px solid black;
border-left: none;
border-right: 1px solid black;
padding: 2pt;
font-size: 90%;
}
ul#main-menu > li:first-child {
border-left: 1px solid black;
}
ul#main-menu > li > a {
border-bottom: none;
}
ul#main-menu > li:hover, ul#main-menu > li:hover > a, ul#main-menu > li > a:hover {
background-color: black;
color: white;
}
/*
.sm li {
margin: 0pt;
list-style: none;
font-size: 90%;
border-top: 1px solid black;
border-bottom: 1px solid black;
border-left: none;
border-right: 1px solid black;
display: table-cell;
text-align: center;
padding: 2pt;
width: 5%;
}
.sm li:first-child {
border-left: 1px solid black;
}
.sm li a {
border-style: none;
border-bottom: none;
}
.sm li:hover, .sm li:hover a, .sm li a:hover {
background-color: black;
color: white;
}
*/

View File

@ -1,73 +0,0 @@
# -*- explicit-buffer-name: "CMakeLists.txt<Seabreeze/src>" -*-
# include( ${QT_USE_FILE} )
include_directories( ${SEABREEZE_SOURCE_DIR}/src
${CORIOLIS_INCLUDE_DIR}
${HURRICANE_INCLUDE_DIR}
${CONFIGURATION_INCLUDE_DIR}
${QtX_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
${Python_INCLUDE_DIRS}
)
set( includes seabreeze/SeabreezeEngine.h
#seabreeze/GraphicSeabreezeEngine.h
)
set( pyIncludes seabreeze/Configuration.h
seabreeze/Delay.h
seabreeze/Node.h
seabreeze/Tree.h
seabreeze/Elmore.h
seabreeze/PySeabreezeEngine.h
#seabreeze/PyGraphicSeabreezeEngine.h
)
#set( mocIncludes seabreeze/GraphicSeabreezeEngine.h )
set( cpps Configuration.cpp
Delay.cpp
Node.cpp
Tree.cpp
Elmore.cpp
SeabreezeEngine.cpp
#GraphicSeabreezeEngine.cpp
)
set( pyCpps PySeabreeze.cpp
PySeabreezeEngine.cpp
#PyGraphicSeabreezeEngine.cpp
)
#qtX_wrap_cpp( mocCpps ${mocIncludes} )
set( depLibs ${CORIOLIS_PYTHON_LIBRARIES}
${CORIOLIS_LIBRARIES}
${HURRICANE_PYTHON_LIBRARIES}
${HURRICANE_GRAPHICAL_LIBRARIES}
${HURRICANE_LIBRARIES}
${CONFIGURATION_LIBRARY}
${BOOKSHELF_LIBRARY}
${CIF_LIBRARY}
${AGDS_LIBRARY}
${UTILITIES_LIBRARY}
${LEFDEF_LIBRARIES}
${OA_LIBRARIES}
${QtX_LIBRARIES}
${Boost_LIBRARIES}
${LIBXML2_LIBRARIES}
-lutil
${LIBEXECINFO_LIBRARIES}
)
add_library( Seabreeze ${cpps} ${mocCpps} ${pyCpps} )
set_target_properties( Seabreeze PROPERTIES VERSION 1.0 SOVERSION 1 )
target_link_libraries( Seabreeze ${depLibs} )
add_python_module( "${pyCpps}"
"${pyIncludes}"
"Do_not_generate_C_library"
Seabreeze
"Seabreeze;${depLibs}"
include/coriolis2/seabreeze
)
install( TARGETS Seabreeze DESTINATION lib${LIB_SUFFIX} )
install( FILES ${includes}
${mocIncludes} DESTINATION include/coriolis2/seabreeze )

View File

@ -1,102 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Configuration.cpp" |
// +-----------------------------------------------------------------+
#include <iostream>
#include <sstream>
#include <iomanip>
#include "hurricane/configuration/Configuration.h"
#include "hurricane/Warning.h"
#include "hurricane/Error.h"
#include "hurricane/Technology.h"
#include "hurricane/DataBase.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Contact.h"
#include "hurricane/Net.h"
#include "hurricane/Segment.h"
#include "hurricane/Cell.h"
#include "crlcore/Utilities.h"
#include "seabreeze/Configuration.h"
namespace Seabreeze {
using std::string;
using std::ostringstream;
using Hurricane::Warning;
using Hurricane::Error;
using Hurricane::Technology;
using Hurricane::RoutingPad;
using Hurricane::Contact;
using Hurricane::Segment;
using Hurricane::Cell;
using Hurricane::Net;
using Hurricane::DataBase;
using Hurricane::Record;
using Hurricane::Name;
using Hurricane::Layer;
using Hurricane::DbU;
//------------------------------------------------------------------------
// Class : "Seabreeze::Configuration"
Configuration::Configuration ()
: _Rct (1)
, _Rsm (1)
, _Csm (1)
{}
Configuration::~Configuration ()
{}
Configuration::Configuration ( const Configuration& other )
: _Rct (other._Rct)
, _Rsm (other._Rsm)
, _Csm (other._Csm)
{}
Configuration* Configuration::clone () const
{ return new Configuration( *this ); }
string Configuration::_getTypeName () const
{ return "Seabreeze::Configuration"; }
string Configuration::_getString () const
{
ostringstream os;
os << "<" << _getTypeName() << ">";
return os.str();
}
Record* Configuration::_getRecord () const
{
Record* record = new Record ( _getString() );
if (record != nullptr) {
record->add( getSlot("_Rct", _Rct) );
record->add( getSlot("_Rsm", _Rsm) );
record->add( getSlot("_Csm", _Csm) );
}
return record;
}
} // Seabreeze namespace.

View File

@ -1,71 +0,0 @@
// -*- C++ -*-
// //
// // This file is part of the Coriolis Software.
// // Copyright (c) SU 2022-2022, All Rights Reserved
// //
// // +-----------------------------------------------------------------+
// // | C O R I O L I S |
// // | S e a b r e e z e - Timing Analysis |
// // | |
// // | Author : Vu Hoang Anh PHAM |
// // | E-mail : Jean-Paul.Chaput@lip6.fr |
// // | =============================================================== |
// // | C++ Header : "./seabreeze/Delay.h" |
// // +-----------------------------------------------------------------+
#include <map>
#include <iostream>
#include "hurricane/RoutingPad.h"
#include "seabreeze/Delay.h"
#include "seabreeze/Elmore.h"
using namespace std;
namespace Seabreeze {
using Hurricane::RoutingPad;
//---------------------------------------------------------
// Class : Seabreeze::Delay
Delay::Delay ( Elmore* elmore, RoutingPad* sink )
: _elmore(elmore)
, _sink (sink)
, _delay (0.0)
{ }
Delay::~Delay ()
{ }
string Delay::_getTypeName () const
{ return "Seabreeze::Delay"; }
string Delay::_getString () const
{
string s = "<Delay ";
s += getString( _sink );
s += " d=" + getString( _delay );
s += ">";
return s;
}
Record* Delay::_getRecord () const
{
Record* record = new Record ( _getString() );
if (record != nullptr) {
record->add( getSlot("_elmore" , _elmore) );
record->add( getSlot("_sink" , _sink ) );
record->add( getSlot("_delay" , _delay ) );
}
return record;
}
} // Seabreeze namespace.

View File

@ -1,577 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Elmore.cpp" |
// +-----------------------------------------------------------------+
#include "hurricane/DebugSession.h"
#include "hurricane/Error.h"
#include "hurricane/Segment.h"
#include "hurricane/Plug.h"
#include "hurricane/Net.h"
#include "hurricane/Hook.h"
#include "seabreeze/Elmore.h"
#include "seabreeze/Node.h"
#include "seabreeze/SeabreezeEngine.h"
namespace Seabreeze {
using namespace std;
using Hurricane::Error;
using Hurricane::DBo;
using Hurricane::DbU;
using Hurricane::Plug;
using Hurricane::Net;
using Hurricane::Cell;
using Hurricane::Hook;
using Hurricane::Instance;
using Hurricane::Property;
using Hurricane::PrivateProperty;
using Hurricane::Component;
using Hurricane::Segment;
using Hurricane::DebugSession;
//---------------------------------------------------------
// Class : "Elmore"
Elmore::Elmore ( Net* net )
: _seabreeze(nullptr)
, _net (net)
, _driver (nullptr)
, _tree (new Tree(this))
, _delays ()
{}
Elmore::~Elmore ()
{
cdebug_log(199,0) << "Elmore::~Elmore() " << endl;
delete _tree;
for ( Delay* delay : _delays ) delete delay;
}
void Elmore::setup ()
{
cdebug_log(199,1) << "Elmore::findDriver()" << endl;
for ( RoutingPad* rp : _net->getRoutingPads() ) {
Plug* plug = static_cast<Plug*>( rp->getPlugOccurrence().getEntity() );
if (plug->getMasterNet()->getDirection() & Net::Direction::DirOut) {
if (_driver) {
cerr << Error( "Elmore::setup(): %s has more than one driver:\n"
" * Using: %s\n"
" * Ignoring: %s"
, getString(_net).c_str()
, getString(_driver).c_str()
, getString(rp).c_str()
) << endl;
continue;
}
_driver = rp;
} else {
_delays.push_back( new Delay(this,rp) );
}
}
cdebug_log(199,0) << "Found " << _delays.size() << " sink points:" << endl;
for ( Delay* delay : _delays ) {
cdebug_log(199,0) << "| " << delay << endl;
}
if (not _driver) {
cerr << Error( "Elmore::_postCreate(): No driver found on %s, aborting."
, getString(_net).c_str() ) << endl;
cdebug_tabw(199,-1);
return;
}
cdebug_tabw(199,-1);
}
const Configuration* Elmore::getConfiguration () const
{ return _seabreeze->getConfiguration(); }
Delay* Elmore::getDelay ( RoutingPad* rp ) const
{
for ( Delay* delay : _delays ) {
if (delay->getSink() == rp) return delay;
}
return nullptr;
}
void Elmore::buildTree ()
{
if (not _driver) {
cerr << Error( "Elmore::buildTree(): Net has no driver, aborting." ) << endl;
return;
}
Contact* rootContact = nullptr;
for ( Component* component : _driver->getSlaveComponents() ) {
Contact* contact = dynamic_cast<Contact*>(component);
if (contact) {
rootContact = contact;
break;
}
}
if (not rootContact) {
cerr << Error( "Elmore::buildTree(): No Contact anchored on %s."
, getString(_driver).c_str() ) << endl;
return;
}
cdebug_log(199,1) << "Elmore::buildTree()" << endl;
cdebug_log(199,0) << "Root contact " << rootContact << endl;
Node* rootNode = new Node( nullptr, rootContact );
double R = 0;
double C = 0;
setRC( &R, &C, rootContact, nullptr );
rootNode->setR( R );
rootNode->setC( (C == 0.0) ? 0.0 : 1/C );
Segment* segment = nullptr;
size_t count = 0;
for ( Component* component : rootContact->getSlaveComponents() ) {
segment = dynamic_cast<Segment*>( component );
if (not segment) continue;
++count;
}
if (count != 1) {
cerr << Error( "Elmore::buildTree(): Terminal contact has more than one segment (%d), aborting.\n"
" (on %s)"
, count
, getString(rootContact).c_str()
) << endl;
cdebug_tabw(199,-1);
return;
}
buildFromNode( rootNode, segment );
//---------- More than 1 Contact in main RoutingPad ------- ( 1 )
for ( Component* component : _driver->getSlaveComponents() ) {
Contact* sideContact = dynamic_cast<Contact*>(component);
if (sideContact && sideContact != rootContact) {
Node* sideNode = new Node( rootNode, sideContact );
double sR = 0;
double sC = 0;
setRC ( &sR, &sC, sideContact, nullptr );
sideNode->setR( sR );
sideNode->setC( (sC == 0.0 ) ? 0.0: 1/sC );
Segment* sideSegment = nullptr;
size_t count = 0;
for ( Component* component : sideContact->getSlaveComponents() ) {
sideSegment = dynamic_cast<Segment*>( component );
if (not sideSegment) continue;
++count;
}
if (count != 1) {
cerr << Error( "Elmore::buildTree(): Terminal contact has more than one segment (%d), aborting.\n"
" (on %s)"
, count
, getString(sideContact).c_str()
) << endl;
cdebug_tabw(199,-1);
return;
}
buildFromNode( sideNode, sideSegment );
}
}
//---------------------------------------------------------------
/*
//---------- More than 1 Contact in 1 RoutingPad ---------- ( 2 )
for ( RoutingPad* rp : getNet()->getRoutingPads() ) {
Node* mainNode = nullptr;
for ( Component* rpComp : rp->getSlaveComponents() ) {
Contact* mainContact = dynamic_cast<Contact*>(rpComp);
if ( not mainContact ) continue;
mainNode = _tree->getNode( mainContact );
if ( mainNode ) break;
}
if ( mainNode == nullptr ) {
cerr << "No mainNode found!" << endl;
break;
}
for ( Component* rpComp : rp->getSlaveComponents() ) {
Contact* sideContact = dynamic_cast<Contact*>(rpComp);
if ( not sideContact || sideContact == mainNode->contact() ) continue;
Node* sideNode = new Node( mainNode, sideContact );
double sR = 0;
double sC = 0;
setRC( &sR, &sC, sideContact, nullptr );
sideNode->setR( sR );
sideNode->setC( (sC == 0.0) ? 0.0 : 1/sC );
Segment* sideSegment = nullptr;
size_t sideCount = 0;
for ( Component* component : sideContact->getSlaveComponents() ) {
sideSegment = dynamic_cast<Segment*>( component );
if (not sideSegment) continue;
++sideCount;
}
if (sideCount != 1) {
cerr << Error( "Elmore::buildTree(): Terminal side contact has to have one segment (%d), aborting.\n"
" (on %s)"
, sideCount
, getString(sideContact).c_str()
) << endl;
cdebug_tabw(199,-1);
return;
}
buildFromNode( sideNode, sideSegment );
}
}
//---------------------------------------------------------
*/
cdebug_log(199,0) << "Elmore::buildTree() - Finished" << endl;
cdebug_tabw(199,-1);
_tree->print( cerr );
}
void Elmore::buildFromNode ( Node* rootNode, Segment* toSegment )
{
if (not rootNode->contact()) {
cerr << Error( "Elmore::buildFromNode(): rootNode has no contact, aborting." ) << endl;
return;
}
_tree->addNode( rootNode );
cdebug_log(199,1) << "Elmore::buildFromNode()" << endl;
cdebug_log(199,0) << "rootNode->_contact=" << rootNode->contact() << endl;
cdebug_log(199,0) << "toSegment=" << toSegment << endl;
Contact* opposite = dynamic_cast<Contact*>( toSegment->getOppositeAnchor( rootNode->contact()) );
if (not opposite or (rootNode->parent() and (opposite == rootNode->parent()->contact())) ) {
cdebug_tabw(199,-1);
return;
}
cdebug_log(199,0) << "opposite=" << opposite << endl;
double Rb = 0;
double Cb = 0;
opposite = buildBranch( &Rb, &Cb, opposite );
if (not opposite) {
cerr << Error( "Elmore::buildFromNode(): Branch end up on NULL Contact, pruned." ) << endl;
cdebug_tabw(199,-1);
return;
}
cdebug_log(199,0) << "Reached fork " << opposite << endl;
Node* node = new Node( rootNode, opposite);
node->setR( Rb );
node->setC( (Cb == 0.0) ? 0.0 : 1/Cb );
cdebug_log(199,0) << "R=" << Rb << " C=" << Cb << endl;
int count = 0;
for ( Component* component : opposite->getSlaveComponents() ) {
count += (dynamic_cast<Segment*>(component)) ? 1 : 0;
}
cdebug_log(199,0) << "Node's contact has : " << count << " segments" << endl;
if (count == 1) {
_tree->addNode( node );
} else if (count > 2) {
for ( Component* component : opposite->getSlaveComponents() ) {
Segment* segment = dynamic_cast<Segment*>( component );
if (not segment) continue;
cdebug_log(199,0) << "| " << segment << endl;
Contact* target = dynamic_cast<Contact*>( segment->getOppositeAnchor(opposite) );
if (not target) {
cerr << Error( "Elmore::buildFromNode(): Segment missing opposite anchor. pruned." ) << endl;
continue;
}
cdebug_log(199,0) << "target=" << target << endl;
if (not _tree->isReached(target)) {
buildFromNode( node, segment);
}
}
}
//---------- More than 1 Contact in this RoutingPad ------- ( 1 )
Hook* masterHook = opposite->getAnchorHook()->getMasterHook();
RoutingPad* currentRP = nullptr;
if ( masterHook ) {
currentRP = dynamic_cast<RoutingPad*>( masterHook->getComponent() );
cdebug_log(199,0) << " Look back = " <<currentRP << endl;
}
if ( currentRP ) {
for ( Component* component : currentRP->getSlaveComponents() ) {
Contact* sideContact = dynamic_cast<Contact*>(component);
if (sideContact && sideContact != opposite) {
Node* sideNode = new Node( node, sideContact );
double sR = 0;
double sC = 0;
setRC ( &sR, &sC, sideContact, nullptr );
sideNode->setR( sR );
sideNode->setC( (sC == 0.0 ) ? 0.0: 1/sC );
Segment* sideSegment = nullptr;
size_t count = 0;
for ( Component* component : sideContact->getSlaveComponents() ) {
sideSegment = dynamic_cast<Segment*>( component );
if (not sideSegment) continue;
++count;
}
if (count != 1) {
cerr << Error( "Elmore::buildTree(): Terminal contact has more than one segment (%d), aborting.\n"
" (on %s)"
, count
, getString(sideContact).c_str()
) << endl;
cdebug_tabw(199,-1);
return;
}
buildFromNode( sideNode, sideSegment );
}
}
}
//---------------------------------------------------------------
cdebug_tabw(199,-1);
}
Contact* Elmore::buildBranch ( double* R, double* C, Contact* current )
{
cdebug_log(199,1) << "Elmore::buildBranch()" << endl;
cdebug_log(199,0) << "current=" << current << endl;
while ( true ) {
_tree->setReached( current );
int count = 0;
Segment* segment = nullptr;
for ( Component* component : current->getSlaveComponents() ) {
segment = dynamic_cast<Segment*>( component );
if (not segment) continue;
Contact* opposite = dynamic_cast<Contact*>( segment->getOppositeAnchor(current) );
if (opposite and _tree->isReached(opposite)) {
setRC( R, C, current, segment );
cdebug_log(199,0) << "current=" << current << endl;
cdebug_log(199,0) << "segment=" << segment << endl;
cdebug_log(199,0) << "R=" << *R << endl;
cdebug_log(199,0) << "C=" << *C << endl;
}
++count;
}
if (not count) {
cerr << Error( "Elmore::buildBranch(): Contact seems to be a dead end, pruning.\n"
" (on %s)"
, getString(current).c_str() ) << endl;
cdebug_tabw(199,-1);
return nullptr;
}
else if (count != 2) {
break;
}
Contact* next = nullptr;
for ( Component* component : current->getSlaveComponents() ) {
segment = dynamic_cast<Segment*>( component );
if (not segment) continue;
cdebug_log(199,0) << "| " << segment << endl;
Contact* opposite = dynamic_cast<Contact*>( segment->getOppositeAnchor(current) );
cdebug_log(199,0) << "opposite=" << opposite << endl;
if (opposite and not _tree->isReached(opposite))
next = opposite;
}
if (not next) {
cerr << Error( "Elmore::buildBranch(): Wire loop detected.\n"
" (on %s)"
, getString(current).c_str() ) << endl;
cdebug_tabw(199,-1);
return nullptr;
}
current = next;
}
cdebug_tabw(199,-1);
return current;
}
void Elmore::setRC ( double* R, double* C, Contact* contact, Segment* segment )
{
double Rcont = getConfiguration()->getRct();
//double Hcont = DbU::toPhysical( contact->getHeight(), DbU::UnitPower::Nano );
//double Wcont = DbU::toPhysical( contact->getWidth (), DbU::UnitPower::Nano );
double Wcont = DbU::toLambda( contact->getWidth () );
double Acont = Wcont * Wcont;
*R += Rcont * Acont;
if (not segment) {
*C = 0;
} else {
double Rseg = getConfiguration()->getRsm();
double Cseg = getConfiguration()->getCsm();
//double Lseg = DbU::toPhysical( segment->getLength(), DbU::UnitPower::Nano );
//double Wseg = DbU::toPhysical( segment->getWidth (), DbU::UnitPower::Nano );
double Lseg = DbU::toLambda( segment->getLength() );
double Wseg = DbU::toLambda( segment->getWidth () );
double Aseg = Lseg * Wseg;
cdebug_log(199,0) << "Elmore::setRC() on " << segment << endl;
cdebug_log(199,0) << " Lseg=" << Lseg << " Wseg=" << Wseg << " Aseg=" << Aseg << endl;
*R += Rseg * Aseg;
*C += (Aseg) ? 1/(Cseg*Aseg) : 0.0;
}
}
Delay* Elmore::delayElmore ( RoutingPad* rp )
{ return _tree->computeElmoreDelay( rp ); }
void Elmore::toTree ( ostream& os ) const
{ _tree->print( os ); }
string Elmore::_getTypeName () const
{ return "Seabreeze::Elmore"; }
string Elmore::_getString () const
{
string s = "<" + _getTypeName() + ">";
return s;
}
Record* Elmore::_getRecord () const
{
Record* record = new Record ( _getString() );
if (record != nullptr) {
record->add( getSlot("_seabreeze", _seabreeze) );
record->add( getSlot("_net" , _net ) );
record->add( getSlot("_driver" , _driver ) );
record->add( getSlot("_tree" , _tree ) );
record->add( getSlot("_delays" , &_delays ) );
}
return record;
}
//---------------------------------------------------------
// Class : "ElmoreProperty"
Name ElmoreProperty::_name = "Seabreeze::Elmore";
ElmoreProperty::ElmoreProperty ( Net* net )
: PrivateProperty()
, _elmore (net)
{
if (net) {
SeabreezeEngine* seabreeze
= dynamic_cast<SeabreezeEngine*>( ToolEngine::get( net->getCell(), "Seabreeze" ));
if (not seabreeze) {
cerr << Error( "ElmoreProperty::ElmoreProperty(): Cannot find SeabreezeEngine on %s."
, getString(net->getCell()).c_str()) << endl;
}
_elmore.setSeabreeze( seabreeze );
_elmore.setup();
}
cdebug_log(199,0) << "ElmoreProperty::ElmoreProperty() on " << net << endl;
}
ElmoreProperty* ElmoreProperty::create ( Net* net )
{
ElmoreProperty* property = new ElmoreProperty( net );
property->_postCreate();
return property;
}
Name ElmoreProperty::staticGetName ()
{ return _name; }
Name ElmoreProperty::getName () const
{ return _name; }
string ElmoreProperty::_getTypeName () const
{ return "ElmoreProperty"; }
string ElmoreProperty::_getString () const
{
string s = PrivateProperty::_getString ();
s.insert ( s.length() - 1 , " " + getString(&_elmore) );
return s;
}
Record* ElmoreProperty::_getRecord () const
{
Record* record = PrivateProperty::_getRecord();
if ( record ) {
record->add( getSlot( "_name" , _name ) );
record->add( getSlot( "_elmore", &_elmore ) );
}
return record;
}
//---------------------------------------------------------
// Class : "ElmoreExtension"
Elmore* ElmoreExtension::create ( Net* net )
{
cdebug_log(199,1) << "ElmoreExtension::create() " << net << endl;
Elmore* elmore = get( net );
if (not elmore) {
ElmoreProperty* property = new ElmoreProperty( net );
net->put( property );
elmore = property->getElmore();
}
cdebug_tabw(199,-1);
return elmore;
}
void ElmoreExtension::destroy ( Net* net )
{
cdebug_log(199,1) << "ElmoreExtension::destroy() " << net << endl;
Property* property = net->getProperty( ElmoreProperty::staticGetName() );
if (property) net->remove( property );
cdebug_tabw(199,-1);
}
Elmore* ElmoreExtension::get ( Net* net )
{
Elmore* elmore = nullptr;
Property* property = net->getProperty( ElmoreProperty::staticGetName() );
if (property) elmore = static_cast<ElmoreProperty*>( property )->getElmore();
return elmore;
}
} // Seabreeze namespace.

View File

@ -1,86 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Node.cpp" |
// +-----------------------------------------------------------------+
#include <iostream>
#include "seabreeze/Node.h"
namespace Seabreeze {
using std::string;
Node::Node ()
: _R (0.0)
, _Rt (0.0)
, _C (0.0)
, _parent (nullptr)
, _childs ()
, _contact(nullptr)
, _label (0)
, _ap (0)
{ }
Node::Node ( Node* parent, Contact* contact )
: _R (0.0)
, _Rt (0.0)
, _C (0.0)
, _parent (parent)
, _childs ()
, _contact(contact)
, _label (0)
, _ap (0)
{
if (parent) parent->addChild( this );
}
Node::~Node ()
{ }
string Node::_getTypeName () const
{ return "Seabreeze::Node"; }
string Node::_getString () const
{
string s = "<Node ";
s += getString( _contact );
s += " R=" + getString( _R );
s += " C=" + getString( _C );
s += ">";
return s;
}
Record* Node::_getRecord () const
{
Record* record = new Record ( _getString() );
if (record != nullptr) {
record->add( getSlot("_R" , _R ) );
record->add( getSlot("_Rt" , _Rt ) );
record->add( getSlot("_C" , _C ) );
record->add( getSlot("_parent" , _parent ) );
record->add( getSlot("_childs" , &_childs ) );
record->add( getSlot("_contact", _contact) );
record->add( getSlot("_label" , _label ) );
record->add( getSlot("_ap" , _ap ) );
}
return record;
}
} // Seabreeze namespace.

View File

@ -1,103 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2017-2021, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | T o o l E n g i n e T u t o r i a l |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./PySeabreeze.cpp" |
// +-----------------------------------------------------------------+
#include "hurricane/isobar/PyHurricane.h"
#include "hurricane/isobar/PyCell.h"
#include "seabreeze/PySeabreezeEngine.h"
namespace Seabreeze {
using std::cerr;
using std::endl;
using Hurricane::tab;
using Isobar::__cs;
using Isobar::getPyHash;
using CRL::PyTypeToolEngine;
// using CRL::PyTypeGraphicTool;
#if !defined(__PYTHON_MODULE__)
// +=================================================================+
// | "PySeabreeze" Shared Library Code Part |
// +=================================================================+
# else // End of PyHurricane Shared Library Code Part.
// +=================================================================+
// | "PySeabreeze" Python Module Code Part |
// +=================================================================+
extern "C" {
// +-------------------------------------------------------------+
// | "PySeabreeze" Module Methods |
// +-------------------------------------------------------------+
static PyMethodDef PySeabreeze_Methods[] =
{ {NULL, NULL, 0, NULL} /* sentinel */
};
static PyModuleDef PySeabreeze_ModuleDef =
{ PyModuleDef_HEAD_INIT
, .m_name = "Seabreeze"
, .m_doc = "Show how to interface Coriolis/C++ to Python."
, .m_size = -1
, .m_methods = PySeabreeze_Methods
};
// ---------------------------------------------------------------
// Module Initialization : "PyInit_Seabreeze ()"
PyMODINIT_FUNC PyInit_Seabreeze ( void )
{
cdebug_log(40,0) << "PyInit_Seabreeze()" << endl;
PySeabreezeEngine_LinkPyType();
//PyGraphicSeabreezeEngine_LinkPyType();
PYTYPE_READY_SUB( SeabreezeEngine , ToolEngine );
//PYTYPE_READY_SUB( GraphicSeabreezeEngine, GraphicTool );
PyObject* module = PyModule_Create( &PySeabreeze_ModuleDef );
if (module == NULL) {
cerr << "[ERROR]\n"
<< " Failed to initialize Seabreeze module." << endl;
return NULL;
}
Py_INCREF( &PyTypeSeabreezeEngine );
PyModule_AddObject( module, "SeabreezeEngine", (PyObject*)&PyTypeSeabreezeEngine );
//Py_INCREF( &PyTypeGraphicSeabreezeEngine );
//PyModule_AddObject( module, "GraphicSeabreezeEngine", (PyObject*)&PyTypeGraphicSeabreezeEngine );
return module;
}
} // End of extern "C".
#endif // Python Module Code Part.
} // Seabreeze namespace.

View File

@ -1,215 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2017-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | T o o l E n g i n e T u t o r i a l |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./PySeabreezeEngine.cpp" |
// +-----------------------------------------------------------------+
#include <functional>
#include "hurricane/isobar/PyCell.h"
#include "hurricane/viewer/PyCellViewer.h"
#include "hurricane/isobar/PyNet.h"
#include "hurricane/viewer/ExceptionWidget.h"
#include "hurricane/Cell.h"
#include "crlcore/Utilities.h"
#include "seabreeze/PySeabreezeEngine.h"
# undef ACCESS_OBJECT
# undef ACCESS_CLASS
# define ACCESS_OBJECT _baseObject._object
# define ACCESS_CLASS(_pyObject) &(_pyObject->_baseObject)
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(SeabreezeEngine,seabreeze,function)
namespace Seabreeze {
using std::cerr;
using std::endl;
using std::hex;
using std::ostringstream;
using Hurricane::tab;
using Hurricane::Exception;
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::ExceptionWidget;
using Isobar::ProxyProperty;
using Isobar::ProxyError;
using Isobar::ConstructorError;
using Isobar::HurricaneError;
using Isobar::HurricaneWarning;
using Isobar::getPyHash;
using Isobar::ParseOneArg;
using Isobar::ParseTwoArg;
using Isobar::PyCell;
using Isobar::PyCell_Link;
using Isobar::PyCellViewer;
using Isobar::PyTypeCellViewer;
using Isobar::PyNet;
using CRL::PyToolEngine;
extern "C" {
#if defined(__PYTHON_MODULE__)
// +=================================================================+
// | "PySeabreezeEngine" Python Module Code Part |
// +=================================================================+
static PyObject* PySeabreezeEngine_get ( PyObject*, PyObject* args )
{
cdebug_log(40,0) << "PySeabreezeEngine_get()" << endl;
SeabreezeEngine* seabreeze = NULL;
HTRY
PyObject* arg0;
if (not ParseOneArg("Seabreeze.get", args, CELL_ARG, &arg0)) return NULL;
seabreeze = SeabreezeEngine::get(PYCELL_O(arg0));
HCATCH
return PySeabreezeEngine_Link(seabreeze);
}
static PyObject* PySeabreezeEngine_create ( PyObject*, PyObject* args )
{
cdebug_log(40,0) << "PySeabreezeEngine_create()" << endl;
SeabreezeEngine* seabreeze = NULL;
HTRY
PyObject* arg0;
if (not ParseOneArg("Seabreeze.get", args, CELL_ARG, &arg0)) return NULL;
Cell* cell = PYCELL_O(arg0);
seabreeze = SeabreezeEngine::get(cell);
if (seabreeze == NULL) {
seabreeze = SeabreezeEngine::create(cell);
} else
cerr << Warning("%s already has a Seabreeze engine.",getString(cell).c_str()) << endl;
HCATCH
return PySeabreezeEngine_Link(seabreeze);
}
static PyObject* PySeabreezeEngine_setViewer ( PySeabreezeEngine* self, PyObject* args )
{
cdebug_log(40,0) << "PySeabreezeEngine_setViewer ()" << endl;
HTRY
METHOD_HEAD( "SeabreezeEngine.setViewer()" )
PyObject* pyViewer = NULL;
if (not PyArg_ParseTuple(args,"O:EtesianEngine.setViewer()",&pyViewer)) {
PyErr_SetString( ConstructorError, "Bad parameters given to EtesianEngine.setViewer()." );
return NULL;
}
if (IsPyCellViewer(pyViewer)) {
seabreeze->setViewer( PYCELLVIEWER_O(pyViewer) );
}
HCATCH
Py_RETURN_NONE;
}
/*
PyObject* PySeabreezeEngine_runTool ( PySeabreezeEngine* self )
{
cdebug_log(40,0) << "PySeabreezeEngine_runTool()" << endl;
Cell* cell = NULL;
HTRY
METHOD_HEAD("SeabreezeEngine.runTool()")
if (seabreeze->getViewer()) {
if (ExceptionWidget::catchAllWrapper( std::bind(&SeabreezeEngine::runTool,seabreeze) )) {
PyErr_SetString( HurricaneError, "SeabreezeEngine::runTool() has thrown an exception (C++)." );
return NULL;
}
cell = seabreeze->getCell();
} else {
cell = seabreeze->runTool();
}
HCATCH
return PyCell_Link( cell );
}
*/
static PyObject* PySeabreezeEngine_buildElmore ( PySeabreezeEngine* self, PyObject* args )
{
cdebug_log(40,0) << "PySeabreezeEngine_buildElmore()" << endl;
HTRY
PyObject* arg0 = NULL;
METHOD_HEAD("SeabreezeEngine.buildElmore()")
if (not ParseOneArg("Seabreeze.buildElmore()", args, NET_ARG, &arg0)) return NULL;
seabreeze->buildElmore(PYNET_O(arg0));
HCATCH
Py_RETURN_NONE;
}
// Standart Accessors (Attributes).
// Standart Destroy (Attribute).
DBoDestroyAttribute(PySeabreezeEngine_destroy,PySeabreezeEngine)
PyMethodDef PySeabreezeEngine_Methods[] =
{ { "get" , (PyCFunction)PySeabreezeEngine_get , METH_VARARGS|METH_STATIC
, "Returns the Seabreeze engine attached to the Cell, None if there isnt't." }
, { "create" , (PyCFunction)PySeabreezeEngine_create , METH_VARARGS|METH_STATIC
, "Create a Seabreeze engine on this cell." }
, { "setViewer" , (PyCFunction)PySeabreezeEngine_setViewer , METH_VARARGS
, "Associate a Viewer to this SeabreezeEngine." }
//, { "runDemoPart1" , (PyCFunction)PySeabreezeEngine_runDemoPart1 , METH_NOARGS
// , "Run the first part of the demo." }
, { "buildElmore" , (PyCFunction)PySeabreezeEngine_buildElmore , METH_VARARGS
, "Run the Seabreeze tool." }
, { "destroy" , (PyCFunction)PySeabreezeEngine_destroy , METH_NOARGS
, "Destroy the associated hurricane object. The python object remains." }
, {NULL, NULL, 0, NULL} /* sentinel */
};
DBoDeleteMethod(SeabreezeEngine)
PyTypeObjectLinkPyType(SeabreezeEngine)
#else // End of Python Module Code Part.
// +=================================================================+
// | "PySeabreezeEngine" Shared Library Code Part |
// +=================================================================+
// Link/Creation Method.
PyTypeInheritedObjectDefinitions(SeabreezeEngine,PyToolEngine)
DBoLinkCreateMethod(SeabreezeEngine)
#endif // Shared Library Code Part.
} // extern "C".
} // Seabreeze namespace.

View File

@ -1,158 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./SeabreezeEngine.cpp" |
// +-----------------------------------------------------------------+
#include <iomanip>
#include "hurricane/utilities/Path.h"
#include "hurricane/DebugSession.h"
#include "hurricane/UpdateSession.h"
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "hurricane/Breakpoint.h"
#include "hurricane/Layer.h"
#include "hurricane/Net.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Plug.h"
#include "hurricane/Cell.h"
#include "hurricane/Instance.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "crlcore/AllianceFramework.h"
#include "seabreeze/SeabreezeEngine.h"
#include "seabreeze/Elmore.h"
namespace Seabreeze {
using namespace std;
using Hurricane::dbo_ptr;
using Hurricane::UpdateSession;
using Hurricane::DebugSession;
using Hurricane::tab;
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::Breakpoint;
using Hurricane::Timer;
using Hurricane::DbU;
using Hurricane::Box;
using Hurricane::Layer;
using Hurricane::DataBase;
using Hurricane::Technology;
using Hurricane::Component;
using Hurricane::Contact;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::RoutingPad;
using Hurricane::Cell;
using Hurricane::Plug;
using Hurricane::Instance;
using Hurricane::Transformation;
using Hurricane::Occurrence;
//---------------------------------------------------------
// Class : "Seabreeze::SeabreezeEngine".
Name SeabreezeEngine::_toolName = "Seabreeze";
const Name& SeabreezeEngine::staticGetName ()
{ return _toolName; }
SeabreezeEngine* SeabreezeEngine::create ( Cell* cell )
{
SeabreezeEngine* seabreeze = new SeabreezeEngine ( cell );
seabreeze->_postCreate();
return seabreeze;
}
SeabreezeEngine* SeabreezeEngine::get ( const Cell* cell )
{ return static_cast<SeabreezeEngine*>(ToolEngine::get(cell, staticGetName())); }
const Name& SeabreezeEngine::getName () const
{ return _toolName; };
string SeabreezeEngine::_getTypeName () const
{ return getString(_toolName); }
string SeabreezeEngine::_getString () const
{
ostringstream os;
os << "<" << _toolName << " " << _cell->getName() << ">";
return os.str();
}
Record* SeabreezeEngine::_getRecord () const
{
Record* record = Super::_getRecord();
record->add( getSlot("_configuration", _configuration) );
return record;
}
void SeabreezeEngine::buildElmore ( Net* net )
{
DebugSession::open( net, 190, 200 );
cdebug_log(199,1) << "SeabreezeEngine::buildElmore()" << endl;
cdebug_log(199,0) << "Run on " << net << endl;
Elmore* elmore = ElmoreExtension::create( net );
elmore->buildTree();
cerr << "Net has " << elmore->getDelays().size() << " sink(s)." << endl;
for ( RoutingPad* rp : net->getRoutingPads() ) {
Plug* plug = static_cast<Plug*>( rp->getPlugOccurrence().getEntity() );
if (plug->getMasterNet()->getDirection() & Net::Direction::DirOut) {
continue;
}
cerr << "| Elmore's delay: " << elmore->delayElmore(rp) << endl;
}
cdebug_tabw(199,-1);
DebugSession::close();
}
SeabreezeEngine::SeabreezeEngine ( Cell* cell )
: Super (cell)
, _configuration(new Configuration())
, _viewer (NULL)
{}
SeabreezeEngine::~SeabreezeEngine ()
{
delete _configuration;
}
void SeabreezeEngine::_postCreate()
{
Super::_postCreate ();
}
void SeabreezeEngine::_preDestroy ()
{}
} // Seabreeze namespace.

View File

@ -1,207 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Tree.cpp" |
// +-----------------------------------------------------------------+
#include <string>
#include <iostream>
#include <algorithm>
#include "hurricane/Error.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Net.h"
#include "seabreeze/Elmore.h"
#include "seabreeze/Tree.h"
#include "seabreeze/Node.h"
#include "seabreeze/Delay.h"
namespace Seabreeze {
using std::string;
using std::find;
using std::set;
using std::cerr;
using std::endl;
using std::ostream;
using Hurricane::Error;
using Hurricane::Hook;
using Hurricane::Component;
Tree::Tree ( Elmore* elmore )
: _elmore (elmore)
, _nodes ()
, _reacheds()
{}
Tree::~Tree ()
{
for( Node* n : _nodes) delete n;
}
Node* Tree::getNode ( Contact* contact )
{
for ( Node* n : _nodes ) {
if (n->contact() == contact) return n;
}
return nullptr;
}
void Tree::addNode ( Node* node )
{
if (find(_nodes.begin(), _nodes.end(), node) == _nodes.end()) {
setReached( node->contact() );
_nodes.push_back( node );
}
}
void Tree::markNodeAfter ( Node *ni )
{
if (not ni) return;
ni->setAp( 1 );
for ( Node* child : ni->childs() ) {
markNodeAfter( child );
}
}
void Tree::getBranch ( Contact* contact )
{
for ( Node* n : _nodes ) {
n->setLabel(0);
}
Node *ni = getNode( contact );
ni->setLabel(1);
while ( ni->parent() ) {
ni->parent()->setLabel(1);
ni = ni->parent();
}
}
Delay* Tree::computeElmoreDelay ( RoutingPad* rp )
{
if (not rp) {
cerr << Error( "Tree::computeDelay(): Sink RoutingPad argument is NULL." ) << endl;
return nullptr;
}
Delay* delay = _elmore->getDelay( rp );
if (not delay) {
cerr << Error( "Tree::computeDelay(): No delay for %s, aborting."
, getString(rp).c_str() ) << endl;
return nullptr;
}
Contact* sink = nullptr;
for ( Component* component : rp->getSlaveComponents() ) {
Contact* contact = dynamic_cast<Contact*>( component );
if (contact) {
sink = contact;
break;
}
}
if (not sink) {
cerr << Error( "Tree::computeDelay(): No Contact anchored on RoutingPad, aborting.\n"
" (on %s)"
, getString(rp).c_str()
) << endl;
return nullptr;
}
Hook* masterHook = sink->getAnchorHook()->getMasterHook();
if (masterHook) {
RoutingPad* myrp = dynamic_cast<RoutingPad*>( masterHook->getComponent() );
cdebug_log(199,0) << " Look back=" << myrp << endl;
}
cdebug_log(199,1) << "Tree::computeDelay()" << endl;
cdebug_log(199,0) << " rp=" << rp << endl;
cdebug_log(199,0) << " sink=" << sink << endl;
getBranch( sink );
Node* ni = getNode( sink );
markNodeAfter( ni );
ni->setAp( 0 );
// Compute Rt of all nodes
for ( size_t k = 0; k < _nodes.size(); k++ ) {
if (k == 0)
_nodes[k]->setRt( _nodes[k]->R() );
else {
if (_nodes[k]->ap() == 0) {
if (_nodes[k]->label() == 1) {
_nodes[k]->setRt( _nodes[k]->parent()->Rt() + _nodes[k]->R() );
} else {
_nodes[k]->setRt( _nodes[k]->parent()->Rt() );
}
} else {
_nodes[k]->setRt( ni->Rt() );
}
}
}
// Compute Elmore delay time
delay->setDelay( 0.0 );
for ( size_t k = 0; k < _nodes.size(); k++ ) {
delay->incDelay( (_nodes[k]->Rt()) * (_nodes[k]->C()) );
}
return delay;
}
void Tree::printNode ( ostream& os, Node* node, size_t depth )
{
string indent ( depth*2, ' ');
os << indent << node->contact() << " R=" << node->R() << " C=" << node->C() << endl;
for ( Node* child : node->childs() ) {
printNode( os, child, depth+1 );
}
}
void Tree::print ( ostream& os )
{
os << "Elmore Tree of " << _nodes[0]->contact()->getNet() << endl;
os << " Tree has " << _nodes.size() << " nodes :" << endl;
printNode( os, _nodes[0], 0 );
}
string Tree::_getTypeName () const
{ return "Seabreeze::Tree"; }
string Tree::_getString () const
{
string s = "<" + _getTypeName() + ">";
return s;
}
Record* Tree::_getRecord () const
{
Record* record = new Record ( _getString() );
if (record != nullptr) {
record->add( getSlot("_nodes" , &_nodes ) );
record->add( getSlot("_reacheds", &_reacheds) );
}
return record;
}
} // Seabreeze namespace.

View File

@ -1,64 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./seabreeze/Configuration.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <string>
#include <vector>
#include <hurricane/DbU.h>
namespace Seabreeze {
using std::string;
using Hurricane::Record;
using Hurricane::Name;
using Hurricane::Layer;
using Hurricane::DbU;
using Hurricane::Contact;
using Hurricane::Segment;
//------------------------------------------------------------------------
// Class : "Seabreeze::Configuration"
class Configuration {
public :
Configuration ();
Configuration ( const Configuration& );
virtual ~Configuration ();
virtual Configuration* clone () const;
inline double getRct () const;
inline double getRsm () const;
inline double getCsm () const;
string _getTypeName () const;
string _getString () const;
Record* _getRecord () const;
protected :
// Attributes
double _Rct;
double _Rsm;
double _Csm;
private :
Configuration& operator= ( const Configuration& ) = delete;
};
inline double Configuration::getRct () const { return _Rct; }
inline double Configuration::getRsm () const { return _Rsm; }
inline double Configuration::getCsm () const { return _Csm; }
} // Seabreeze namespace.
INSPECTOR_P_SUPPORT(Seabreeze::Configuration);

View File

@ -1,64 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./seabreeze/Delay.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <map>
#include <iostream>
#include "hurricane/RoutingPad.h"
namespace Seabreeze {
using Hurricane::Record;
using Hurricane::DBo;
using Hurricane::RoutingPad;
class Elmore;
//---------------------------------------------------------
// Class : Seabreeze::Delay
class Delay {
public:
Delay ( Elmore*, RoutingPad* );
~Delay ();
inline Elmore* getElmore () const;
inline RoutingPad* getSink () const;
inline double getDelay () const;
inline void setDelay ( double );
inline void incDelay ( double );
std::string _getTypeName () const;
std::string _getString () const;
Record* _getRecord () const;
private:
Elmore* _elmore;
RoutingPad* _sink;
double _delay;
};
inline Elmore* Delay::getElmore () const { return _elmore; }
inline RoutingPad* Delay::getSink () const { return _sink; }
inline double Delay::getDelay () const { return _delay; }
inline void Delay::setDelay ( double delay ) { _delay = delay; }
inline void Delay::incDelay ( double delay ) { _delay += delay; }
} // Seabreeze namespace.
INSPECTOR_P_SUPPORT(Seabreeze::Delay);

View File

@ -1,149 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./seabreeze/Elmore.cpp" |
// +-----------------------------------------------------------------+
#include <string>
#include <vector>
#include <set>
#include "hurricane/Property.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Contact.h"
#include "hurricane/Segment.h"
#include "Configuration.h"
#include "Tree.h"
#include "Delay.h"
namespace Hurricane {
class Net;
class Instance;
}
namespace Seabreeze {
using Hurricane::Name;
using Hurricane::DBo;
using Hurricane::Net;
using Hurricane::Cell;
using Hurricane::RoutingPad;
using Hurricane::Contact;
using Hurricane::Instance;
using Hurricane::Segment;
using Hurricane::PrivateProperty;
class SeabreezeEngine;
class ElmoreProperty;
//----------------------------------------------------------
// Class : Seabreeze::Elmore
class Elmore {
friend class ElmoreProperty;
public:
Elmore ( Net* );
~Elmore ();
inline SeabreezeEngine* getSeabreeze () const;
const Configuration* getConfiguration () const;
inline Net* getNet () const;
inline RoutingPad* getDriver () const;
Delay* getDelay ( RoutingPad* ) const;
inline const std::vector<Delay*>&
getDelays () const;
void buildTree ();
void buildFromNode ( Node* source, Segment* );
Contact* buildBranch ( double* R, double* C, Contact* contact );
void setRC ( double* R, double* C, Contact* , Segment* );
inline Tree* getTree ();
void setup ();
Delay* delayElmore ( RoutingPad* );
void toTree ( std::ostream& ) const;
inline void setSeabreeze ( SeabreezeEngine* );
Record* _getRecord () const;
std::string _getString () const;
std::string _getTypeName () const;
private:
private:
SeabreezeEngine* _seabreeze;
Net* _net;
RoutingPad* _driver;
Tree* _tree;
std::vector<Delay*> _delays;
};
inline SeabreezeEngine* Elmore::getSeabreeze () const { return _seabreeze; }
inline Net* Elmore::getNet () const { return _net; }
inline RoutingPad* Elmore::getDriver () const { return _driver; }
inline Tree* Elmore::getTree () { return _tree; }
inline void Elmore::setSeabreeze ( SeabreezeEngine* seabreeze ) { _seabreeze = seabreeze; }
inline const std::vector<Delay*>& Elmore::getDelays () const { return _delays; }
//---------------------------------------------------------
// Class : Seabreeze::ElmoreProperty
class ElmoreProperty : public Hurricane::PrivateProperty {
friend class ElmoreExtension;
private:
static Name _name;
public:
static ElmoreProperty* create ( Net* net );
static Name staticGetName ();
Name getName () const;
inline Elmore* getElmore ();
virtual string _getTypeName () const;
virtual Record* _getRecord () const;
virtual std::string _getString () const;
protected:
Elmore _elmore;
protected:
ElmoreProperty ( Net* );
};
inline Elmore* ElmoreProperty::getElmore ()
{ return &_elmore; }
//---------------------------------------------------------
// Class : Seabreeze::ElmoreExtension
class ElmoreExtension {
public:
static Elmore* create ( Net* );
static Elmore* get ( Net* );
static inline Tree* getTree ( Net* );
static inline void toTree ( Net*, std::ostream& );
static void destroy ( Net* );
};
inline Tree* ElmoreExtension::getTree ( Net* net )
{
Elmore* elmore = get( net );
return (elmore) ? elmore->getTree() : nullptr;
}
inline void ElmoreExtension::toTree ( Net* net, std::ostream& os )
{
Elmore* elmore = get( net );
if (elmore) elmore->toTree( os );
}
} // Seabreeze Namespace
INSPECTOR_P_SUPPORT(Seabreeze::Elmore);
INSPECTOR_P_SUPPORT(Seabreeze::ElmoreProperty);

View File

@ -1,83 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./seabreeze/Node.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <vector>
#include "hurricane/Contact.h"
namespace Seabreeze {
using Hurricane::Record;
using Hurricane::Contact;
//----------------------------------------------------------
// Class : Seabreeze::Node.
class Node {
public:
Node ();
Node ( Node* parent, Contact* );
~Node ();
inline double R () const;
inline double Rt () const;
inline double C () const;
inline int label () const;
inline int ap () const;
inline Contact* contact () const;
inline Node* parent () const;
inline const std::vector<Node*>& childs () const;
inline void addChild ( Node* );
inline void setLabel ( int );
inline void setAp ( int );
inline void setRt ( double );
inline void setR ( double );
inline void setC ( double );
Record* _getRecord () const;
std::string _getString () const;
std::string _getTypeName () const;
private :
double _R;
double _Rt;
double _C;
Node* _parent;
std::vector<Node*> _childs;
Contact* _contact;
int _label;
int _ap;
};
inline double Node::R () const { return _R; }
inline double Node::Rt () const { return _Rt; }
inline double Node::C () const { return _C; }
inline int Node::label () const { return _label; }
inline int Node::ap () const { return _ap; }
inline Contact* Node::contact () const { return _contact; }
inline Node* Node::parent () const { return _parent; }
inline const std::vector<Node*>& Node::childs () const { return _childs; }
inline void Node::addChild ( Node* child ) { _childs.push_back( child ); }
inline void Node::setLabel ( int label ) { _label = label; }
inline void Node::setAp ( int ap ) { _ap = ap; }
inline void Node::setRt ( double rt ) { _Rt = rt; }
inline void Node::setR ( double r ) { _R = r; }
inline void Node::setC ( double c ) { _C = c; }
} // Seabreeze namespace;
INSPECTOR_P_SUPPORT(Seabreeze::Node);

View File

@ -1,42 +0,0 @@
#ifndef PY_SEABREEZE_ENGINE_H
#define PY_SEABREEZE_ENGINE_H
#include "hurricane/isobar/PyHurricane.h"
#include "crlcore/PyToolEngine.h"
#include "seabreeze/SeabreezeEngine.h"
namespace Seabreeze {
extern "C" {
// -------------------------------------------------------------------
// Python Object : "PySeabreezeEngine".
typedef struct {
CRL::PyToolEngine _baseObject;
} PySeabreezeEngine;
// -------------------------------------------------------------------
// Functions & Types exported to "PySeabreeze.ccp".
extern PyTypeObject PyTypeSeabreezeEngine;
extern PyMethodDef PySeabreezeEngine_Methods[];
extern PyObject* PySeabreezeEngine_Link ( Seabreeze::SeabreezeEngine* );
extern void PySeabreezeEngine_LinkPyType ();
extern void PySeabreezeEngine_postModuleInit ();
#define IsPySeabreezeEngine(v) ( (v)->ob_type == &PyTypeSeabreezeEngine )
#define PYSEABREEZEENGINE(v) ( (PySeabreezeEngine*)(v) )
#define PYSEABREEZEENGINE_O(v) ( PYSEABREEZEENGINE(v)->_baseObject._object )
} // extern "C".
} // Tutorial namespace.
#endif // PY_SEABREEZE_ENGINE_H

View File

@ -1,94 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./seabreeze/SeabreezeEngine.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <string>
#include <iostream>
#include "hurricane/Name.h"
#include "hurricane/viewer/CellViewer.h"
#include "hurricane/RoutingPad.h"
namespace Hurricane {
class Net;
class Cell;
}
#include "crlcore/ToolEngine.h"
#include "seabreeze/Configuration.h"
namespace Seabreeze {
using Hurricane::Record;
using Hurricane::Name;
using Hurricane::Net;
using Hurricane::Cell;
using Hurricane::CellViewer;
using Hurricane::RoutingPad;
using CRL::ToolEngine;
//----------------------------------------------------------
// Class : "Seabreeze::SeabreezeEngine"
class SeabreezeEngine : public ToolEngine {
public :
typedef ToolEngine Super;
public :
static const Name& staticGetName ();
static SeabreezeEngine* create ( Cell* );
static SeabreezeEngine* get ( const Cell* );
public :
inline CellViewer* getViewer () const;
inline ToolEngine* base ();
virtual const Name& getName () const;
inline const Configuration* getConfiguration () const;
inline double getRct () const;
inline double getRsm () const;
inline double getCsm () const;
inline void setViewer ( CellViewer* );
virtual Record* _getRecord () const;
virtual std::string _getString () const;
virtual std::string _getTypeName () const;
virtual void buildElmore ( Net* net );
protected :
SeabreezeEngine ( Cell* );
virtual ~SeabreezeEngine ();
virtual void _postCreate ();
virtual void _preDestroy ();
private :
SeabreezeEngine ( const SeabreezeEngine& ) = delete;
SeabreezeEngine& operator= ( const SeabreezeEngine& ) = delete;
private :
// Attributes.
static Name _toolName;
protected :
Configuration* _configuration;
CellViewer* _viewer;
};
// Inline Functions.
inline ToolEngine* SeabreezeEngine::base () { return static_cast<ToolEngine*>(this); }
inline const Configuration* SeabreezeEngine::getConfiguration () const { return _configuration; }
inline double SeabreezeEngine::getRct () const { return getConfiguration()->getRct(); }
inline double SeabreezeEngine::getRsm () const { return getConfiguration()->getRsm(); }
inline double SeabreezeEngine::getCsm () const { return getConfiguration()->getCsm(); }
inline CellViewer* SeabreezeEngine::getViewer () const { return _viewer; }
inline void SeabreezeEngine::setViewer ( CellViewer* viewer ) { _viewer = viewer; }
} // Seabreeze namespace.
INSPECTOR_P_SUPPORT(Seabreeze::SeabreezeEngine);

View File

@ -1,77 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) SU 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | S e a b r e e z e - Timing Analysis |
// | |
// | Author : Vu Hoang Anh PHAM |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./seabreeze/Tree.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <set>
#include <vector>
#include <iostream>
#include "hurricane/RoutingPad.h"
namespace Seabreeze {
using Hurricane::Record;
using Hurricane::DBo;
using Hurricane::Contact;
using Hurricane::RoutingPad;
class Node;
class Delay;
class Elmore;
//---------------------------------------------------------
// Class : Seabreeze::Tree.
class Tree {
public:
typedef std::set<Contact*,DBo::CompareById> ContactSet;
public:
Tree ( Elmore* );
~Tree ();
inline bool isReached ( Contact* ) const;
inline Elmore* getElmore () const;
inline size_t getN ();
Node* getNode ( Contact* );
inline const std::vector<Node*>& getNodeList () const;
inline void setReached ( Contact* );
void addNode ( Node* );
void markNodeAfter ( Node* );
void getBranch ( Contact* );
Delay* computeElmoreDelay ( RoutingPad* );
void printNode ( std::ostream& , Node* , size_t depth );
void print ( std::ostream& );
Record* _getRecord () const;
std::string _getString () const;
std::string _getTypeName () const;
private:
Elmore* _elmore;
std::vector<Node*> _nodes;
ContactSet _reacheds;
};
inline Elmore* Tree::getElmore () const { return _elmore; }
inline size_t Tree::getN () { return _nodes.size(); }
inline const std::vector<Node*>& Tree::getNodeList () const { return _nodes; }
inline void Tree::setReached ( Contact* contact ) { _reacheds.insert( contact ); }
inline bool Tree::isReached ( Contact* contact ) const { return _reacheds.count( contact ); }
} // Seabreeze namespace.
INSPECTOR_P_SUPPORT(Seabreeze::Tree);

View File

@ -1,143 +0,0 @@
#include <iostream>
#include <cassert>
#include <fstream>
#include <string>
#include <sstream>
#include <stdlib.h>
#include <map>
#include <vector>
#include "Seabreeze/Node.h"
#include "Seabreeze/Tree.h"
using namespace std;
void build_tree(std::ifstream &file, Tree &t){
if(file.is_open()){
string line;
getline(file, line);
char RoC;
int lb1, lb2, vl; // possible labels of current node (can be parrent - current or current - child), value of R(or C)
vector<string> infos; // memoriser of infos taken from line
// Read file, line by line, get infomations
while(getline(file, line)){
stringstream tmp(line);
string word;
while(tmp >> word){
infos.push_back(word);
}
// Format is :
// infos[0] = RoC
// infos[1] = lb1 = label of current node
// infos[2] = lb2 = label of child node
// infos[3] = vl = value of RoC
char RoC = infos[0].at(0);
// infos[i>0] has type of string, so we need to turn it into integer using strtol
lb1 = strtol(infos[1].c_str(), NULL, 10);
lb2 = strtol(infos[2].c_str(), NULL, 10);
vl = strtol(infos[3].c_str(), NULL, 10);
infos.clear();
if(lb1 < 0 || lb2 == 0 || lb2 < -1){
// No node can have the root as a child
// A parent node cannot have label < 0 (<0 means -1, which is the ground)
cout << "Please check your configuration !" << endl;
cout << RoC << "\t" << lb1 << "\t" << lb2 << "\t" << vl << endl;
return;
}
else if(lb1 >= 0 && lb2 == -1){
// In this case, the branch is connected to "the ground"
// lb1 is the label of current node
// Check if current node is already created
if(RoC == 'R'){
cout << "Please check your configuration !" << endl;
cout << RoC << "\t" << lb1 << "\t" << lb2 << "\t" << vl << endl;
return;
}
//----------------------------------------------------------------------------------
// cout << "Node label : " << lb1 << " " << lb2 << " " << RoC << " " << vl << endl;
//----------------------------------------------------------------------------------
if(t.get_node(lb1)->label == -1)
t.get_node(lb1)->label = lb1;
if(RoC == 'C')
t.get_node(lb1)->C = vl;
//----------------------------------------------------------------------------------
// cout << "Node " << t.get_node(lb1).label << " -> " << lb2 << " C = " << t.get_node(lb1).C << endl << endl;
//----------------------------------------------------------------------------------
}
else if(lb1 >= 0 && lb2 > 0){
// lb1 is the label of parent node
// lb2 is the label of current node
//----------------------------------------------------------------------------------
// cout << "Node label : " << lb1 << " " << lb2 << " " << RoC << " " << vl << endl;
// cout << "Exist ? " << " n1 : " << t.get_node(lb1).label+1 << " n2 : " << t.get_node(lb2).label+1 << endl;
//----------------------------------------------------------------------------------
if(t.get_node(lb1)->label == -1)
t.get_node(lb1)->label = lb1;
if(t.get_node(lb2)->label == -1)
t.get_node(lb2)->label = lb2;
// Get the nodes
if(RoC == 'R')
t.get_node(lb2)->R = vl;
else if(RoC == 'C')
t.get_node(lb2)->C = vl;
//-----------------------------------------------------------------------------------
// cout << "Node : " << t.get_node(lb1).label << " -> " << t.get_node(lb2).label << " R = " << t.get_node(lb2).R << " C = " << t.get_node(lb2).C << endl;
//-----------------------------------------------------------------------------------
((t.get_node(lb1))->Ne).push_back(t.get_node(lb2));
((t.get_node(lb2))->Np) = t.get_node(lb1);
//-----------------------------------------------------------------------------------
// cout << "Check : " << t.get_node(lb2).Np->label << " -> " << t.get_node(lb2).label << " R = " << t.get_node(lb2).R << " C = " << t.get_node(lb2).C << endl;
//-----------------------------------------------------------------------------------
}
}
//-----------------------------------------------------------------------------------
// cout << "Double check !" << endl;
// for(int i = 1; i < t.get_N(); i++){
// cout << t.get_node(i).Np->label << " -> " << t.get_node(i).label << " R = " << t.get_node(i).R << " C = " << t.get_node(i).C << endl;
// }
//-----------------------------------------------------------------------------------
}
}
int main(int argc, char *argv[]){
if(argc < 4){
cout << "Usage : ./test <file name> <nodes number> <point index>" << endl
<< "Example : " << argv[0] << " data.txt 10 3" << endl;
return 0;
}
cout << "Testing with data from : " << argv[1] << endl;
ifstream f(argv[1]);
assert(f.is_open());
int num = strtol(argv[2], NULL, 10);
Tree t;
for(int i = 0; i < num; i++){
t.new_node();
}
build_tree(f, t);
filebuf fb;
fb.open ( "output.txt", ios::out );
ostream fout(&fb);
t.print(fout);
int idx = strtol(argv[3], NULL, 10);
int time = t.Delay_Elmore(idx);
cout << "Elmore delay time : " << time << endl;
fb.close();
return 0;
}

View File

@ -1,5 +0,0 @@
R1 0 1 10
C1 1 -1 20
R2 1 2 30
C2 2 -1 10

View File

@ -1,15 +0,0 @@
R1 0 1 10
C1 1 -1 15
R2 1 2 20
C2 2 -1 25
R3 1 3 30
C3 3 -1 35
R4 3 4 40
C4 4 -1 45
R5 3 5 50
C5 5 -1 55
R6 3 6 60
C6 6 -1 65
R7 5 7 70
C7 7 -1 75

View File

@ -1 +0,0 @@
node : not only left and right children, can have multiple children

View File

@ -1,38 +0,0 @@
# -*- explicit-buffer-name: "CMakeLists.txt<anabatic>" -*-
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
project(ANABATIC)
set(ignoreVariables "${BUILD_DOC} ${CMAKE_INSTALL_DIR}")
option(BUILD_DOC "Build the documentation (doxygen)" OFF)
option(CHECK_DATABASE "Run database in full check mode (very slow)" OFF)
option(USE_LIBBFD "Link with BFD libraries to print stack traces" OFF)
cmake_minimum_required(VERSION 3.16)
list(INSERT CMAKE_MODULE_PATH 0 "${DESTDIR}$ENV{CORIOLIS_TOP}/share/cmake/Modules/")
find_package(Bootstrap REQUIRED)
setup_project_paths(CORIOLIS)
set_cmake_policies()
setup_boost()
setup_qt()
setup_python()
find_package(PythonSitePackages REQUIRED)
find_package(FLUTE REQUIRED)
find_package(HURRICANE REQUIRED)
find_package(CORIOLIS REQUIRED)
find_package(ETESIAN REQUIRED)
find_package(COLOQUINTE REQUIRED)
find_package(Doxygen)
add_subdirectory(src)
add_subdirectory(cmake_modules)
#add_subdirectory(doc)
if(CHECK_DATABASE)
add_definitions(-DCHECK_DATABASE)
message(STATUS "Checking database enabled (very slow).")
endif(CHECK_DATABASE)

View File

@ -1 +0,0 @@
install ( FILES FindANABATIC.cmake DESTINATION share/cmake/Modules )

View File

@ -1,37 +0,0 @@
# - Find the Katabatic includes and libraries.
# The following variables are set if Coriolis is found. If ANABATIC is not
# found, ANABATIC_FOUND is set to false.
# ANABATIC_FOUND - True when the Coriolis include directory is found.
# ANABATIC_INCLUDE_DIR - the path to where the Coriolis include files are.
# ANABATIC_LIBRARIES - The path to where the Coriolis library files are.
SET(ANABATIC_INCLUDE_PATH_DESCRIPTION "directory containing the Katabatic include files. E.g /usr/local/include/coriolis2 or /asim/coriolis/include/coriolis2")
SET(ANABATIC_DIR_MESSAGE "Set the ANABATIC_INCLUDE_DIR cmake cache entry to the ${ANABATIC_INCLUDE_PATH_DESCRIPTION}")
# don't even bother under WIN32
IF(UNIX)
#
# Look for an installation.
#
FIND_PATH(ANABATIC_INCLUDE_PATH NAMES anabatic/AnabaticEngine.h PATHS
# Look in other places.
${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES include/coriolis2
# Help the user find it if we cannot.
DOC "The ${ANABATIC_INCLUDE_PATH_DESCRIPTION}"
)
FIND_LIBRARY(ANABATIC_LIBRARY_PATH
NAMES anabatic
PATHS ${CORIOLIS_DIR_SEARCH}
PATH_SUFFIXES lib64 lib
# Help the user find it if we cannot.
DOC "The ${ANABATIC_INCLUDE_PATH_DESCRIPTION}"
)
SET_LIBRARIES_PATH(ANABATIC ANABATIC)
HURRICANE_CHECK_LIBRARIES(ANABATIC)
ENDIF(UNIX)

View File

@ -1,346 +0,0 @@
// -*- C++ -*-
namespace Anabatic {
/*! \defgroup LoadGlobalRouting Global Routing Loading
* \brief Translation rules to build detailed routing from global
*
* This module documents how the global routing built by \c Knik is
* loaded into the \c Anabatic data-base. It is intented for developpers
* only.
*/
//! \addtogroup LoadGlobalRouting
//! \{
//! \enum LocalFunctionFlag
//! A set of flags for all functions of the LoadGlobalRouting module.
//! They can be combined to form the \e flags argument of functions.
//! the functions will ignore flags that are not intended to them.
//!
//! For \c HSmall, \c VSmall & \c Punctual see checkRoutingPadSize().
//! \var LocalFunctionFlag::NoFlags
//! A simple alias over zero to explicitly tell that no flag at all is
//! passed to the function.
//! \var LocalFunctionFlag::HAccess
//! The constructed topology will be accessed through an horizontal
//! segment. The absence of this flag tell that the access will be done
//! trough a vertical.
//! \var LocalFunctionFlag::VSmall
//! The RoutingPad vertically covers a very small number of access points,
//! so it is likely overconstrained for direct horizontal connexion.
//! \var LocalFunctionFlag::HSmall
//! The RoutingPad horizontally covers a very small number of access points,
//! so it is likely overconstrained for direct vertical connexion.
//! \var LocalFunctionFlag::Punctual
//! The RoutingPad covers only an access point in either direction.
//! \var LocalFunctionFlag::DoSourceContact
//! When creating Anabatic::AutoContactTerminal on non-punctual RoutingPad, this flag
//! request the creation of a contact <em>on the source point</em>.
//! \var LocalFunctionFlag::DoTargetContact
//! When creating Anabatic::AutoContactTerminal on non-punctual RoutingPad, this flag
//! request the creation of a contact <em>on the target point</em>.
//! \function uint64_t checkRoutingPadSize ( Component* rp );
//!
//! Look at the geometrical size of the Component and assess if
//! it's span is too narrow either horizontally or vertically.
//! Return a combination of flags indicating it's state:
//! - HSmall : less than 3 pitches in horizontal direction.
//! - VSmall : less than 3 pitches in vertical direction.
//! - Punctual : one pitch in either directions.
//!
//! The component can be a RoutingPad, a Vertical or an Horizontal.
//!
//! \image html checkRoutingPadSize.png "checkRoutingPadSize()"
/*! \class NetBuilder
*
* \brief Build the wiring for a Net inside a GCell (\b internal).
*
* As this class is called to initially construct the Anabatic wiring,
* it must build a \b connex wiring. That is without gaps in layer depth,
* because the topology restauration mechanism (AutoContact::updateTopology())
* of the AutoContact cannot work until all AutoSegments are revalidated at
* least once. The topology restauration work by creating doglegs which in turn,
* call the canonization, which needs all the caches to be up to date.
*/
//! \function void NetBuilder::doRp_AutoContacts ( GCell* gcell, Component* rp, AutoContact*& source, AutoContact*& target, uint64_t flags );
//! \param gcell The GCell into which create the AutoContact.
//! \param rp The Component we want to access.
//! \param source The AutoContact created on the \c source (\e returned).
//! \param target The AutoContact created on the \c target (\e returned).
//! \param flags Managed by this function:
//! - LocalFunctionFlag::DoSourceContact
//! - LocalFunctionFlag::DoTargetContact
//!
//! Create the AutoContact directly anchored on the Component (terminal).
//! Three cases are manageds:
//! -# <b>Ordinary (non-punctual) \c METAL1 terminal</b>: an AutoContactTerminal
//! is anchored on the RoutingPad.
//! -# <b>Punctual \c METAL1 terminal</b>, the access must never be blocked
//! by other routing. To ensure it, we create a fixed AutoSegment (anchored
//! on two AutoContactTerminal) to cover it. The \e normal AutoContactTerminal
//! is also created.
//! -# <b>non \c METAL1 terminal</b>, as for the punctual \c METAL1, a
//! fixed protection is added over the RoutingPad. If we access
//! horizontally a vertical RoutingPad or vertically an horizontal
//! one, an extra AutoContactTerminal is added (to allow is displacement
//! along the RoutingPad).
//!
//! To avoid creating a fixed protection over a RoutingPad multiple times,
//! the RoutingPad and it's associated protection is stored in a static
//! \c map : \c __routingPadAutoSegments.
//!
//! Conversely, because an AutoContactTerminal can only be connected to one
//! segment, each time this function is called a new terminal will be created
//! (or maybe two in case of non-punctual terminals). If only one AutoContact
//! is requested, it is created centered on the RoutingPad. The initial
//! position of AutoContact <em>do not prevent them to move afterwards</em>,
//! even those created on source/target on a non-punctual RoutingPad.
//!
//! \remark For clarity we describe the layer management of this function in term
//! of \c METAL, but it is the RoutingGauge depth which is actually used.
//!
//! \image html doRp_AutoContacts.png "doRp_AutoContacts()"
//! \function AutoContact* NetBuilder::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags );
//! \param gcell The GCell into which create the AutoContact.
//! \param rp The Component onto which anchor the access contact.
//! \param flags Relevant flags are:
//! - HAccess, the terminal is to be accessed through an horizontal
//! segment.
//! - VSmall, force the terminal to be considered as small in the
//! vertical direction.
//!
//! If \c HAccess is set, the Component is to be accessed trough an horizontal
//! segment. If unset, the access is done vertically.
//!
//! Create an AutoContact to access a Component (terminal). If the Component
//! is not to be accessed through an horizontal segment, and do not cover a
//! large span in the horizontal direction (flag \c VSmall), a local horizontal
//! AutoSegment is added to slacken the vertical constraints.
//!
//! \image html doRp_Access.png "doRp_Access()"
//! \function AutoContact* NetBuilder::doRp_AccessPad ( RoutingPad* rp, uint64_t flags );
//! \param rp The Component onto which anchor the access contact.
//! \param flags Relevant flags are:
//! - HAccess, the terminal is to be accessed through an horizontal
//! segment.
//! - VSmall, force the terminal to be considered as small in the
//! vertical direction.
//! \return A Anabatic::AutoContactTerminal .
//!
//! The Component \c rp is a RoutingPad which belongs to a pad cell. This case
//! occurs when we are routing a complete chip. This method build, from the
//! \c rp a stack of articulated punctual segments and contacts to reach the
//! default H/V routing layers (usually \c METAL2 & \c METAL3). This may be
//! needed when the pad terminal is in \c METAL5, for instance.
//!
//! The returned AutoContactTerminal is anchored on the last punctual segment
//! build.
//!
//! The GCell into which the AutoContactTerminal is created may be under the
//! pads area. However, it will be right on the border of the GCell.
//! The global router vertexes of GCell under the pad area are marked as
//! blocked so will never be used for routing.
//!
//! \remark The segments and contacts added to ensure the layer connexity are not
//! put into the Anabatic database. They are plain Hurricane objects, invisibles
//! from it.
//! \function void NetBuilder::doRp_StairCaseH ( GCell* gcell, Component* rp1, Component* rp2 );
//!
//! Build the wiring to connect to horizontal Component. Two cases:
//! - The Component are aligneds, then only a straight wire is created.
//! - They are \e not aligned, then a complete dogleg is created.
//!
//! \image html doRp_StairCaseH.png "doRp_StairCaseH()"
//! \function void NetBuilder::doRp_StairCaseV ( GCell* gcell, Component* rp1, Component* rp2 );
//!
//! Build the wiring to connect to vertical Components. Two cases:
//! - The Components are aligneds, then only a straight wire is created.
//! - They are \e not aligned, then a complete dogleg is created.
//!
//! \image html doRp_StairCaseV.png "doRp_StairCaseV()"
//! \function void NetBuilder::_do_xG_1Pad ();
//!
//! Construct the topology, when there is only global wires and one local
//! terminal, but coming from a Pad. As thoses connectors will always be
//! on one border of the GCell they can be considered as a kind of global.
//!
//! So this method mostly calls NetBuilder::doRp_AccessPad() to create
//! the AutoContactTerminal, then calls NetBuilder::_do_xG(), except
//! for straight lines which are managed directly.
//! \function void NetBuilder::_do_xG ();
//!
//! Construct the topology, when there is only global wires (no local terminals).
//!
//! Some topology are not handled because they must not be managed by this
//! function:
//! <ul>
//! <li>One global: nonsensical because there also must be a terminal.
//! <li>Two aligned globals: in that case we do a straight wire whithout
//! any AutoContact (handled by the source/target of the wire).
//! </ul>
//!
//! \image html _do_xG.png "_do_xG()"
//! \function void NetBuilder::_do_1G_1M1 ();
//!
//! Construct a topology where there is \e one global and one RoutingPad
//! in \c METAL1. The \c METAL1 is assumed to be vertical.
//!
//! \remark When accessing the RoutingPad through an horizontal global segment
//! and the vertical extension of the segment is small, the global is
//! still directly attached to the terminal, inducing a high constraint
//! on it. We left to job of slackening it to the router.
//!
//! \image html _do_1G_1M1.png "_do_1G_1M1()"
//! \function void NetBuilder::_do_1G_xM1 ();
//!
//! Construct a topology where there is \e one global and any number of
//! RoutingPad in \c METAL1. The \c METAL1 is assumed to be vertical.
//!
//! The RoutingPads are linked together two by two. If the horizontal
//! segments are not aligned by the router, part of the routage will be
//! done through the RoutingPad itself. The global incoming segment will
//! connected to the leftmost, rightmost or centermost RoutingPad according
//! from wich side it comes from.
//!
//! \image html _do_1G_xM1.png "_do_1G_xM1()"
//! \function void NetBuilder::_do_xG_1M1_1M2 ();
//!
//! Construct a topology where there is at least one global (and up to 4),
//! one \c METAL1 RoutingPad (assumed V) and one \c METAL2 RoutingPad (assumed H).
//!
//! In this topology, we want to try to reuse the \c METAL2 RoutingPad as a
//! feedtrough in the horizontal routage. Thus:
//! - The \c METAL1 and \c METAL2 RoutingPad are connected through a separate wiring.
//! - The south & west global wiring is attached to the leftmost contact of
//! the \c METAL2.
//! - The north & east global wiring is attached to the rightmost contact of
//! the \c METAL2.
//!
//! South/west and north/south can be build independantly. Depending on the number
//! of globals, they can consist of:
//! - Nothing (no south nor west).
//! - An AutoContact (west present).
//! - An horizontal plus a turn (south present).
//! - An horizontal plus a HTee (south & west present).
//!
//! \remark Not all configurations are represented below.
//!
//! \image html _do_xG_1M1_1M2.png "_do_xG_1M1_1M2()"
//! \function void NetBuilder::_do_xG_xM1_xM3 ();
//!
//! Construct a topology where there is at least one global (and up to 4),
//! at least one \c METAL1 RoutingPad (assumed V) and at least one \c METAL3
//! RoutingPad (assumed V).
//!
//! In this topology, we want to try to reuse the \c METAL3 RoutingPad as a
//! feedtrough in the vertical routage. Thus:
//! - The \c METAL1 and \c METAL3 RoutingPad are connected through a separate
//! wiring made of separate horizontals.
//! - The south-west global wiring is attached to the leftmost RoutingPad
//! if there isn't south or to the first \c METAL3 otherwise.
//! - The north-east global wiring is attached to the rightmost RoutingPad
//! if there isn't north or to the first \c METAL3 otherwise.
//!
//! South/west and north/south can be build independantly. Depending on the number
//! of globals, they can consist of:
//! - Nothing (no south nor west).
//! - An AutoContact on the leftmost RoutingPad (west present).
//! - An AutoContact on the first \c METAL3 (only south present).
//! - An AutoContact plus a vertical plus a VTee (south & west present).
//!
//! \image html _do_xG_xM1_xM3.png "_do_xG_xM1_xM3()"
//! \function void NetBuilder::_do_xG_xM2 ();
//!
//! Construct a topology where there is at least one global (and up to 4),
//! and any number of \c METAL2 RoutingPads (assumeds H).
//!
//! In this topology, we want to try to reuse the \c METAL2 RoutingPad as a
//! feedtrough in the horizontal routage. Thus:
//! - The RoutingPad are connecteds trough a separate staircase (or
//! straight wire if aligneds).
//! - The south-west global wiring is attached to the leftmost RoutingPad
//! if there isn't south or to the biggest horizontal RoutingPad otherwise.
//! - The north-east global wiring is attached to the rightmost RoutingPad
//! if there isn't south or to the biggest horizontal RoutingPad otherwise.
//!
//! \image html _do_xG_xM2.png "_do_xG_xM2()"
//! \function void NetBuilder::_do_1G_1M3 ();
//!
//! Construct a topology where there is one global and one \c METAL3 RoutingPad
//! (assumeds V).
//!
//! In this topology, we reuse the \c METAL3 RoutingPad as a feedtrough in the
//! vertical routage. Thus:
//! - If the global is either north or south, we directly connect to the
//! north end or south end of the RoutingPad. \red{The vertical global will}
//! \red{have no slack at all we assume that METAL3 terminals are only from}
//! \red{blocks and are aligneds vertically.}
//! - If the global is east or west \e and the RoutingPad is sufficiently
//! extended in the vertical direction, we connect an horizontal in the
//! normal way.
//! - If the global is not sufficiently extended, we add a turn to give some
//! slack to the global.
//!
//!
//! \image html _do_1G_1M3.png "_do_1G_1M3()"
//! \function void NetBuilder::_do_xG_xM3 ();
//!
//! Construct a topology where there at least one global and two \c METAL3 RoutingPad
//! (assumed V).
//!
//! In this topology, we reuse the \c METAL3 RoutingPad as a feedtrough in the
//! vertical routage. \red{We assume that the most likely relative position}
//! \red{of the RoutingPads is to be aligned vertically}.
//! Thus:
//! - All RoutingPads are linked two by two trough vertical staircases.
//! - The south-west global wiring is attached to the bottommost RoutingPad
//! (without vertical slack). If a misalignment is detected, then a
//! dogleg is added.
//! - The north-east global wiring is attached to the topmost RoutingPad
//! (without vertical slack).
//!
//! South/west and north/south can be build independantly. Depending on the number
//! of globals, they can consist of:
//! - Nothing (no south nor west).
//! - An sliding AutoContact on the bottommost RoutingPad (west present).
//! - An fixed AutoContact on the bottommost RoutingPad (only south present).
//! - An fixed AutoContact plus a vertical plus a VTee (south & west present).
//!
//! \image html _do_xG_xM3.png "_do_xG_xM3()"
//! \function void singleGCell ( AnabaticEngine* anbt, Net* net );
//!
//! All the RoutingPads of the net are concentrated under a single
//! GCell. This function assumes that all the terminals are in
//! \c METAL1 (vertical), and link them two by two by horizontal
//! wires.
//! \}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,703 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoContact.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <climits>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Layer.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Net.h"
#include "hurricane/Plug.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContact.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoContactHTee.h"
#include "anabatic/AutoContactVTee.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/AnabaticEngine.h"
#include "anabatic/Session.h"
namespace Anabatic {
using std::ostringstream;
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::DebugSession;
using Hurricane::ForEachIterator;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContact".
size_t AutoContact::_maxId = 0;
size_t AutoContact::_allocateds = 0;
const Name AutoContact::_goName = "Anabatic::AutoContact";
AutoContact::AutoContact ( GCell* gcell, Contact* contact )
: _id (contact->getId())
, _contact (contact)
, _gcell (gcell)
, _flags (CntInvalidatedCache|CntInCreationStage)
, _xMin (_gcell->getXMin())
, _xMax (_gcell->getConstraintXMax())
, _yMin (_gcell->getYMin())
, _yMax (_gcell->getConstraintYMax())
{
_allocateds++;
_gcell->addContact ( this );
}
void AutoContact::_preCreate ( GCell* gcell, Net* net, const Layer* layer )
{
if (not gcell) throw Error("AutoContact::_preCreate(): GCell* parameter must not be NULL.");
if (not net ) throw Error("AutoContact::_preCreate(): Net* parameter must not be NULL.");
if (not layer) throw Error("AutoContact::_preCreate(): const Layer* parameter must not be NULL.");
}
void AutoContact::_postCreate ()
{
restoreNativeConstraintBox();
cdebug_log(145,0) << "Native CBox: " << this
<< " <" << DbU::getValueString(getCBXMin())
<< " " << DbU::getValueString(getCBYMin())
<< " " << DbU::getValueString(getCBXMax())
<< " " << DbU::getValueString(getCBYMax()) << ">" << endl;
Session::link( this );
invalidate( Flags::Topology );
cdebug_log(145,0) << "AutoContact::_postCreate() - " << this << " in " << _gcell << endl;
}
void AutoContact::destroy ()
{
_preDestroy ();
delete this;
}
void AutoContact::_preDestroy ()
{
DebugSession::open( _contact->getNet(), 145, 150 );
cdebug_log(145,0) << "AutoContact::_preDestroy() - <AutoContact id:" << _id << ">" << endl;
#if 0
bool canDestroyBase = true;
if (not _contact->getSlaveComponents().isEmpty()) {
ostringstream message;
message << "Base contact still have slaves components, cancelled.\n"
<< " on: " << this;
for ( Component* component : _contact->getSlaveComponents() ) {
message << "\n | " << component;
}
cerr << Error( message.str() ) << endl;
canDestroyBase = false;
}
#endif
if (not Session::doDestroyTool()) {
_gcell->removeContact( this );
Session::unlink( this );
}
#if 0
if (Session::doDestroyBaseContact() and canDestroyBase)
_contact->destroy();
#endif
DebugSession::close();
}
AutoContact::~AutoContact ()
{ _allocateds--; }
size_t AutoContact::getAllocateds ()
{ return _allocateds; }
const Name& AutoContact::getStaticName ()
{ return _goName; }
bool AutoContact::canDestroy ( Flags flags ) const
{
if (not _contact->getSlaveComponents().isEmpty()) {
if (flags & Flags::WarnOnError) {
cerr << Error("Base contact still have slaves components, cancelled.\n"
" (%s)"
,_getString().c_str()) << endl;
}
return false;
}
return true;
}
const Name& AutoContact::getName () const { return _goName; }
AutoSegments AutoContact::getAutoSegments () { return new AutoSegments_CachedOnContact(this); }
AutoSegment* AutoContact::getPerpandicular ( const AutoSegment* ) const { return NULL; }
AutoHorizontal* AutoContact::getHorizontal1 () const { return NULL; }
AutoHorizontal* AutoContact::getHorizontal2 () const { return NULL; }
AutoVertical* AutoContact::getVertical1 () const { return NULL; }
AutoVertical* AutoContact::getVertical2 () const { return NULL; }
bool AutoContact::isOnPin () const { return false; }
void AutoContact::getDepthSpan ( size_t& minDepth, size_t& maxDepth ) const
{
cdebug_log(145,1) << "AutoContact::getDepthSpan() of " << this << endl;
minDepth = (size_t)-1;
maxDepth = 0;
Component* anchor = getAnchor ();
if (anchor) {
cdebug_log(145,0) << "* Anchor depth: "
<< Session::getRoutingGauge()->getLayerDepth(anchor->getLayer())<< endl;
minDepth = std::min( minDepth, Session::getRoutingGauge()->getLayerDepth(anchor->getLayer()) );
maxDepth = std::max( maxDepth, Session::getRoutingGauge()->getLayerDepth(anchor->getLayer()) );
}
for ( AutoSegment* segment : const_cast<AutoContact*>(this)->getAutoSegments() ) {
cdebug_log(145,0) << "* segment depth: "
<< Session::getRoutingGauge()->getLayerDepth(segment->getLayer())<< endl;
minDepth = std::min( minDepth, Session::getRoutingGauge()->getLayerDepth(segment->getLayer()) );
maxDepth = std::max( maxDepth, Session::getRoutingGauge()->getLayerDepth(segment->getLayer()) );
}
cdebug_tabw(145,-1);
}
void AutoContact::updateLayer ()
{
size_t minDepth = (size_t)-1;
size_t maxDepth = 0;
getDepthSpan( minDepth, maxDepth );
setLayerAndWidth( maxDepth-minDepth, minDepth );
// if (minDepth == maxDepth)
// setLayer( Session::getRoutingGauge()->getRoutingLayer(minDepth) );
// else
// setLayer( Session::getRoutingGauge()->getContactLayer(minDepth) );
}
void AutoContact::getLengths ( DbU::Unit* lengths, AutoSegment::DepthLengthSet& processeds )
{
DbU::Unit hSideLength = getGCell()->getSide( Flags::Horizontal ).getSize();
DbU::Unit vSideLength = getGCell()->getSide( Flags::Vertical ).getSize();
for ( AutoSegment* segment : getAutoSegments() ) {
bool isSourceHook = (segment->getAutoSource() == this);
if (processeds.find(segment) != processeds.end()) continue;
processeds.insert( segment );
size_t depth = Session::getRoutingGauge()->getLayerDepth(segment->getLayer());
DbU::Unit length;
if (segment->isLocal()) {
length = segment->getAnchoredLength();
lengths[depth] += length;
DbU::Unit sideLength = (segment->isHorizontal()) ? hSideLength : vSideLength;
if ( not segment->isUnbound() and (abs(length) > sideLength) )
cerr << Error( "AutoContact::getLength(): Suspicious length %s (> %s) of %s.\n"
" (on: %s)"
, DbU::getValueString(length).c_str()
, DbU::getValueString(sideLength).c_str()
, getString(segment).c_str()
, getString(this).c_str()) << endl;
} else {
if (segment->isHorizontal()) {
if (isSourceHook)
lengths[depth] += _gcell->getXMax() - segment->getSourceX();
else
lengths[depth] += segment->getTargetX() - _gcell->getXMin();
} else {
if (isSourceHook)
lengths[depth] += _gcell->getYMax() - segment->getSourceY();
else
lengths[depth] += segment->getTargetY() - _gcell->getYMin();
}
}
}
}
Box AutoContact::getNativeConstraintBox () const
{
if (isUserNativeConstraints()) return getConstraintBox();
if (isFixed()) return Box(_contact->getPosition());
return _gcell->getConstraintBox();
}
Interval AutoContact::getNativeUConstraints ( Flags direction ) const
{
Box nativeConstraints = getNativeConstraintBox();
Interval constraint;
if (direction & Flags::Horizontal) {
constraint = Interval( nativeConstraints.getXMin(), nativeConstraints.getXMax() );
} else {
constraint = Interval( nativeConstraints.getYMin(), nativeConstraints.getYMax() );
}
//if (direction & Flags::NoGCellShrink) constraint.inflate( 0, GCell::getTopRightShrink() );
return constraint;
}
Interval AutoContact::getUConstraints ( Flags direction ) const
{
Interval constraint;
if (direction & Flags::Horizontal) {
constraint = Interval( getCBXMin(), getCBXMax() );
} else {
constraint = Interval( getCBYMin(), getCBYMax() );
}
//if (direction & Flags::NoGCellShrink) constraint.inflate( 0, GCell::getTopRightShrink() );
return constraint;
}
void AutoContact::invalidate ( Flags flags )
{
if (flags & Flags::Topology ) setFlags( CntInvalidatedCache );
if (not isInvalidated()) {
cdebug_log(145,1) << "AutoContact::invalidate() - " << this << endl;
cdebug_log(145,0) << "flags:" << flags.asString(FlagsFunction) << endl;
setFlags( CntInvalidated );
Session::invalidate( this );
_invalidate( flags );
getGCell()->invalidate();
cdebug_tabw(145,-1);
}
}
void AutoContact::setGCell ( GCell* gcell )
{
invalidate();
if (_gcell) _gcell->removeContact( this );
_gcell = gcell;
if (_gcell) {
cdebug_log(145,0) << "AutoContact::setGCell() " << gcell << endl;
_gcell->addContact( this );
_contact->setPosition( _gcell->getCenter() );
_xMin = _gcell->getXMin();
_yMin = _gcell->getYMin();
_xMax = _gcell->getConstraintXMax();
_yMax = _gcell->getConstraintYMax();
if (cdebug.enabled()) {
cdebug_log(145,0) << "* deltas: [" << DbU::getValueString(_xMin)
<< " " << DbU::getValueString(_yMin)
<< " " << DbU::getValueString(_xMax)
<< " " << DbU::getValueString(_yMax)
<< "]" << endl;
}
} else {
cerr << Bug( "NULL GCell for %s.", _getString().c_str() ) << endl;
}
}
void AutoContact::updateSize ()
{
if (isInvalidatedWidth()) {
size_t minDepth = 0;
size_t maxDepth = 0;
getDepthSpan( minDepth, maxDepth );
if (getVertical1() and getVertical1()->isWide()) {
size_t vdepth = (Session::getLayerDepth(getVertical1()->getLayer()) == maxDepth) ? maxDepth : minDepth;
DbU::Unit width = getVertical1()->getWidth();
width += Session::getViaWidth(vdepth) - Session::getWireWidth(vdepth);
setWidth( width );
}
if (getHorizontal1() and getHorizontal1()->isWide()) {
size_t hdepth = (Session::getLayerDepth(getHorizontal1()->getLayer()) == maxDepth) ? maxDepth : minDepth;
DbU::Unit width = getHorizontal1()->getWidth();
width += Session::getViaWidth(hdepth) - Session::getWireWidth(hdepth);
setHeight( width );
}
unsetFlags ( CntInvalidatedWidth );
}
}
void AutoContact::_getTopology ( Contact* support, Component*& anchor, Horizontal**& horizontals, Vertical**& verticals, size_t size )
{
size_t hcount = 0;
size_t vcount = 0;
for ( size_t i=0 ; i<size ; ++i ) {
horizontals[i] = NULL;
verticals [i] = NULL;
}
anchor = support->getAnchor();
for ( Component* component : support->getSlaveComponents() ) {
Horizontal* h = dynamic_cast<Horizontal*>(component);
if (h != NULL) {
if (hcount < size) horizontals[hcount++] = h;
} else {
Vertical* v = dynamic_cast<Vertical*>(component);
if ( (v != NULL) and (vcount < size) ) verticals[vcount++] = v;
}
}
}
void AutoContact::showTopologyError ( const std::string& message, Flags flags )
{
Component* anchor = NULL;
Horizontal** horizontals = new Horizontal* [10];
Vertical** verticals = new Vertical* [10];
if (not (flags & Flags::CParanoid)) cparanoid.setStreamMask( mstream::PassThrough );
_getTopology ( base(), anchor, horizontals, verticals, 10 );
cparanoid << Error("In topology of %s",getString(this).c_str()) << endl;
if (anchor) cparanoid << " A: " << anchor << endl;
for ( size_t i=0 ; (i<10) and (horizontals[i] != NULL); ++i ) {
AutoSegment* autoSegment = Session::lookup ( horizontals[i] );
if (autoSegment != NULL)
cparanoid << " " << (autoSegment->isGlobal()?'G':'L') << ": " << autoSegment << endl;
else
cparanoid << " ?: " << horizontals[i] << endl;
}
for ( size_t i=0 ; (i<10) and (verticals[i] != NULL); ++i ) {
AutoSegment* autoSegment = Session::lookup ( verticals[i] );
if (autoSegment != NULL)
cparanoid << " " << (autoSegment->isGlobal()?'G':'L') << ": " << autoSegment << endl;
else
cparanoid << " ?: " << verticals[i] << endl;
}
cparanoid << " " << message << endl;
if (not (flags & Flags::CParanoid)) cparanoid.unsetStreamMask( mstream::PassThrough );
delete [] horizontals;
delete [] verticals;
}
void AutoContact::checkTopology ()
{
//cdebug_log(145,0) << "checkTopology() NOT RE-IMPLEMENTED YET " << this << endl;
}
void AutoContact::forceOnGrid ( Point )
{
cerr << Warning( "AutoContact::forcedOnGrid() not implemented for this derived class.\n"
" %s\n"
, getString(this).c_str()
) << endl;
}
bool AutoContact::isTee ( Flags direction ) const
{
return (isHTee() and (direction & Flags::Horizontal))
or (isVTee() and (direction & Flags::Vertical ));
}
bool AutoContact::canMoveUp ( const AutoSegment* moved ) const
{
cdebug_log(149,0) << "AutoContact::canMoveUp() " << this << endl;
size_t viaDepth = 100;
RoutingGauge* rg = Session::getRoutingGauge();
size_t movedDepth = rg->getLayerDepth(moved->getLayer());
Component* anchor = getAnchor();
if (anchor) {
viaDepth = rg->getLayerDepth( anchor->getLayer() );
cdebug_log(149,0) << "| Anchor depth: " << viaDepth << endl;
}
for ( AutoSegment* segment : const_cast<AutoContact*>(this)->getAutoSegments() ) {
if (segment == moved) continue;
size_t depth = rg->getLayerDepth(segment->getLayer());
if (viaDepth == 100) viaDepth = depth;
else
if (viaDepth != depth) return false;
cdebug_log(149,0) << "| Segment depth: " << depth << endl;
}
return (movedDepth+1 == viaDepth);
}
void AutoContact::setConstraintBox ( const Box& box )
{
cdebug_log(149,0) << "setConstraintBox() " << this << " " << getConstraintBox()
<< " from:" << box << endl;
setCBXMin ( box.getXMin() );
setCBXMax ( box.getXMax() );
setCBYMin ( box.getYMin() );
setCBYMax ( box.getYMax() );
cdebug_log(149,0) << "setConstraintBox() " << this << " " << getConstraintBox() << endl;
cdebug_log(149,0) << "* " << _gcell << endl;
}
bool AutoContact::restrictConstraintBox ( DbU::Unit constraintMin
, DbU::Unit constraintMax
, Flags flags
)
{
cdebug_log(149,0) << "restrictConstraintBox() - " << this << " " << getConstraintBox() << endl;
if (flags & Flags::Horizontal) {
if ( (constraintMin > getCBYMax()) or (constraintMax < getCBYMin()) ) {
if ( Session::isInDemoMode() or not (flags & Flags::WarnOnError) ) return false;
cerr << Error ( "Incompatible DY restriction on %s", _getString().c_str() ) << endl;
if ( constraintMin > getCBYMax() )
cerr << Error ( "(constraintMin > CBYMax : %s > %s)"
, DbU::getValueString(constraintMin).c_str()
, DbU::getValueString(getCBYMax()).c_str() )
<< endl;
if ( constraintMax < getCBYMin() )
cerr << Error ( "(constraintMax < CBYMin : %s < %s)"
, DbU::getValueString(constraintMax).c_str()
, DbU::getValueString(getCBYMin()).c_str() )
<< endl;
return false;
}
setCBYMin ( std::max(getCBYMin(),constraintMin) );
setCBYMax ( std::min(getCBYMax(),constraintMax) );
} else if (flags & Flags::Vertical) {
if ( (constraintMin > getCBXMax()) || (constraintMax < getCBXMin()) ) {
if ( Session::isInDemoMode() or not (flags & Flags::WarnOnError) ) return false;
cerr << Error ( "Incompatible DX restriction on %s", _getString().c_str() ) << endl;
if ( constraintMin > getCBXMax() )
cerr << Error ( "(constraintMin > CBXMax : %s > %s)"
, DbU::getValueString(constraintMin).c_str()
, DbU::getValueString(getCBXMax()).c_str() )
<< endl;
if ( constraintMax < getCBXMin() )
cerr << Error ( "(constraintMax < CBXMin : %s < %s)"
, DbU::getValueString(constraintMax).c_str()
, DbU::getValueString(getCBXMin()).c_str() )
<< endl;
return false;
}
setCBXMin ( std::max(getCBXMin(),constraintMin) );
setCBXMax ( std::min(getCBXMax(),constraintMax) );
}
cdebug_log(149,0) << "restrictConstraintBox() - " << this << " " << getConstraintBox() << endl;
return true;
}
void AutoContact::restoreNativeConstraintBox ()
{ setConstraintBox ( getNativeConstraintBox() ); }
Box& AutoContact::intersectConstraintBox ( Box& box ) const
{ return box = box.getIntersection ( getConstraintBox() ); }
void AutoContact::migrateConstraintBox ( AutoContact* other )
{
if (_gcell != other->_gcell) {
cerr << Error( "AutoContact::migrateConstraintBox(): AutoContacts do not belongs to the same GCell:\n"
" from: %s\n"
" to: %s"
, getString(other).c_str()
, getString(this ).c_str()
) << endl;
return;
}
setConstraintBox( other->getConstraintBox() );
other->restoreNativeConstraintBox();
}
Box AutoContact::getBoundingBox () const
{ return _gcell->getBoundingBox (); }
void AutoContact::translate ( const DbU::Unit& tx, const DbU::Unit& ty )
{
cerr << Warning("Calling AutoContact::translate() is likely a bug.") << endl;
_contact->translate ( tx, ty );
}
void AutoContact::setLayerAndWidth ( size_t delta, size_t depth )
{
cdebug_log(145,1) << "AutoContact::setLayerAndWidth() " << this << endl;
cdebug_log(145,0) << "delta:" << delta << " depth:" << depth << endl;
if (delta == 0) {
setLayer( Session::getRoutingLayer(depth) );
if (Session::getDirection(depth) & Flags::Horizontal) {
setSizes( Session::getPWireWidth(depth)
, Session::getWireWidth (depth) );
} else {
setSizes( Session::getWireWidth (depth)
, Session::getPWireWidth(depth) );
}
} else {
setLayer( Session::getContactLayer(depth) );
setSizes( Session::getViaWidth (depth)
, Session::getViaWidth (depth) );
}
cdebug_tabw(145,-1);
}
AutoContact* AutoContact::createFrom ( Contact* hurricaneContact )
{
AutoContact* autoContact = NULL;
Component* anchor;
size_t hSize = 0;
size_t vSize = 0;
Horizontal** horizontals = new Horizontal* [4];
Vertical** verticals = new Vertical* [4];
GCell* gcell = Session::getAnabatic()->getGCellUnder( hurricaneContact->getCenter() );
if (not gcell) {
throw Error("AutoContact::createFrom( %s ):\n"
" Contact is *not* under a GCell (outside routed area?)"
, getString(hurricaneContact).c_str()
);
}
_getTopology ( hurricaneContact, anchor, horizontals, verticals, 4 );
for ( size_t i=0 ; i<4 ; ++i ) {
hSize += (horizontals[i] != NULL) ? 1 : 0;
vSize += (verticals [i] != NULL) ? 1 : 0;
}
if (anchor) {
if (hSize+vSize == 1) {
autoContact = new AutoContactTerminal( gcell, hurricaneContact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
}
} else {
if ((hSize == 1) and (vSize == 1)) {
autoContact = new AutoContactTurn ( gcell, hurricaneContact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
} else if ((hSize == 2) and (vSize == 1)) {
autoContact = new AutoContactHTee ( gcell, hurricaneContact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
} else if ((hSize == 1) and (vSize == 2)) {
autoContact = new AutoContactVTee ( gcell, hurricaneContact );
}
}
if (not autoContact) {
throw Error("AutoContact::createFrom( %s ):\n"
" Contact do not have a manageable topology (a:%u, h:%u, v:%u)"
, getString(hurricaneContact).c_str()
, ((anchor) ? 1 : 0)
, hSize
, vSize
);
}
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
return autoContact;
}
string AutoContact::_getTypeName () const
{ return "AutoContact"; }
string AutoContact::_getString () const
{
string s = _contact->_getString();
size_t i = s.find(' ');
if (i != string::npos) {
s.erase ( i+1, 7 );
s.insert( i+1, _getTypeName() );
}
//s.insert( 1, "id: " );
//s.insert( 4, getString(_id) );
s.insert( s.size()-1, (isFixed ())?" F":" -" );
s.insert( s.size()-1, (isTerminal ())? "T": "-" );
s.insert( s.size()-1, (canDrag ())? "D": "-" );
s.insert( s.size()-1, (isHTee ())? "h": "-" );
s.insert( s.size()-1, (isVTee ())? "v": "-" );
s.insert( s.size()-1, (isInvalidated ())? "i": "-" );
s.insert( s.size()-1, (isInvalidatedCache())? "c": "-" );
//s.insert( s.size()-1, getString(getConstraintBox()));
return s;
}
Record* AutoContact::_getRecord () const
{
Record* record = _contact->_getRecord ();
record->add ( getSlot ( "_gcell" , _gcell ) );
record->add ( getSlot ( "_constraintBox", getConstraintBox() ) );
record->add ( getSlot ( "_flags" , _flags ) );
return record;
}
} // Anabatic namespace.

View File

@ -1,352 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoContactHTee.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <climits>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Layer.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Net.h"
#include "hurricane/Plug.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactHTee.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/Session.h"
namespace Anabatic {
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::DebugSession;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactHTee".
AutoContactHTee* AutoContactHTee::create ( GCell* gcell, Net* net, const Layer* layer )
{
_preCreate( gcell, net, layer );
DbU::Unit viaSide = Session::getViaWidth( layer );
Contact* contact = Contact::create ( net
, layer
, gcell->getCenter().getX()
, gcell->getCenter().getY()
, viaSide
, viaSide
);
AutoContactHTee* autoContact = new AutoContactHTee ( gcell, contact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
cdebug_log(145,0) << "create(net*) " << autoContact << endl;
return autoContact;
}
AutoContactHTee::AutoContactHTee ( GCell* gcell, Contact* contact )
: AutoContact (gcell,contact)
, _horizontal1(NULL)
, _horizontal2(NULL)
, _vertical1 (NULL)
{
setFlags( CntHTee );
}
AutoContactHTee::~AutoContactHTee ()
{ }
AutoSegment* AutoContactHTee::getOpposite ( const AutoSegment* from ) const
{
if (from == _horizontal1) return _horizontal2;
if (from == _horizontal2) return _horizontal1;
return NULL;
}
AutoSegment* AutoContactHTee::getPerpandicular ( const AutoSegment* from ) const
{
if ( (from == _horizontal1) or (from == _horizontal2) ) return _vertical1;
return NULL;
}
AutoSegment* AutoContactHTee::getSegment ( unsigned int index ) const
{
AutoSegment* segment = NULL;
switch ( index ) {
case 0: return _horizontal1;
case 1: return _horizontal2;
case 2: return _vertical1;
}
//if (not segment)
// cerr << Error( "In %s:\n No cached segment at index %d"
// , getString(this).c_str(), index ) << endl;
return segment;
}
AutoHorizontal* AutoContactHTee::getHorizontal1 () const { return _horizontal1; };
AutoHorizontal* AutoContactHTee::getHorizontal2 () const { return _horizontal2; };
AutoVertical* AutoContactHTee::getVertical1 () const { return _vertical1; };
void AutoContactHTee::_invalidate ( Flags flags )
{
flags |= Flags::Propagate;
if (_horizontal1 and _horizontal2) {
if (_horizontal1->isInvalidated() xor _horizontal2->isInvalidated())
flags.reset( Flags::Propagate );
}
cdebug_log(145,0) << "flags:" << flags.asString(FlagsFunction) << endl;
if (_horizontal1) _horizontal1->invalidate( flags );
if (_horizontal2) _horizontal2->invalidate( flags );
if (_vertical1 ) _vertical1 ->invalidate();
}
void AutoContactHTee::cacheDetach ( AutoSegment* segment )
{
cdebug_log(145,0) << _getTypeName() << "::cacheDetach() " << this << endl;
cdebug_log(145,0) << "| h1:" << _horizontal1 << endl;
cdebug_log(145,0) << "| h2:" << _horizontal2 << endl;
cdebug_log(145,0) << "| v1:" << _vertical1 << endl;
if (segment == _horizontal1) _horizontal1 = NULL;
else if (segment == _horizontal2) _horizontal2 = NULL;
else if (segment == _vertical1) _vertical1 = NULL;
else {
if (_horizontal1 or _horizontal2 or _vertical1)
cerr << Bug( "%s::cacheDetach() On %s,\n"
" Cannot detach %s\n"
" because it *not* attached to this contact."
, _getTypeName().c_str()
, getString(this).c_str()
, getString(segment).c_str()
) << endl;
return;
}
setFlags( CntInvalidatedCache );
}
void AutoContactHTee::cacheAttach ( AutoSegment* segment )
{
cdebug_log(145,1) << _getTypeName() << "::cacheAttach() " << this << endl;
cdebug_log(145,0) << "Attaching: " << segment << endl;
if (segment->getDirection() == Flags::Horizontal) {
if (not _horizontal1) _horizontal1 = static_cast<AutoHorizontal*>(segment);
else if (not _horizontal2) _horizontal2 = static_cast<AutoHorizontal*>(segment);
else {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" h1 & h2 cache have not been cleared first, cancelled."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
cdebug_tabw(145,-1);
return;
}
} else if (segment->getDirection() == Flags::Vertical) {
if (_vertical1) {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" v1 cache has not been cleared first, cancelled."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
cdebug_tabw(145,-1);
return;
}
_vertical1 = static_cast<AutoVertical*>(segment);
}
if (_horizontal1 and _horizontal2 and _vertical1)
unsetFlags( CntInvalidatedCache );
cdebug_log(145,0) << "| h1:" << _horizontal1 << endl;
cdebug_log(145,0) << "| h2:" << _horizontal2 << endl;
cdebug_log(145,0) << "| v1:" << _vertical1 << endl;
cdebug_tabw(145,-1);
}
void AutoContactHTee::updateCache ()
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl;
Component* anchor;
Horizontal** horizontals = new Horizontal* [3];
Vertical** verticals = new Vertical* [3];
_getTopology( base(), anchor, horizontals, verticals, 3 );
_horizontal1 = static_cast<AutoHorizontal*>( Session::lookup(horizontals[0]) );
_horizontal2 = static_cast<AutoHorizontal*>( Session::lookup(horizontals[1]) );
_vertical1 = static_cast<AutoVertical *>( Session::lookup(verticals [0]) );
string message;
if (horizontals[0] == NULL) message = "HTee has less than two horizontal segments.";
else if (horizontals[1] == NULL) message = "HTee has less than two horizontal segments.";
else if (horizontals[2] != NULL) message = "HTee has more than two horizontal segments.";
else if (verticals [0] == NULL) message = "HTee is missing mandatory vertical segment.";
else if (verticals [1] != NULL) message = "HTee has more than one vertical segment.";
else if (_horizontal1 == NULL) message = "AutoSegment lookup failed on first horizontal segment.";
else if (_horizontal2 == NULL) message = "AutoSegment lookup failed on second horizontal segment.";
else if (_vertical1 == NULL) message = "AutoSegment lookup failed on vertical segment.";
else if ( (not _horizontal1->isCreated() and not _horizontal2->isCreated())
and (_horizontal1->getY() != _horizontal2->getY()) ) {
message = "HTee has misaligned horizontal segments";
message += " h1:" + getString(_horizontal1->getY());
message += " h2:" + getString(_horizontal2->getY());
}
if (not message.empty()) {
showTopologyError( message );
setFlags( CntBadTopology );
}
unsetFlags( CntInvalidatedCache );
cdebug_log(145,0) << "h1:" << _horizontal1 << endl;
cdebug_log(145,0) << "h2:" << _horizontal2 << endl;
cdebug_log(145,0) << "v1:" << _vertical1 << endl;
delete [] horizontals;
delete [] verticals;
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactHTee::updateGeometry ()
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
base()->invalidate( false );
unsetFlags( CntInvalidated );
if (not hasBadTopology()) {
setX( getVertical1 ()->getX() );
setY( getHorizontal1()->getY() );
updateSize();
}
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactHTee::updateTopology ()
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (not hasBadTopology()) {
RoutingGauge* rg = Session::getRoutingGauge();
size_t depthH1 = rg->getLayerDepth( getHorizontal1()->getLayer() );
size_t depthH2 = rg->getLayerDepth( getHorizontal2()->getLayer() );
size_t depthV1 = rg->getLayerDepth( getVertical1 ()->getLayer() );
size_t minDepth = std::min( depthV1, std::min(depthH1,depthH2) );
size_t maxDepth = std::max( depthV1, std::max(depthH1,depthH2) );
size_t delta = maxDepth - minDepth;
cdebug_log(145,0) << "delta:" << delta << endl;
unsetFlags( CntWeakTerminal );
if (maxDepth - minDepth > 3) {
showTopologyError( "Sheared HTee, layer delta exceed 3." );
setFlags( CntBadTopology );
} else {
if (depthH1 == depthH2) {
// Dogleg on the vertical.
switch ( delta ) {
case 0:
case 1: setLayerAndWidth( delta, minDepth ); break;
default:
setLayerAndWidth( delta, depthH1 + ((depthH1==minDepth)?0:-1) );
_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
break;
}
} else {
// Dogleg on the horizontal with the greater gap (should be equal to +/-2).
int deltaH1 = (int)depthH1 - (int)depthV1;
int deltaH2 = (int)depthH2 - (int)depthV1;
if (std::abs(deltaH1) > std::abs(deltaH2)) {
setLayerAndWidth( 2, depthH2 + ((depthH2<depthV1)?0:-1) );
//_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
_horizontal1->makeDogleg(this);
cdebug_log(145,0) << "New h1:" << _horizontal1 << endl;
} else {
setLayerAndWidth( 2, depthH1 + ((depthH1<depthV1)?0:-1) );
//_horizontal2 = static_cast<AutoHorizontal*>( _horizontal2->makeDogleg(this) );
_horizontal2->makeDogleg(this);
cdebug_log(145,0) << "New h2:" << _horizontal2 << endl;
}
}
}
_horizontal1->invalidate( this );
_horizontal2->invalidate( this );
_vertical1 ->invalidate( this );
}
cdebug_tabw(145,-1);
DebugSession::close();
}
string AutoContactHTee::_getTypeName () const
{ return "ContactHTee"; }
} // Anabatic namespace.

View File

@ -1,589 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoContactTerminal.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <climits>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Layer.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Net.h"
#include "hurricane/Plug.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Pin.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/Session.h"
namespace Anabatic {
using std::ostringstream;
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::DebugSession;
using Hurricane::Transformation;
using Hurricane::Entity;
using Hurricane::Occurrence;
using Hurricane::Pin;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactTerminal".
AutoContactTerminal* AutoContactTerminal::create ( GCell* gcell
, Component* anchor
, const Layer* layer
, Point point
, DbU::Unit width
, DbU::Unit height
)
{
cdebug_log(145,1) << "AutoContactTerminal::create(... Point, ...) " << endl;
cdebug_log(145,0) << "@" << point << endl;
anchor->getBodyHook()->detach();
AutoContactTerminal* autoContact = AutoContactTerminal::create( gcell
, anchor
, layer
, point.getX(), point.getY()
, width, height
);
cdebug_tabw(145,-1);
return autoContact;
}
AutoContactTerminal* AutoContactTerminal::create ( GCell* gcell
, Component* anchor
, const Layer* layer
, const DbU::Unit x
, const DbU::Unit y
, const DbU::Unit width
, const DbU::Unit height
)
{
cdebug_log(145,0) << "AutoContactTerminal::create(... x, y, ...) " << endl;
cdebug_log(145,0) << "@ x:" << DbU::getValueString(x) << " y:" << DbU::getValueString(y) << endl;
_preCreate( gcell, anchor->getNet(), layer );
Point anchorPosition = anchor->getPosition();
Contact* contact = Contact::create( anchor
, layer
, x - anchorPosition.getX()
, y - anchorPosition.getY()
, width
, height
);
AutoContactTerminal* autoContact = new AutoContactTerminal( gcell, contact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
cdebug_log(145,0) << "create(Component*) " << autoContact << endl;
return autoContact;
}
AutoContactTerminal::AutoContactTerminal ( GCell* gcell, Contact* contact )
: AutoContact(gcell,contact)
, _segment (NULL)
{
setFlags( CntTerminal );
}
AutoContactTerminal::~AutoContactTerminal ()
{ }
bool AutoContactTerminal::isEndPoint () const
{
RoutingPad* rp = dynamic_cast<RoutingPad*>( getAnchor() );
return (rp->getBodyHook()->getSlaveHooks().getSize() == 1);
}
bool AutoContactTerminal::isOnPin () const
{
RoutingPad* rp = dynamic_cast<RoutingPad*>( getAnchor() );
return (dynamic_cast<Pin*>(rp->getOccurrence().getEntity()) != NULL);
}
AutoSegment* AutoContactTerminal::getOpposite ( const AutoSegment* ) const
{ return NULL; }
AutoSegment* AutoContactTerminal::getPerpandicular ( const AutoSegment* ) const
{ return NULL; }
AutoSegment* AutoContactTerminal::getSegment ( unsigned int index ) const
{
if (_segment) {
switch ( index ) {
case 0: return (_segment->isHorizontal()) ? _segment : NULL;
case 2: return (_segment->isVertical ()) ? _segment : NULL;
}
}
return NULL;
}
RoutingPad* AutoContactTerminal::getRoutingPad () const
{ return dynamic_cast<RoutingPad*>(getAnchor()); }
AutoSegments AutoContactTerminal::getRpConnecteds () const
{ return AutoSegments_OnRoutingPad(this); }
Box AutoContactTerminal::getNativeConstraintBox () const
{
cdebug_log(145,1) << "AutoContactTerminal::getNativeConstraintBox()" << endl;
if (isUserNativeConstraints()) {
cdebug_log(145,1) << " Native constraints sets by user:" << getConstraintBox() << endl;
cdebug_tabw(145,-1);
cdebug_tabw(145,-1);
return getConstraintBox();
}
Component* component = getAnchor();
if (component == NULL) {
cerr << Error( "%s is not anchored.", getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return _gcell->getBoundingBox();
}
RoutingLayerGauge* lg = Session::getLayerGauge( Session::getLayerDepth(component->getLayer()) );
DbU::Unit xborder = 0;
DbU::Unit yborder = 0;
const Layer* viaLayer = Session::getContactLayer( lg->getDepth() );
if (viaLayer) {
if (lg->isHorizontal() and (lg->getDepth() != 0)) {
xborder = Session::getViaWidth( lg->getDepth() )/2
+ viaLayer->getBottomEnclosure( Layer::EnclosureH );
} else {
yborder = Session::getViaWidth( lg->getDepth() )/2
+ viaLayer->getBottomEnclosure( Layer::EnclosureV );
xborder = Session::getViaWidth( lg->getDepth() )/2
+ viaLayer->getBottomEnclosure( Layer::EnclosureH );
if (Session::getRoutingGauge()->isSymbolic()) {
// SxLib bug: METAL1 terminal segments are 0.5 lambdas too shorts on
// their extremities. Should modificate all the standard cells layout...
// HARDCODED.
if (getString(Session::getRoutingGauge()->getName()).substr(0,6) == "msxlib")
yborder -= DbU::fromLambda( 1.0 );
else
yborder -= DbU::fromLambda( 0.5 );
}
}
}
DbU::Unit xMin;
DbU::Unit xMax;
DbU::Unit yMin;
DbU::Unit yMax;
Vertical* vertical;
Horizontal* horizontal;
RoutingPad* routingPad;
if ( (horizontal = dynamic_cast<Horizontal*>(component)) ) {
cdebug_log(145,0) << "Anchor: " << horizontal << "@" << horizontal->getSourcePosition() << endl;
xMin = horizontal->getSourcePosition().getX();
xMax = horizontal->getTargetPosition().getX();
yMin = yMax
= horizontal->getTargetPosition().getY();
} else if ( (vertical = dynamic_cast<Vertical*>(component)) ) {
cdebug_log(145,0) << "Anchor: " << vertical << "@" << vertical->getSourcePosition() << endl;
yMin = vertical->getSourcePosition().getY();
yMax = vertical->getTargetPosition().getY();
xMin = xMax
= vertical->getTargetPosition().getX();
} else if ( (routingPad = dynamic_cast<RoutingPad*>(component)) ) {
Occurrence occurrence = routingPad->getOccurrence();
Transformation transformation = occurrence.getPath().getTransformation();
Horizontal* horizontal = dynamic_cast<Horizontal*>( occurrence.getEntity() );
Vertical* vertical = dynamic_cast<Vertical* >( occurrence.getEntity() );
cdebug_log(145,0) << "Anchor: " << occurrence.getEntity() << endl;
cdebug_log(145,0) << "transf: " << transformation << endl;
if (horizontal or vertical) {
Box bb;
// Assume that transformation contains no rotations (for now).
if (horizontal) { bb = horizontal->getBoundingBox(); const_cast<AutoContactTerminal*>(this)->setFlags( CntOnHorizontal ); }
if (vertical) { bb = vertical ->getBoundingBox(); const_cast<AutoContactTerminal*>(this)->setFlags( CntOnVertical ); }
transformation.applyOn( bb );
cdebug_log(145,0) << "Shrink border x:" << DbU::getValueString(xborder)
<< " y:" << DbU::getValueString(yborder)
<< endl;
// HARDCODED.
if ( (Session::getRoutingGauge()->getName() == "sxlib")
and (bb.getWidth() == DbU::fromLambda(1.0)) ) {
bb.inflate( DbU::fromLambda(0.5), 0 );
}
bb.inflate( -xborder, -yborder );
xMin = bb.getXMin();
yMin = bb.getYMin();
xMax = bb.getXMax();
yMax = bb.getYMax();
} else {
xMin = xMax = component->getPosition().getX();
yMin = yMax = component->getPosition().getY();
}
#if FOR_SYMBOLIC_LAYERS
Entity* entity = routingPad->getOccurrence().getEntity();
Transformation transf = routingPad->getOccurrence().getPath().getTransformation();
cdebug_log(145,0) << "Anchor: " << routingPad << endl;
int rpOrient = 1;
switch ( transf.getOrientation() ) {
case Transformation::Orientation::R1:
case Transformation::Orientation::R3:
case Transformation::Orientation::XR:
case Transformation::Orientation::YR:
rpOrient = 2;
break;
default:
break;
}
if (dynamic_cast<Horizontal*>(entity)) {
// rpOrient *is* the rotation.
} else if ( dynamic_cast<Vertical*>(entity) ) {
// rpOrient is the inverse rotation.
rpOrient = (rpOrient == 1) ? 2 : 1;
} else {
rpOrient = 0;
}
switch ( rpOrient ) {
case 1:
xMin = routingPad->getSourcePosition().getX();
xMax = routingPad->getTargetPosition().getX();
yMin = yMax
= routingPad->getTargetPosition().getY();
break;
case 2:
yMin = routingPad->getSourcePosition().getY();
yMax = routingPad->getTargetPosition().getY();
xMin = xMax
= routingPad->getTargetPosition().getX();
break;
default:
xMin = xMax = routingPad->getPosition().getX();
yMin = yMax = routingPad->getPosition().getY();
break;
}
#endif
} else {
xMin = xMax = component->getPosition().getX();
yMin = yMax = component->getPosition().getY();
}
order( xMin, xMax );
order( yMin, yMax );
Box bb ( xMin, yMin, xMax, yMax );
if (_segment and _segment->isWide()) {
if (dynamic_cast<AutoHorizontal*>(_segment)) bb.inflate( 0, 0, 0, -_segment->getWidth() );
else bb.inflate( 0, 0, -_segment->getWidth(), 0 );
}
cdebug_log(145,0) << "| Using (y): "
<< DbU::getValueString(bb.getYMin()) << " "
<< DbU::getValueString(bb.getYMax()) << " " << bb << endl;
cdebug_tabw(145,-1);
return bb;
}
void AutoContactTerminal::_invalidate ( Flags flags )
{
cdebug_log(145,0) << "flags:" << flags.asString(FlagsFunction) << endl;
if (_segment) _segment->invalidate( flags|Flags::Propagate );
}
void AutoContactTerminal::cacheDetach ( AutoSegment* segment )
{
if (_segment == segment) {
//_segment->unsetFlags( AutoSegment::SegAxisSet );
_segment = NULL;
setFlags( CntInvalidatedCache );
unsetFlags( CntDrag );
}
}
void AutoContactTerminal::cacheAttach ( AutoSegment* segment )
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::cacheAttach() " << this << endl;
if (_segment) {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" cache has not been cleared first, cancelled."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
cdebug_tabw(145,-1);
DebugSession::close();
return;
}
_segment = segment;
unsetFlags( CntInvalidatedCache );
if ( (dynamic_cast<AutoHorizontal*>(_segment) and (getFlags() & CntOnHorizontal))
or (dynamic_cast<AutoVertical*> (_segment) and (getFlags() & CntOnVertical )) ) {
_segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegAxisSet );
setFlags( CntDrag );
cdebug_log(145,0) << "Drag Contact/Segment set" << endl;
}
cdebug_log(145,0) << "Cached:" << _segment << endl;
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactTerminal::updateCache ()
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl;
Component* anchor;
Horizontal** horizontals = new Horizontal* [2];
Vertical** verticals = new Vertical* [2];
_getTopology( base(), anchor, horizontals, verticals, 2 );
if (anchor == NULL)
showTopologyError( "Terminal is missing an anchor (RoutingPad or Component)." );
size_t count = 0;
if (horizontals[0] != NULL) ++count;
if (horizontals[1] != NULL) ++count;
if (verticals [0] != NULL) ++count;
if (verticals [1] != NULL) ++count;
if (count != 1) {
showTopologyError( "Terminal has not *exactly* one segment." );
}
if (horizontals[0] != NULL ) {
_segment = Session::lookup( horizontals[0] );
if (getFlags() & CntOnHorizontal) {
setFlags( CntDrag );
_segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegFixedAxis );
}
} else {
_segment = Session::lookup( verticals[0] );
if (getFlags() & CntOnVertical) {
setFlags( CntDrag );
_segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegFixedAxis );
}
}
if (_segment == NULL) {
ostringstream os;
os << this << ", AutoSegment lookup failed for:"
<< "\n h1: " << horizontals[0]
<< "\n v1: " << verticals[0];
delete [] horizontals;
delete [] verticals;
showTopologyError( os.str() );
throw Error( os.str() );
}
unsetFlags( CntInvalidatedCache );
cdebug_log(145,0) << "seg:" << _segment << endl;
delete [] horizontals;
delete [] verticals;
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactTerminal::updateGeometry ()
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
base()->invalidate( false );
unsetFlags( CntInvalidated );
ostringstream message;
if (not hasBadTopology()) {
Box anchorBb = getAnchor()->getBoundingBox();
anchorBb.inflate( Session::getViaWidth (getAnchor()->getLayer())
- Session::getWireWidth(getAnchor()->getLayer()) );
if (_segment->isHorizontal()) {
DbU::Unit axis = _segment->getY();
if (_segment->isWide()) {
axis += (- _segment->getWidth() + Session::getWireWidth(_segment->getLayer())) / 2;
setHeight( _segment->getContactWidth() );
}
if (not getUConstraints(Flags::Vertical).contains(axis)) {
cdebug_log(145,0) << "Cached: " << _segment << endl;
message << "Terminal horizontal segment Y " << DbU::getValueString(axis)
<< " axis is outside RoutingPad " << getUConstraints(Flags::Vertical) << ".";
Interval intv;
_segment->getConstraints( intv );
message << "\n Segment constraints: " << intv << endl;
Flags flags = Flags::NoFlags;
if (_segment->isCreated()) flags |= Flags::CParanoid;
showTopologyError( message.str(), flags );
} else
setY( _segment->getY() );
} else {
DbU::Unit axis = _segment->getX();
if (_segment->isWide()) {
axis += (- _segment->getWidth() + Session::getWireWidth(_segment->getLayer())) / 2;
setWidth ( _segment->getContactWidth() );
setHeight( anchorBb.getHeight() );
cdebug_log(145,0) << "Contact for wide segment." << endl;
}
if (canDrag()) {
AutoContact* opposite = _segment->getOppositeAnchor(this);
AutoSegment* perpandicular = opposite->getPerpandicular( _segment );
if (perpandicular) {
cdebug_log(145,0) << "Draging V interval ["
<< DbU::getValueString(getCBYMin()) << " "
<< DbU::getValueString(getCBYMax()) << "]" << endl;
DbU::Unit y = perpandicular->getAxis();
y = std::min( y, getCBYMax() );
y = std::max( y, getCBYMin() );
Point onGrid = Session::getNearestGridPoint( Point(getX(),y), getConstraintBox() );
setY( onGrid.getY() );
cdebug_log(145,0) << "Draging to Y @" << DbU::getValueString(y)
<< " pitched:" << DbU::getValueString(onGrid.getY())
<< " " << getConstraintBox() << endl;
}
}
if (not getUConstraints(Flags::Horizontal).contains(axis)) {
cdebug_log(145,0) << "Cached: " << _segment << endl;
message << "Terminal vertical segment X " << DbU::getValueString(axis)
<< " axis is outside RoutingPad " << getUConstraints(Flags::Horizontal) << ".";
Flags flags = Flags::NoFlags;
if (_segment->isCreated()) flags |= Flags::CParanoid;
showTopologyError( message.str(), flags );
} else
setX( _segment->getX() );
}
}
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactTerminal::updateTopology ()
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
RoutingGauge* rg = Session::getRoutingGauge();
size_t anchorDepth = rg->getLayerDepth( (_flags & CntIgnoreAnchor) ? getLayer()
: getAnchor()->getLayer() );
size_t segmentDepth = rg->getLayerDepth( _segment->getLayer() );
size_t delta = abssub( anchorDepth, segmentDepth );
if (delta > 3) {
showTopologyError( "Sheared Terminal, layer delta exceed 3." );
setFlags( CntBadTopology );
} else {
if (delta > 1) {
//_segment = _segment->makeDogleg( this );
_segment->makeDogleg( this );
delta = abssub( anchorDepth, rg->getLayerDepth( _segment->getLayer() ) );
cdebug_log(145,0) << "Delta: " << delta << " Update seg: " << _segment << endl;
}
if (delta == 0) setLayerAndWidth( delta, anchorDepth );
if (delta == 1) setLayerAndWidth( delta, std::min(anchorDepth,segmentDepth) );
}
_segment->invalidate( this );
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactTerminal::forceOnGrid ( Point gridPoint )
{
setFlags( CntUserNativeConstraints );
setConstraintBox( Box(gridPoint) );
}
string AutoContactTerminal::_getTypeName () const
{ return "ContactTerminal"; }
} // Anabatic namespace.

View File

@ -1,299 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoContactTurn.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <climits>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Layer.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Net.h"
#include "hurricane/Plug.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/Session.h"
namespace Anabatic {
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::DebugSession;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactTurn".
AutoContactTurn* AutoContactTurn::create ( GCell* gcell, Net* net, const Layer* layer )
{
_preCreate( gcell, net, layer );
DbU::Unit viaSide = Session::getViaWidth( layer );
Contact* contact = Contact::create ( net
, layer
, gcell->getCenter().getX()
, gcell->getCenter().getY()
, viaSide
, viaSide
);
AutoContactTurn* autoContact = new AutoContactTurn ( gcell, contact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
cdebug_log(145,0) << "create(net*) " << autoContact << endl;
return autoContact;
}
AutoContactTurn::AutoContactTurn ( GCell* gcell, Contact* contact )
: AutoContact (gcell,contact)
, _horizontal1(NULL)
, _vertical1 (NULL)
{
setFlags( CntTurn );
}
AutoContactTurn::~AutoContactTurn ()
{ }
AutoSegment* AutoContactTurn::getOpposite ( const AutoSegment* ) const
{ return NULL; }
AutoSegment* AutoContactTurn::getPerpandicular ( const AutoSegment* reference ) const
{
cdebug_log(149,0) << _getTypeName() << "::getPerpandicular() " << this
<< " to:" << reference << endl;
cdebug_log(149,0) << "| _horizontal1:" << _horizontal1 << endl;
cdebug_log(149,0) << "| _vertical1 :" << _vertical1 << endl;
if (reference == _horizontal1) return _vertical1;
if (reference == _vertical1 ) return _horizontal1;
cdebug_log(149,0) << _getTypeName() << "::getPerpandicular() " << this
<< " to:" << reference << " failed." << endl;
return NULL;
}
AutoSegment* AutoContactTurn::getSegment ( unsigned int index ) const
{
switch ( index ) {
case 0: return _horizontal1;
case 2: return _vertical1;
}
return NULL;
}
AutoHorizontal* AutoContactTurn::getHorizontal1 () const { return _horizontal1; };
AutoVertical* AutoContactTurn::getVertical1 () const { return _vertical1; };
void AutoContactTurn::_invalidate ( Flags flags )
{
if (_horizontal1) _horizontal1->invalidate( flags|Flags::Propagate );
if (_vertical1 ) _vertical1 ->invalidate( flags|Flags::Propagate );
}
void AutoContactTurn::cacheDetach ( AutoSegment* segment )
{
cdebug_log(149,0) << _getTypeName() << "::cacheDetach() " << this
<< " from:" << segment << endl;
if (segment == _horizontal1) _horizontal1 = NULL;
else if (segment == _vertical1) _vertical1 = NULL;
else return;
setFlags( CntInvalidatedCache );
}
void AutoContactTurn::cacheAttach ( AutoSegment* segment )
{
cdebug_log(149,0) << _getTypeName() << "::cacheAttach() " << this
<< " to:" << segment << endl;
if (segment->getDirection() == Flags::Horizontal) {
if (_horizontal1) {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" h1 cache has not been cleared first, cancelled."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
return;
}
_horizontal1 = static_cast<AutoHorizontal*>(segment);
} else if (segment->getDirection() == Flags::Vertical) {
if (_vertical1) {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" v1 cache has not been cleared first, cancelled."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
return;
}
_vertical1 = static_cast<AutoVertical*>(segment);
}
if (_horizontal1 and _vertical1) unsetFlags( CntInvalidatedCache );
setFlags( CntInvalidatedWidth );
}
void AutoContactTurn::updateCache ()
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateCache() " << this << endl;
Component* anchor;
Horizontal** horizontals = new Horizontal* [2];
Vertical** verticals = new Vertical* [2];
_getTopology ( base(), anchor, horizontals, verticals, 2 );
_horizontal1 = static_cast<AutoHorizontal*>( Session::lookup(horizontals[0]) );
_vertical1 = static_cast<AutoVertical *>( Session::lookup(verticals [0]) );
string message;
if (horizontals[0] == NULL) message = "Turn is missing mandatory horizontal segment.";
else if (horizontals[1] != NULL) message = "Turn has more than one horizontal segment.";
else if (verticals [0] == NULL) message = "Turn is missing mandatory vertical segment.";
else if (verticals [1] != NULL) message = "Turn has more than one vertical segment.";
else if (_horizontal1 == NULL) message = "AutoSegment lookup failed on horizontal segment.";
else if (_vertical1 == NULL) message = "AutoSegment lookup failed on vertical segment.";
if (not message.empty()) {
showTopologyError( message );
setFlags( CntBadTopology );
} else {
unsetFlags( CntInvalidatedCache );
setFlags ( CntInvalidatedWidth );
}
cdebug_log(145,0) << "h1:" << _horizontal1 << endl;
cdebug_log(145,0) << "v1:" << _vertical1 << endl;
delete [] horizontals;
delete [] verticals;
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactTurn::updateGeometry ()
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateGeometry() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
base()->invalidate( false );
unsetFlags( CntInvalidated );
if (not hasBadTopology()) {
setX( getVertical1 ()->getX() );
setY( getHorizontal1()->getY() );
updateSize();
}
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactTurn::updateTopology ()
{
DebugSession::open ( getNet(), 145, 150 );
cdebug_log(145,1) << _getTypeName() << "::updateTopology() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (not hasBadTopology()) {
RoutingGauge* rg = Session::getRoutingGauge();
size_t depthH1 = rg->getLayerDepth( getHorizontal1()->getLayer() );
size_t depthV1 = rg->getLayerDepth( getVertical1 ()->getLayer() );
size_t depthContact = (depthH1 <= depthV1) ? depthH1 : depthH1-1;
size_t delta = abssub ( depthH1, depthV1 );
unsetFlags( CntWeakTerminal );
if (delta > 3) {
showTopologyError( "Sheared Turn, layer delta exceed 3." );
setFlags( CntBadTopology );
} else {
if (delta > 1) {
bool updateH1 = (_horizontal1->isInvalidatedLayer() and not _horizontal1->isNonPref())
or _vertical1->isNonPref();
if (updateH1) {
//_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
_horizontal1->makeDogleg(this);
cdebug_log(145,0) << "Update h1: " << _horizontal1 << endl;
} else /*if (_vertical1->isInvalidatedLayer())*/ {
//_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
_vertical1->makeDogleg(this);
cdebug_log(145,0) << "Update v1: " << _vertical1 << endl;
}
depthH1 = rg->getLayerDepth( _horizontal1->getLayer() );
depthV1 = rg->getLayerDepth( _vertical1->getLayer() );
depthContact = (depthH1 <= depthV1) ? depthH1 : depthH1-1;
delta = abssub ( depthH1, depthV1 );
}
setLayerAndWidth( delta, depthContact );
}
_horizontal1->invalidate( this );
_vertical1 ->invalidate( this );
}
cdebug_tabw(145,-1);
DebugSession::close ();
}
string AutoContactTurn::_getTypeName () const
{ return "ContactTurn"; }
} // Anabatic namespace.

View File

@ -1,320 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoContactVTee.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <climits>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Layer.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/Net.h"
#include "hurricane/Plug.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/AutoContactVTee.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/Session.h"
namespace Anabatic {
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::DebugSession;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactVTee".
AutoContactVTee* AutoContactVTee::create ( GCell* gcell, Net* net, const Layer* layer )
{
_preCreate( gcell, net, layer );
DbU::Unit viaSide = Session::getViaWidth( layer );
Contact* contact = Contact::create( net
, layer
, gcell->getCenter().getX()
, gcell->getCenter().getY()
, viaSide
, viaSide
);
AutoContactVTee* autoContact = new AutoContactVTee( gcell, contact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
cdebug_log(145,0) << "create(net*) " << autoContact << endl;
return autoContact;
}
AutoContactVTee::AutoContactVTee ( GCell* gcell, Contact* contact )
: AutoContact(gcell,contact)
, _horizontal1(NULL)
, _vertical1 (NULL)
, _vertical2 (NULL)
{
setFlags( CntVTee );
}
AutoContactVTee::~AutoContactVTee ()
{ }
AutoSegment* AutoContactVTee::getOpposite ( const AutoSegment* from ) const
{
if (from == _vertical1) return _vertical2;
if (from == _vertical2) return _vertical1;
return NULL;
}
AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* from ) const
{
if ( (from == _vertical1) or (from == _vertical2) ) return _horizontal1;
return NULL;
}
AutoSegment* AutoContactVTee::getSegment ( unsigned int index ) const
{
switch ( index ) {
case 0: return _horizontal1;
case 2: return _vertical1;
case 3: return _vertical2;
}
return NULL;
}
AutoHorizontal* AutoContactVTee::getHorizontal1 () const { return _horizontal1; };
AutoVertical* AutoContactVTee::getVertical1 () const { return _vertical1; };
AutoVertical* AutoContactVTee::getVertical2 () const { return _vertical2; };
void AutoContactVTee::_invalidate ( Flags flags )
{
flags |= Flags::Propagate;
if (_vertical1 and _vertical2) {
if (_vertical1->isInvalidated() xor _vertical2->isInvalidated())
flags.reset( Flags::NoFlags );
}
if (_vertical1 ) _vertical1 ->invalidate( flags );
if (_vertical2 ) _vertical2 ->invalidate( flags );
if (_horizontal1) _horizontal1->invalidate();
}
void AutoContactVTee::cacheDetach ( AutoSegment* segment )
{
if (segment == _horizontal1) _horizontal1 = NULL;
else if (segment == _vertical1) _vertical1 = NULL;
else if (segment == _vertical2) _vertical2 = NULL;
else return;
setFlags( CntInvalidatedCache );
}
void AutoContactVTee::cacheAttach ( AutoSegment* segment )
{
if (segment->getDirection() == Flags::Vertical) {
if (not _vertical1) _vertical1 = static_cast<AutoVertical*>(segment);
else if (not _vertical2) _vertical2 = static_cast<AutoVertical*>(segment);
else {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" v1 & v2 cache have not been cleared first, cancelling."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
return;
}
} else if (segment->getDirection() == Flags::Horizontal) {
if (_horizontal1) {
cerr << Bug( "%s::cacheAttach() On %s,\n"
" h1 cache has not been cleared first, cancelling."
, _getTypeName().c_str(), getString(this).c_str()
) << endl;
return;
}
_horizontal1 = static_cast<AutoHorizontal*>(segment);
}
if (_vertical1 and _vertical2 and _horizontal1)
unsetFlags( CntInvalidatedCache );
}
void AutoContactVTee::updateCache ()
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << "AutoContactVTee::updateCache() " << this << endl;
Component* anchor;
Horizontal** horizontals = new Horizontal* [3];
Vertical** verticals = new Vertical* [3];
_getTopology ( base(), anchor, horizontals, verticals, 3 );
_horizontal1 = static_cast<AutoHorizontal*>( Session::lookup(horizontals[0]) );
_vertical1 = static_cast<AutoVertical *>( Session::lookup(verticals [0]) );
_vertical2 = static_cast<AutoVertical *>( Session::lookup(verticals [1]) );
string message;
if (verticals [0] == NULL) message = "VTee has less than two vertical segments.";
else if (verticals [1] == NULL) message = "VTee has less than two vertical segments.";
else if (verticals [2] != NULL) message = "VTee has more than two vertical segments.";
else if (horizontals[0] == NULL) message = "VTee is missing mandatory horizontal segment.";
else if (horizontals[1] != NULL) message = "VTee has more than one horizontal segment.";
else if (_horizontal1 == NULL) message = "AutoSegment lookup failed on horizontal segment.";
else if (_vertical1 == NULL) message = "AutoSegment lookup failed on first vertical segment.";
else if (_vertical2 == NULL) message = "AutoSegment lookup failed on second vertical segment.";
else if ( (not _vertical1->isCreated() and not _vertical2->isCreated())
and (_vertical1->getY() != _vertical2->getY()) )
message = "VTee has misaligned vertical segments";
if (not message.empty() ) {
showTopologyError( message );
setFlags( CntBadTopology );
}
unsetFlags( CntInvalidatedCache );
cdebug_log(145,0) << "h1:" << _horizontal1 << endl;
cdebug_log(145,0) << "v1:" << _vertical1 << endl;
cdebug_log(145,0) << "v2:" << _vertical2 << endl;
delete [] horizontals;
delete [] verticals;
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactVTee::updateGeometry ()
{
DebugSession::open( getNet(), 145, 150 );
cdebug_log(145,1) << "AutoContactVTee::updateGeometry() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
base()->invalidate( false );
unsetFlags( CntInvalidated );
if (not hasBadTopology()) {
setX( getVertical1 ()->getX() );
setY( getHorizontal1()->getY() );
updateSize();
}
cdebug_tabw(145,-1);
DebugSession::close();
}
void AutoContactVTee::updateTopology ()
{
DebugSession::open ( getNet(), 145, 150 );
cdebug_log(145,1) << "AutoContactVTee::updateTopology() " << this << endl;
if (isInvalidatedCache()) updateCache();
if (isInvalidatedCache()) {
cerr << Error( "%s::updateGeometry() %s: Unable to restore cache."
, _getTypeName().c_str(), getString(this).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (not hasBadTopology()) {
RoutingGauge* rg = Session::getRoutingGauge();
size_t depthV1 = rg->getLayerDepth( getVertical1 ()->getLayer() );
size_t depthV2 = rg->getLayerDepth( getVertical2 ()->getLayer() );
size_t depthH1 = rg->getLayerDepth( getHorizontal1()->getLayer() );
size_t minDepth = std::min( depthH1, std::min(depthV1,depthV2) );
size_t maxDepth = std::max( depthH1, std::max(depthV1,depthV2) );
size_t delta = maxDepth - minDepth;
cdebug_log(145,0) << "minDepth:" << minDepth << endl;
cdebug_log(145,0) << "maxDepth:" << maxDepth << endl;
cdebug_log(145,0) << "delta:" << delta << endl;
unsetFlags( CntWeakTerminal );
if ( maxDepth - minDepth > 3 ) {
showTopologyError( "Sheared VTee, layer delta exceed 3." );
setFlags( CntBadTopology );
} else {
if (depthV1 == depthV2) {
cdebug_log(145,0) << "depthV1 == depthV2 (" << depthV1 << ")" << endl;
// Dogleg on the horizontal.
switch ( delta ) {
case 0:
case 1: setLayerAndWidth( delta, minDepth ); break;
default:
cdebug_log(145,0) << "Restore connectivity: dogleg on h1." << endl;
setLayerAndWidth( delta, depthV1 + ((depthV1==minDepth)?0:-1) );
_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
break;
}
} else {
// Dogleg on the vertical with the greater gap (should be equal to +/-2).
int deltaV1 = (int)depthV1 - (int)depthH1;
int deltaV2 = (int)depthV2 - (int)depthH1;
if (std::abs(deltaV1) > std::abs(deltaV2)) {
setLayerAndWidth( 2, depthV2 + ((depthV2<depthH1)?0:-1) );
//_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
_vertical1->makeDogleg(this);
} else {
setLayerAndWidth( 2, depthV1 + ((depthV1<depthH1)?0:-1) );
//_vertical2 = static_cast<AutoVertical*>( _vertical2->makeDogleg(this) );
_vertical2->makeDogleg(this);
}
}
}
_horizontal1->invalidate( this );
_vertical1 ->invalidate( this );
_vertical2 ->invalidate( this );
}
cdebug_tabw(145,-1);
DebugSession::close ();
}
string AutoContactVTee::_getTypeName () const
{ return "ContactVTee"; }
} // Anabatic namespace.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,774 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoSegments.cpp" |
// +-----------------------------------------------------------------+
#include "hurricane/Error.h"
#include "hurricane/RoutingPad.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoSegment.h"
namespace {
using namespace Anabatic;
AutoContact* isLocalDogleg ( AutoSegment* current, AutoContact* from, AutoSegment* master )
{
if (not current->isLocal() or not from->isTurn()) return NULL;
AutoContact* to = current->getOppositeAnchor( from );
if (not to->isTurn()) return NULL;
AutoSegment* targetGlobal = to->getPerpandicular( current );
if (not targetGlobal->isGlobal() or (master->getLayer() != targetGlobal->getLayer())) return NULL;
cdebug_log(144,0) << "Global aligned though dogleg:" << targetGlobal << endl;
Interval masterConstraints;
Interval targetConstraints;
master ->getConstraints( masterConstraints );
targetGlobal->getConstraints( targetConstraints );
if (not targetConstraints.intersect(masterConstraints)) return NULL;
return to;
}
} // Anonymous namespace.
namespace Anabatic {
using namespace std;
using Hurricane::tab;
using Hurricane::_TName;
using Hurricane::Error;
using Hurricane::ForEachIterator;
using Hurricane::Hook;
using Hurricane::RoutingPad;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegmentStack".
void AutoSegmentStack::push ( AutoContact* contact, AutoSegment* segment )
{
cdebug_log(144,0) << "Stacking " << contact << " + " << segment << endl;
push_back( make_pair(contact,segment) );
}
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegments_OnContact".
AutoSegments_OnContact::Locator::Locator ( AutoSegment* master, Contact* contact )
: AutoSegmentHL()
, _master (master)
, _element (NULL)
{
_hook = contact->getBodyHook()->getPreviousMasterHook();
progress();
}
AutoSegmentHL* AutoSegments_OnContact::Locator::getClone () const
{ return new Locator(*this); }
AutoSegment* AutoSegments_OnContact::Locator::getElement () const
{ return _element; }
bool AutoSegments_OnContact::Locator::isValid () const
{ return _hook; }
void AutoSegments_OnContact::Locator::progress ()
{
while (_hook) {
_hook = _hook->getNextHook();
_element = NULL;
if ( _hook->isMaster() ) { _hook = NULL; break; }
Segment* segment = dynamic_cast<Segment*>( _hook->getComponent() );
if (segment) _element = Session::lookup( segment );
if (not _element or (_element == _master)) continue;
break;
}
}
string AutoSegments_OnContact::Locator::_getString () const
{
string s = "<" + _TName("AutoSegments_OnContact::Locator")
+ getString(_element)
+ ">";
return s;
}
AutoSegmentHC* AutoSegments_OnContact::getClone () const
{ return new AutoSegments_OnContact(*this); }
AutoSegmentHL* AutoSegments_OnContact::getLocator () const
{ return new Locator(_master,_contact); }
string AutoSegments_OnContact::_getString () const
{
string s = "<" + _TName("AutoSegments_OnContact") + " "
+ getString(_master)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegments_OnRoutingPad".
AutoSegments_OnRoutingPad::Locator::Locator ( RoutingPad* rp, const AutoContactTerminal* contact )
: AutoSegmentHL()
, _elements ({{NULL,NULL,NULL,NULL}})
, _index (0)
{
if (rp) {
for ( Component* component : rp->getSlaveComponents() ) {
AutoSegment* segment = Session::lookup( dynamic_cast<Segment*>(component) );
if (not segment) continue;
size_t offset = 2;
if (contact and (contact->getSegment() == segment)) offset = 0;
if (segment->isHorizontal()) _elements[offset ] = segment;
else _elements[offset+1] = segment;
}
}
while ( (_index < 4) and not _elements[_index] ) ++_index;
}
AutoSegmentHL* AutoSegments_OnRoutingPad::Locator::getClone () const
{ return new Locator(*this); }
AutoSegment* AutoSegments_OnRoutingPad::Locator::getElement () const
{ return (_index < 4) ? _elements[_index] : NULL; }
bool AutoSegments_OnRoutingPad::Locator::isValid () const
{ return (_index < 4); }
void AutoSegments_OnRoutingPad::Locator::progress ()
{
cdebug_log(145,0) << "AutoSegments_OnRoutingPad::Locator::progress()" << endl;
++_index;
while ( (_index < 4) and not _elements[_index] ) ++_index;
}
string AutoSegments_OnRoutingPad::Locator::_getString () const
{
string s = "<" + _TName("AutoSegments_OnRoutingPad::Locator")
+ getString(_index)
+ ">";
return s;
}
AutoSegments_OnRoutingPad::AutoSegments_OnRoutingPad ( const AutoContact* contact )
: AutoSegmentHC()
, _routingPad(NULL)
, _contact (dynamic_cast<const AutoContactTerminal*>(contact))
{
if (_contact)
_routingPad = dynamic_cast<RoutingPad*>(_contact->getAnchor());
}
AutoSegmentHC* AutoSegments_OnRoutingPad::getClone () const
{ return new AutoSegments_OnRoutingPad(*this); }
AutoSegmentHL* AutoSegments_OnRoutingPad::getLocator () const
{ return new Locator(_routingPad,_contact); }
string AutoSegments_OnRoutingPad::_getString () const
{
string s = "<" + _TName("AutoSegments_OnRoutingPad") + " "
+ getString(_routingPad)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "AutoSegments_Connecteds".
AutoSegments_Connecteds::Locator::Locator ( AutoSegment* segment, Flags flags )
: AutoSegmentHL()
, _stack ()
{
cdebug_log(145,0) << "AutoSegments_Connecteds::Locator::Locator()" << endl;
if (flags & Flags::Source) {
AutoContact* contact = segment->getAutoSource();
if (contact) _stack.push( contact, segment );
}
if (flags & Flags::Target) {
AutoContact* contact = segment->getAutoTarget();
if (contact) _stack.push( contact, segment );
}
}
AutoSegmentHL* AutoSegments_Connecteds::Locator::getClone () const
{ return new Locator(*this); }
bool AutoSegments_Connecteds::Locator::isValid () const
{ return not _stack.isEmpty(); }
void AutoSegments_Connecteds::Locator::progress ()
{
cdebug_log(145,0) << "AutoSegments_Connecteds::Locator::progress()" << endl;
while (not _stack.isEmpty()) {
AutoContact* sourceContact = _stack.getAutoContact ();
AutoSegment* sourceSegment = _stack.getAutoSegment ();
_stack.pop ();
AutoContactTerminal* sourceTerminal = dynamic_cast<AutoContactTerminal*>( sourceContact );
if (sourceTerminal) {
for ( AutoSegment* currentSegment : sourceTerminal->getRpConnecteds() ) {
cdebug_log(145,0) << "Looking at: " << currentSegment << endl;
if (currentSegment == sourceSegment) continue;
AutoContact* targetContact = currentSegment->getAutoSource();
if (not targetContact->isTerminal()) _stack.push( targetContact, currentSegment );
targetContact = currentSegment->getAutoTarget();
if (not targetContact->isTerminal()) _stack.push( targetContact, currentSegment );
}
} else {
LocatorHelper helper (sourceContact,Flags::WithPerpands);
for ( ; helper.isValid() ; helper.progress() ) {
AutoSegment* currentSegment = helper.getSegment();
cdebug_log(145,0) << "Looking at: " << currentSegment << endl;
if (currentSegment == sourceSegment) continue;
AutoContact* targetContact = currentSegment->getOppositeAnchor( sourceContact );
if (targetContact) _stack.push( targetContact, currentSegment );
}
}
break;
}
}
string AutoSegments_Connecteds::Locator::_getString () const
{
string s = "<" + _TName("AutoSegments_Connecteds::Locator") + ">";
return s;
}
AutoSegmentHC* AutoSegments_Connecteds::getClone () const
{ return new AutoSegments_Connecteds(*this); }
AutoSegmentHL* AutoSegments_Connecteds::getLocator () const
{ return new Locator(_segment,_flags); }
AutoSegment* AutoSegments_Connecteds::Locator::getElement () const
{ return _stack.getAutoSegment(); }
string AutoSegments_Connecteds::_getString () const
{
string s = "<" + _TName("AutoSegments_Connecteds") + " "
+ getString(_segment)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "AutoSegments_Aligneds".
AutoSegments_Aligneds::Locator::Locator ( AutoSegment* segment, Flags flags )
: AutoSegmentHL()
, _flags (flags)
, _master(segment)
, _stack ()
{
if (not _master) return;
if (not _flags.intersect(Flags::Source|Flags::Target))
_flags |= Flags::Source | Flags::Target;
_flags |= (_master->isHorizontal()) ? Flags::Horizontal : Flags::Vertical;
if (_flags & Flags::WithDoglegs) _flags |= Flags::WithPerpands;
cdebug_log(144,0) << "AutoSegments_Aligneds::Locator::Locator() _flags:" << _flags.asString(FlagsFunction) << endl;
if (_flags & Flags::Source) {
AutoContact* contact = segment->getAutoSource();
if (contact) _stack.push( contact, segment );
}
if (_flags & Flags::Target) {
AutoContact* contact = segment->getAutoTarget();
if (contact) _stack.push( contact, segment );
}
if (not (_flags & Flags::WithSelf)) progress();
}
AutoSegmentHL* AutoSegments_Aligneds::Locator::getClone () const
{ return new Locator(*this); }
bool AutoSegments_Aligneds::Locator::isValid () const
{ return not _stack.isEmpty(); }
void AutoSegments_Aligneds::Locator::progress ()
{
cdebug_log(144,0) << "AutoSegments_Aligneds::Locator::progress()" << endl;
while (not _stack.isEmpty()) {
AutoContact* sourceContact = _stack.getAutoContact ();
AutoSegment* sourceSegment = _stack.getAutoSegment ();
_stack.pop ();
cdebug_log(144,1) << "Iterate over: " << sourceContact << endl;
LocatorHelper helper (sourceContact, _flags);
for ( ; helper.isValid() ; helper.progress() ) {
AutoSegment* currentSegment = helper.getSegment();
cdebug_log(144,0) << "| " << currentSegment << endl;
if (currentSegment == sourceSegment) continue;
if (AutoSegment::areAligneds(currentSegment,_master)) {
if ( (not (_flags & Flags::NoCheckLayer))
and AutoSegment::areAlignedsAndDiffLayer(currentSegment,_master)) {
cerr << Error( "Aligned segments not in same layer (aligneds locator)\n"
" %s\n"
" %s."
,getString(_master).c_str()
,getString(currentSegment).c_str() ) << endl;
continue;
}
AutoContact* targetContact = currentSegment->getOppositeAnchor( sourceContact );
if (targetContact) _stack.push( targetContact, currentSegment );
} else {
if (_flags & Flags::WithDoglegs) {
AutoContact* targetContact = isLocalDogleg( currentSegment, sourceContact, _master );
if (targetContact) {
cdebug_log(144,0) << "Stacking dogleg global. " << endl;
_stack.push( targetContact, currentSegment );
continue;
}
}
}
}
cdebug_tabw(144,-1);
if (_stack.getAutoSegment() == _master) continue;
if (not AutoSegment::areAligneds(_stack.getAutoSegment(),_master)) continue;
break;
}
}
string AutoSegments_Aligneds::Locator::_getString () const
{
string s = "<" + _TName("AutoSegments_Aligneds::Locator") + ">";
return s;
}
AutoSegmentHC* AutoSegments_Aligneds::getClone () const
{ return new AutoSegments_Aligneds(*this); }
AutoSegmentHL* AutoSegments_Aligneds::getLocator () const
{ return new Locator(_segment,_flags); }
AutoSegment* AutoSegments_Aligneds::Locator::getElement () const
{ return _stack.getAutoSegment(); }
string AutoSegments_Aligneds::_getString () const
{
string s = "<" + _TName("AutoSegments_Aligneds") + " "
+ getString(_segment)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "AutoSegments_Perpandiculars".
AutoSegments_Perpandiculars::Locator::Locator ( AutoSegment* master, Flags flags )
: AutoSegmentHL()
//, _flags (Flags::WithPerpands|Flags::WithDoglegs)
, _flags (Flags::WithPerpands|flags)
, _master (master)
, _stack ()
, _perpandiculars()
{
cdebug_log(144,0) << "AutoSegments_Perpandiculars::Locator::Locator(): _flags:" << _flags.asString(FlagsFunction) << endl;
cdebug_log(144,0) << " " << _master << endl;
if (not _master) return;
if (_master->isHorizontal()) _flags |= Flags::Horizontal;
else _flags |= Flags::Vertical;
AutoContact* contact = _master->getAutoSource();
if ( contact ) _stack.push( contact, _master );
contact = _master->getAutoTarget();
if ( contact ) _stack.push( contact, _master );
progress();
}
AutoSegment* AutoSegments_Perpandiculars::Locator::getElement () const
{
if (_perpandiculars.empty()) return NULL;
return _perpandiculars.back();
}
void AutoSegments_Perpandiculars::Locator::progress ()
{
cdebug_log(144,1) << "AutoSegments_Perpandiculars::Locator::progress()" << endl;
if (not _perpandiculars.empty()) _perpandiculars.pop_back();
if (not _perpandiculars.empty()) { cdebug_tabw(144,-1); return; }
while ( not _stack.isEmpty() ) {
AutoContact* sourceContact = _stack.getAutoContact();
AutoSegment* sourceSegment = _stack.getAutoSegment();
_stack.pop();
cdebug_log(144,0) << "Iterate over: " << sourceContact << endl;
LocatorHelper helper (sourceContact, _flags);
for ( ; helper.isValid() ; helper.progress() ) {
AutoSegment* currentSegment = helper.getSegment();
if (currentSegment == sourceSegment) continue;
cdebug_log(144,0) << "| " << currentSegment << endl;
if (AutoSegment::areAligneds(currentSegment,_master)) {
AutoContact* targetContact = currentSegment->getOppositeAnchor( sourceContact );
if (targetContact) {
if (_master->getLayer() != currentSegment->getLayer()) {
continue;
}
cdebug_log(144,0) << "Stacking target. " << endl;
_stack.push( targetContact, currentSegment );
// if ( (_master->isHorizontal() and sourceContact->isHTee())
// or (_master->isVertical () and sourceContact->isVTee()) ) {
// if (AutoSegment::areAlignedsAndDiffLayer(currentSegment,_master)) {
// cerr << Error("Aligned segments not in same layer (perpandicular locator)\n"
// " %s\n"
// " %s."
// ,getString(_master).c_str()
// ,getString(currentSegment).c_str()) << endl;
// continue;
// }
// cdebug_log(144,0) << "Stacking target. " << endl;
// _stack.push( targetContact, currentSegment );
// }
} else {
cdebug_log(144,0) << "No opposite anchor to: " << sourceContact << endl;
}
} else {
if ( (_flags & Flags::WithDoglegs) and currentSegment->isLocal() and sourceContact->isTurn() ) {
AutoContact* targetContact = currentSegment->getOppositeAnchor( sourceContact );
if (targetContact->isTurn()) {
AutoSegment* targetGlobal = targetContact->getPerpandicular( currentSegment );
if (targetGlobal->isGlobal() and (_master->getLayer() == targetGlobal->getLayer())) {
cdebug_log(144,0) << "Global aligned though dogleg:" << targetGlobal << endl;
Interval masterConstraints;
Interval targetConstraints;
_master ->getConstraints( masterConstraints );
targetGlobal->getConstraints( targetConstraints );
if (targetConstraints.intersect(masterConstraints)) {
cdebug_log(144,0) << "Stacking dogleg global. " << endl;
_stack.push( targetContact, currentSegment );
continue;
}
}
}
}
_perpandiculars.push_back( currentSegment );
}
}
if (_stack.isEmpty()) break;
if (_stack.getAutoSegment() == _master) continue;
if (not _perpandiculars.empty()) break;
}
cdebug_tabw(144,-1);
}
AutoSegmentHL* AutoSegments_Perpandiculars::Locator::getClone () const
{ return new Locator(*this); }
bool AutoSegments_Perpandiculars::Locator::isValid () const
{ return not _perpandiculars.empty(); }
AutoSegmentHC* AutoSegments_Perpandiculars::getClone () const
{ return new AutoSegments_Perpandiculars(*this); }
AutoSegmentHL* AutoSegments_Perpandiculars::getLocator () const
{ return new Locator(_master,_flags); }
string AutoSegments_Perpandiculars::Locator::_getString () const
{
string s = "<" + _TName("AutoSegments_Perpandiculars::Locator") + ">";
return s;
}
string AutoSegments_Perpandiculars::_getString () const
{
string s = "<" + _TName("AutoSegments_Perpandiculars") + " "
+ getString(_master)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "AutoSegments_AnchorOnGCell".
AutoSegments_AnchorOnGCell::Locator::Locator ( GCell* fcell, Flags flags )
: AutoSegmentHL()
, _flags (flags)
, _itContact (fcell->getContacts().begin())
, _itEnd (fcell->getContacts().end())
, _hookLocator(NULL)
, _element (NULL)
{ progress(); }
AutoSegments_AnchorOnGCell::Locator::~Locator ()
{ if (_hookLocator) delete _hookLocator; }
AutoSegment* AutoSegments_AnchorOnGCell::Locator::getElement () const
{ return _element; }
AutoSegmentHL* AutoSegments_AnchorOnGCell::Locator::getClone () const
{ return new Locator(*this); }
bool AutoSegments_AnchorOnGCell::Locator::isValid () const
{ return _element != NULL; }
void AutoSegments_AnchorOnGCell::Locator::progress ()
{
cdebug_log(145,1) << "AutoSegments_AnchorOnGCell::Locator::progress()" << endl;
while ( true ) {
if (_hookLocator == NULL) {
if (_itContact == _itEnd) {
cdebug_log(145,0) << "No more AutoContacts" << endl;
cdebug_tabw(145,-1);
return;
}
cdebug_log(145,0) << *_itContact << endl;
_hookLocator = (*_itContact)->getBodyHook()->getSlaveHooks().getLocator();
_itContact++;
} else {
_hookLocator->progress();
}
while ( _hookLocator->isValid() ) {
cdebug_log(145,0) << _hookLocator->getElement() << endl;
Hook* hook = dynamic_cast<Segment::SourceHook*>(_hookLocator->getElement());
if (hook) {
if ( ((_flags & Flags::Source) and (dynamic_cast<Segment::SourceHook*>(hook)))
or ((_flags & Flags::Target) and (dynamic_cast<Segment::TargetHook*>(hook))) ) {
_element = Session::lookup( static_cast<Segment*>(hook->getComponent()) );
if (_element->isHorizontal()) {
if (_flags & Flags::Horizontal) { cdebug_tabw(145,-1); return; }
} else
if (_flags & Flags::Vertical) { cdebug_tabw(145,-1); return; }
}
}
_hookLocator->progress();
}
_hookLocator = NULL;
_element = NULL;
}
cdebug_tabw(145,-1);
}
string AutoSegments_AnchorOnGCell::Locator::_getString () const
{
string s = "<" + _TName("AutoSegments_AnchorOnGCell::Locator") + ">";
return s;
}
AutoSegmentHC* AutoSegments_AnchorOnGCell::getClone () const
{ return new AutoSegments_AnchorOnGCell(*this); }
AutoSegmentHL* AutoSegments_AnchorOnGCell::getLocator () const
{ return new Locator(_fcell,_flags); }
string AutoSegments_AnchorOnGCell::_getString () const
{
string s = "<" + _TName("AutoSegments_AnchorOnGCell") + " "
+ getString(_fcell)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegments_CachedOnContact".
AutoSegments_CachedOnContact::Locator::Locator ( AutoContact* sourceContact, Flags direction )
: AutoSegmentHL()
, _helper(new LocatorHelper(sourceContact,direction))
{ }
AutoSegments_CachedOnContact::Locator::~Locator ()
{ delete _helper; }
AutoSegment* AutoSegments_CachedOnContact::Locator::getElement () const
{ return _helper->getSegment(); }
AutoSegmentHL* AutoSegments_CachedOnContact::Locator::getClone () const
{ return new Locator(*this); }
bool AutoSegments_CachedOnContact::Locator::isValid () const
{ return _helper->isValid(); }
void AutoSegments_CachedOnContact::Locator::progress ()
{
cdebug_log(145,0) << "AutoSegments_CachedOnContact::Locator::progress()" << endl;
_helper->progress();
}
AutoSegmentHL* AutoSegments_CachedOnContact::getLocator () const
{ return new Locator(_sourceContact,_direction); }
AutoSegmentHC* AutoSegments_CachedOnContact::getClone () const
{ return new AutoSegments_CachedOnContact(*this); }
string AutoSegments_CachedOnContact::Locator::_getString () const
{
string s = "<" + _TName("AutoSegments_CachedOnContact::Locator") + ">";
return s;
}
string AutoSegments_CachedOnContact::_getString () const
{
string s = "<" + _TName("AutoSegments_CachedOnContact") + " "
+ getString(_sourceContact)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "AutoSegments_IsAccountable".
AutoSegmentHF* AutoSegments_IsAccountable::getClone () const
{ return new AutoSegments_IsAccountable(); }
bool AutoSegments_IsAccountable::accept ( AutoSegment* segment ) const
{ return segment->isCanonical(); }
string AutoSegments_IsAccountable::_getString () const
{ return "<AutoSegments_IsAccountable>"; }
// -------------------------------------------------------------------
// Class : "AutoSegments_InDirection".
AutoSegmentHF* AutoSegments_InDirection::getClone () const
{ return new AutoSegments_InDirection(_direction); }
bool AutoSegments_InDirection::accept ( AutoSegment* segment ) const
{
return ( segment->isHorizontal() and (_direction & Flags::Horizontal) )
or ( segment->isVertical () and (_direction & Flags::Vertical ) );
}
string AutoSegments_InDirection::_getString () const
{ return "<AutoSegments_InDirection>"; }
} // Anabatic namespace.

View File

@ -1,870 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./AutoVertical.cpp" |
// +-----------------------------------------------------------------+
#include <algorithm>
#include "hurricane/Bug.h"
#include "hurricane/Warning.h"
#include "hurricane/ViaLayer.h"
#include "hurricane/Vertical.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/Configuration.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/AutoHorizontal.h"
namespace Anabatic {
using std::min;
using std::max;
using std::abs;
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::ViaLayer;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoVertical".
Segment* AutoVertical::base () { return _vertical; }
Segment* AutoVertical::base () const { return _vertical; }
Vertical* AutoVertical::getVertical () { return _vertical; }
DbU::Unit AutoVertical::getSourceU () const { return _vertical->getSource()->getY(); }
DbU::Unit AutoVertical::getTargetU () const { return _vertical->getTarget()->getY(); }
DbU::Unit AutoVertical::getDuSource () const { return _vertical->getDySource(); }
DbU::Unit AutoVertical::getDuTarget () const { return _vertical->getDyTarget(); }
Interval AutoVertical::getSpanU () const { return Interval(_vertical->getSourceY(),_vertical->getTargetY()); }
string AutoVertical::_getTypeName () const { return "AutoVertical"; }
AutoVertical::AutoVertical ( Vertical* vertical )
: AutoSegment(vertical)
, _vertical(vertical)
{
cdebug_log(145,0) << "CTOR AutoVertical " << this << endl;
cdebug_log(145,0) << " over " << vertical << endl;
}
void AutoVertical::_postCreate ()
{
AutoSegment::_postCreate ();
AutoContact* source = getAutoSource();
if (source->isTerminal()) source->setX( _vertical->getX() );
AutoContact* target = getAutoTarget();
if (target->isTerminal()) target->setX( _vertical->getX() );
_gcell = source->getGCell();
setOptimalMax( getGCell()->getXMax() );
resetNativeConstraints( getGCell()->getXMin(), getGCell()->getConstraintXMax() );
cdebug_log(145,0) << "Source in " << getGCell() << endl;
cdebug_log(145,0) << "Target in " << target->getGCell() << endl;
if (getGCell() != target->getGCell()) {
setFlags( SegGlobal );
vector<GCell*> gcells;
getGCells( gcells );
for ( GCell* gcell : gcells ) {
if ( (gcell != getGCell()) and (gcell != target->getGCell()) )
gcell->addVSegment( this );
mergeNativeMin( gcell->getXMin() );
mergeNativeMax( gcell->getConstraintXMax() );
}
}
}
void AutoVertical::_preDestroy ()
{
cdebug_log(149,1) << "AutoVertical::_preDestroy() - <id:" << getId() << "> " << endl;
cdebug_log(149,0) << _getString() << endl;
if ( not Session::doDestroyTool() ) {
vector<GCell*> gcells;
getGCells( gcells );
for ( GCell* gcell : gcells ) gcell->removeVSegment( this );
}
AutoSegment::_preDestroy ();
cdebug_tabw(145,-1);
}
AutoVertical::~AutoVertical ()
{
if ( Session::doDestroyBaseSegment() and not Session::doDestroyTool() ) {
cdebug_log(149,0) << "~AutoVertical() - " << endl;
_vertical->destroy ();
}
}
void AutoVertical::setDuSource ( DbU::Unit du )
{
_vertical->setDySource(du);
if (abs(du) > getPitch())
cerr << Warning( "AutoVertical::setDuSource(): Suspiciously big du=%s (should not exceed routing pitch %s)\n"
" On %s"
, DbU::getValueString(du).c_str()
, DbU::getValueString(getPitch()).c_str()
, getString(this).c_str() ) << endl;
}
void AutoVertical::setDuTarget ( DbU::Unit du )
{
_vertical->setDyTarget(du);
if (abs(du) > getPitch())
cerr << Warning( "AutoVertical::setDuTarget(): Suspiciously big du=%s (should not exceed routing pitch %s)\n"
" On %s"
, DbU::getValueString(du).c_str()
, DbU::getValueString(getPitch()).c_str()
, getString(this).c_str() ) << endl;
}
Interval AutoVertical::getSourceConstraints ( Flags flags ) const
{
if (flags & Flags::NativeConstraints) {
Box nativeBox ( getAutoSource()->getNativeConstraintBox() );
return Interval ( nativeBox.getXMin(), nativeBox.getXMax() );
}
return Interval ( getAutoSource()->getCBXMin(), getAutoSource()->getCBXMax() );
}
Interval AutoVertical::getTargetConstraints ( Flags flags ) const
{
if (flags & Flags::NativeConstraints) {
Box nativeBox ( getAutoTarget()->getNativeConstraintBox() );
return Interval ( nativeBox.getXMin(), nativeBox.getXMax() );
}
return Interval ( getAutoTarget()->getCBXMin(), getAutoTarget()->getCBXMax() );
}
bool AutoVertical::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const
{
cdebug_log(149,1) << "getConstraints() " << this << endl;
constraintMin = getNativeMin();
constraintMax = getNativeMax();
cdebug_log(149,0) << "Native constraints: ["
<< DbU::getValueString(constraintMin) << ":"
<< DbU::getValueString(constraintMax) << "]"
<< endl;
constraintMin = std::max ( constraintMin, getAutoSource()->getCBXMin() );
constraintMax = std::min ( constraintMax, getAutoSource()->getCBXMax() );
cdebug_log(149,0) << "Merge with source constraints: ["
<< DbU::getValueString(getAutoSource()->getCBXMin()) << ":"
<< DbU::getValueString(getAutoSource()->getCBXMax()) << "]"
<< endl;
constraintMin = std::max ( constraintMin, getAutoTarget()->getCBXMin() );
constraintMax = std::min ( constraintMax, getAutoTarget()->getCBXMax() );
cdebug_log(149,0) << "Merge with target constraints: ["
<< DbU::getValueString(getAutoTarget()->getCBXMin()) << ":"
<< DbU::getValueString(getAutoTarget()->getCBXMax()) << "]"
<< endl;
Interval userConstraints = getUserConstraints();
if (not userConstraints.isEmpty()) {
constraintMin = max ( constraintMin, userConstraints.getVMin() );
constraintMax = min ( constraintMax, userConstraints.getVMax() );
cdebug_log(149,0) << "Merge with user constraints: ["
<< DbU::getValueString(userConstraints.getVMin()) << ":"
<< DbU::getValueString(userConstraints.getVMax()) << "]"
<< endl;
} else
cdebug_log(155,0) << "Empty user constraints" << endl;
cdebug_log(149,0) << "Resulting constraints: ["
<< DbU::getValueString(constraintMin) << ":"
<< DbU::getValueString(constraintMax) << "]"
<< endl;
if (constraintMin > constraintMax)
cerr << Error( "AutoVertical::getConstraints(): Invalid interval [%s : %s]\n"
" on %s"
, DbU::getValueString(constraintMin).c_str()
, DbU::getValueString(constraintMax).c_str()
, getString(this).c_str()
) << endl;
cdebug_tabw(149,-1);
return true;
}
Flags AutoVertical::getDirection () const
{ return Flags::Vertical; }
bool AutoVertical::getGCells ( vector<GCell*>& gcells ) const
{
vector<GCell*>().swap( gcells );
bool success = true;
DbU::Unit xprobe = getX();
GCell* gcell = getAutoSource()->getGCell();
GCell* end = getAutoTarget()->getGCell();
cdebug_log(144,0) << "xprobe: " << DbU::getValueString(xprobe) << endl;
if (gcell->getYMin() > end->getYMin()) std::swap( gcell, end );
if (xprobe == gcell->getConstraintXMax()) xprobe--;
gcells.push_back( gcell );
while ( gcell != end ) {
gcell = gcell->getNorth( xprobe );
if (not gcell) {
success = false;
if (not isCreated()) {
cerr << Error( "AutoVertical::getGCells() : NULL GCell under %s\n"
" begin:%s\n"
" end: %s"
, getString(this).c_str()
, getString(getAutoSource()->getGCell()).c_str()
, getString(getAutoTarget()->getGCell()).c_str()
) << endl;
}
break;
}
gcells.push_back( gcell );
}
return success;
}
bool AutoVertical::_canSlacken () const
{
cdebug_tabw(149,-1);
if (getAutoSource()->isOnPin() or getAutoTarget()->isOnPin()) { cdebug_tabw(149,-1); return false; }
Interval sourceSide = getAutoSource()->getGCell()->getSide( Flags::Horizontal );
Interval targetSide = getAutoTarget()->getGCell()->getSide( Flags::Horizontal );
Interval sourceConstraints = Interval(getAutoSource()->getCBXMin(),getAutoSource()->getCBXMax());
Interval targetConstraints = Interval(getAutoTarget()->getCBXMin(),getAutoTarget()->getCBXMax());
bool sourceGoStraight = getAutoSource()->getGCell()->isGoStraight();
bool targetGoStraight = getAutoTarget()->getGCell()->isGoStraight();
// Expand by a tiny amount for the "contains" to work for sure.
sourceConstraints.inflate( 1 );
targetConstraints.inflate( 1 );
if (not sourceGoStraight and not sourceConstraints.contains(sourceSide)) { cdebug_tabw(149,-1); return true; }
if (not targetGoStraight and not targetConstraints.contains(targetSide)) { cdebug_tabw(149,-1); return true; }
cdebug_tabw(149,-1);
return false;
}
bool AutoVertical::_slacken ( Flags flags )
{
cdebug_log(149,1) << "AutoVertical::_slacken() " << this << endl;
if (not isDrag()) {
if ( not isStrongTerminal()
or (not (_flags & (SegGlobal|SegWeakGlobal)) and (getAnchoredLength() < getPitch()*5)) )
{ cdebug_tabw(149,-1); return false; }
}
cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
cdebug_log(149,0) << "test:" << (getAnchoredLength() < getPitch()*5) << endl;
cdebug_log(149,0) << "length:" << DbU::getValueString(getAnchoredLength()) << endl;
bool success = false;
bool sourceSlackened = false;
bool targetSlackened = false;
bool halfSlackened = false;
int lowSlack = (flags & Flags::HalfSlacken) ? 3 : 10;
AutoContact* source = getAutoSource();
AutoSegment* parallel = this;
if (source->isTerminal()) {
Interval constraints = source->getUConstraints (Flags::Horizontal|Flags::NoGCellShrink);
Interval nativeConstraints = source->getNativeUConstraints(Flags::Horizontal|Flags::NoGCellShrink);
int slack = constraints.getSize() / getPitch();
int nativeSlack = nativeConstraints.getSize() / getPitch();
// Ugly: GCell's track number is hardwired.
if ((slack < lowSlack) or (nativeSlack - slack < 3)) {
_makeDogleg( source->getGCell(), Flags::NoFlags );
sourceSlackened = true;
} else if (slack < 10) {
halfSlackened = true;
}
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
if (sourceSlackened and (doglegs.size() >= 2)) {
cdebug_log(149,0) << "AutoVertical::_slacken(): Source @" << DbU::getValueString(getSourcePosition()) << endl;
doglegs[doglegs.size()-2]->_setAxis( getSourcePosition() );
success = true;
parallel = doglegs[ doglegs.size()-1 ];
}
}
AutoContact* target = NULL;
if (parallel) {
target = parallel->getAutoTarget();
} else {
target = getAutoTarget();
}
if (target->isTerminal()) {
Interval constraints = target->getUConstraints (Flags::Horizontal|Flags::NoGCellShrink);
Interval nativeConstraints = target->getNativeUConstraints(Flags::Horizontal|Flags::NoGCellShrink);
int slack = constraints.getSize() / getPitch();
int nativeSlack = nativeConstraints.getSize() / getPitch();
// Ugly: GCell's track number is hardwired.
if ((slack < lowSlack) or (nativeSlack - slack < 3)) {
_makeDogleg( target->getGCell(), Flags::NoFlags );
targetSlackened = true;
} else if (slack < 10) {
halfSlackened = true;
}
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
if (targetSlackened and (doglegs.size() >= 2)) {
cdebug_log(149,0) << "AutoVertical::_slacken(): Source @" << DbU::getValueString(getTargetPosition()) << endl;
doglegs[doglegs.size()-2]->_setAxis( getTargetPosition() );
success = true;
}
}
if (sourceSlackened and targetSlackened) {
setFlags ( SegSlackened );
unsetFlags( SegHalfSlackened );
} else {
if (sourceSlackened or targetSlackened) {
if (halfSlackened) {
setFlags( SegHalfSlackened );
} else {
setFlags ( SegSlackened );
unsetFlags( SegHalfSlackened );
}
}
}
cdebug_tabw(149,-1);
return success;
}
void AutoVertical::_setAxis ( DbU::Unit axis )
{
setFlags( SegAxisSet );
if (_vertical->getX() == axis) return;
cdebug_log(144,0) << "_setAxis() @X " << DbU::getValueString(axis) << " " << this << endl;
_vertical->setX( axis );
invalidate();
AutoContact* anchor = getAutoSource();
anchor->invalidate();
if (anchor->isTerminal()) anchor->setX( axis );
anchor = getAutoTarget();
anchor->invalidate();
if (anchor->isTerminal()) anchor->setX( axis );
}
void AutoVertical::updateOrient ()
{
if (_vertical->getTargetY() < _vertical->getSourceY()) {
cdebug_log(145,0) << "updateOrient() " << this << " (before S/T swap)" << endl;
_vertical->invert();
unsigned int spinFlags = _flags & SegDepthSpin;
unsetFlags( SegDepthSpin );
if (spinFlags & SegSourceTop ) setFlags( SegTargetTop );
if (spinFlags & SegSourceBottom) setFlags( SegTargetBottom );
if (spinFlags & SegTargetTop ) setFlags( SegSourceTop );
if (spinFlags & SegTargetBottom) setFlags( SegSourceBottom );
unsigned int invalidatedFlags = _flags & (SegInvalidatedSource|SegInvalidatedTarget);
unsetFlags( SegInvalidatedSource|SegInvalidatedTarget );
if (invalidatedFlags & SegInvalidatedSource) setFlags( SegInvalidatedTarget );
if (invalidatedFlags & SegInvalidatedTarget) setFlags( SegInvalidatedSource );
unsigned int terminalFlags = _flags & SegStrongTerminal;
unsetFlags( SegStrongTerminal );
if (terminalFlags & SegSourceTerminal) setFlags( SegTargetTerminal );
if (terminalFlags & SegTargetTerminal) setFlags( SegSourceTerminal );
}
}
void AutoVertical::updatePositions ()
{
_sourcePosition = getSourceU() - getExtensionCap(Flags::Source);
_targetPosition = getTargetU() + getExtensionCap(Flags::Target);
}
void AutoVertical::updateNativeConstraints ()
{
vector<GCell*> gcells;
getGCells( gcells );
resetNativeConstraints( gcells[0]->getXMin(), gcells[0]->getConstraintXMax() );
for ( GCell* gcell : gcells ) {
mergeNativeMin( gcell->getXMin() );
mergeNativeMax( gcell->getConstraintXMax() );
}
}
bool AutoVertical::checkPositions () const
{
bool coherency = true;
DbU::Unit sourcePosition = _vertical->getSource()->getY() - getExtensionCap(Flags::Source);
DbU::Unit targetPosition = _vertical->getTarget()->getY() + getExtensionCap(Flags::Target);
if ( _sourcePosition != sourcePosition ) {
cerr << Error ( "%s\n Source position incoherency: "
"Shadow: %s, real: %s."
, _getString().c_str()
, DbU::getValueString(_sourcePosition).c_str()
, DbU::getValueString( sourcePosition).c_str()
) << endl;
coherency = false;
}
if ( _targetPosition != targetPosition ) {
cerr << Error ( "%s\n Target position incoherency: "
"Shadow: %s, real: %s."
, _getString().c_str()
, DbU::getValueString(_targetPosition).c_str()
, DbU::getValueString( targetPosition).c_str()
) << endl;
coherency = false;
}
return coherency;
}
bool AutoVertical::checkConstraints () const
{
Interval sourceConstraints = Interval(getAutoSource()->getCBXMin(),getAutoSource()->getCBXMax());
Interval targetConstraints = Interval(getAutoTarget()->getCBXMin(),getAutoTarget()->getCBXMax());
if (not sourceConstraints.intersect(targetConstraints)) {
cerr << Error ( "%s\n Constraints incoherency:\n"
" S:%s %s\n"
" T:%s %s"
, _getString().c_str()
, getString(sourceConstraints).c_str()
, getString(getAutoSource()).c_str()
, getString(targetConstraints).c_str()
, getString(getAutoTarget()).c_str()
) << endl;
return false;
}
return true;
}
bool AutoVertical::canMoveULeft ( float reserve ) const
{
#if THIS_IS_DISABLED
if (not isGlobal()) return false;
if (not getAutoSource()->isTurn() or not getAutoTarget()->isTurn()) return false;
if (not getAutoSource()->getGCell()->getLeft()) return false;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
AutoSegment* perpandiculars[2] = { autoSource->getSegment(0), autoTarget->getSegment(0) };
if ( ( (not perpandiculars[0]->isGlobal()) or (perpandiculars[0]->getAutoSource() == autoSource) )
and ( (not perpandiculars[1]->isGlobal()) or (perpandiculars[1]->getAutoSource() == autoTarget) ) )
return false;
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
unsigned int depth = Session::getRoutingGauge()->getLayerDepth( getLayer() );
float currMaxDensity = 0.0;
float leftMaxDensity = 0.0;
for ( GCell* gcell=begin ; gcell and gcell!=end ; gcell=gcell->getUp() ) {
if (currMaxDensity < gcell->getWDensity(depth)) currMaxDensity = gcell->getWDensity( depth );
}
begin = begin->getLeft();
end = end ->getLeft();
for ( GCell* gcell=begin ; gcell and gcell!=end ; gcell=gcell->getUp() ) {
if (leftMaxDensity < gcell->getWDensity(depth)) leftMaxDensity = gcell->getWDensity( depth );
}
return (leftMaxDensity + reserve < currMaxDensity);
#endif
return false;
}
bool AutoVertical::canMoveURight ( float reserve ) const
{
#if THIS_IS_DISABLED
if (not isGlobal()) return false;
if (not getAutoSource()->isTurn() or not getAutoTarget()->isTurn()) return false;
if (not getAutoSource()->getGCell()->getRight()) return false;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
AutoSegment* perpandiculars[2] = { autoSource->getSegment(0), autoTarget->getSegment(0) };
if ( ( (not perpandiculars[0]->isGlobal()) or (perpandiculars[0]->getAutoTarget() == autoSource) )
and ( (not perpandiculars[1]->isGlobal()) or (perpandiculars[1]->getAutoTarget() == autoTarget) ) )
return false;
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
unsigned int depth = Session::getRoutingGauge()->getLayerDepth( getLayer() );
float currMaxDensity = 0.0;
float leftMaxDensity = 0.0;
for ( GCell* gcell=begin ; gcell and gcell!=end ; gcell=gcell->getUp() ) {
if (currMaxDensity < gcell->getWDensity(depth)) currMaxDensity = gcell->getWDensity( depth );
}
begin = begin->getRight();
end = end ->getRight();
for ( GCell* gcell=begin ; gcell and gcell!=end ; gcell=gcell->getUp() ) {
if (leftMaxDensity < gcell->getWDensity(depth)) leftMaxDensity = gcell->getWDensity( depth );
}
return (leftMaxDensity + reserve < currMaxDensity);
#endif
return false;
}
bool AutoVertical::moveULeft ()
{
#if THIS_IS_DISABLED
if (not getAutoSource()->isTurn() or not getAutoTarget()->isTurn()) return false;
if (not getAutoSource()->getGCell()->getLeft()) return false;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
AutoSegment* perpandicular = autoSource->getSegment(0);
if (perpandicular->isLocal()) {
perpandicular->setFlags( Anabatic::SegGlobal );
} else {
if (perpandicular->getAutoSource() == autoSource) {
begin->addHSegment( perpandicular );
} else {
if (begin->getLeft() == perpandicular->getAutoSource()->getGCell()) {
perpandicular->unsetFlags( Anabatic::SegGlobal );
} else
begin->getLeft()->removeHSegment( perpandicular );
}
}
perpandicular = autoTarget->getSegment(0);
if (perpandicular->isLocal()) {
perpandicular->setFlags( Anabatic::SegGlobal );
} else {
if (perpandicular->getAutoSource() == autoTarget) {
end->addHSegment( perpandicular );
} else {
if (end->getLeft() == perpandicular->getAutoSource()->getGCell()) {
perpandicular->unsetFlags( Anabatic::SegGlobal );
} else
end->getLeft()->removeHSegment( perpandicular );
}
}
if (begin != end) {
for ( GCell* gcell=begin->getUp() ; gcell and gcell!=end ; gcell=gcell->getUp() )
gcell->removeVSegment( this );
}
begin = begin->getLeft();
end = end ->getLeft();
autoSource->setGCell( begin );
autoTarget->setGCell( end );
if (begin != end) {
for ( GCell* gcell=begin->getUp() ; gcell and gcell!=end ; gcell=gcell->getUp() )
gcell->addVSegment( this );
}
DbU::Unit x = begin->getSide( Flags::Horizontal ).getVMax();
setAxis( x );
return true;
#endif
return false;
}
bool AutoVertical::moveURight ()
{
#if THIS_IS_DISABLED
cdebug_log(149,0) << "AutoVertical::moveURight()" << endl;
if (not getAutoSource()->isTurn() or not getAutoTarget()->isTurn()) return true;
if (not getAutoSource()->getGCell()->getRight()) return true;
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
AutoSegment* perpandicular = autoSource->getSegment(0);
if (perpandicular->isLocal()) {
perpandicular->setFlags( Anabatic::SegGlobal );
} else {
if (perpandicular->getAutoTarget() == autoSource) {
begin->addHSegment( perpandicular );
} else {
if (begin->getRight() == perpandicular->getAutoTarget()->getGCell()) {
perpandicular->unsetFlags( Anabatic::SegGlobal );
} else
begin->getRight()->removeHSegment( perpandicular );
}
}
perpandicular = autoTarget->getSegment(0);
if (perpandicular->isLocal()) {
perpandicular->setFlags( Anabatic::SegGlobal );
} else {
if (perpandicular->getAutoTarget() == autoTarget) {
end->addHSegment( perpandicular );
} else {
if (end->getRight() == perpandicular->getAutoTarget()->getGCell()) {
perpandicular->unsetFlags( Anabatic::SegGlobal );
} else
end->getRight()->removeHSegment( perpandicular );
}
}
if (begin != end) {
for ( GCell* gcell=begin->getUp() ; gcell and gcell!=end ; gcell=gcell->getUp() )
gcell->removeVSegment( this );
}
begin = begin->getRight();
end = end ->getRight();
autoSource->setGCell( begin );
autoTarget->setGCell( end );
if (begin != end) {
for ( GCell* gcell=begin->getUp() ; gcell and gcell!=end ; gcell=gcell->getUp() )
gcell->addVSegment( this );
}
DbU::Unit x = begin->getSide( Flags::Horizontal ).getVMin();
setAxis( x );
cdebug_log(149,0) << "Moved to axis: " << DbU::getValueString(x) << endl;
return true;
#endif
return false;
}
Flags AutoVertical::_makeDogleg ( GCell* doglegGCell, Flags flags )
{
cdebug_log(149,0) << "AutoVertical::_makeDogleg(GCell*)" << endl;
//Session::doglegReset();
AutoContact* autoSource = getAutoSource();
AutoContact* autoTarget = getAutoTarget();
GCell* begin = autoSource->getGCell();
GCell* end = autoTarget->getGCell();
if (not autoSource->canDrag()) unsetFlags( SegDrag );
DbU::Unit doglegAxis = (doglegGCell->getYMax() + doglegGCell->getYMin()) / 2;
if (isLocal())
doglegAxis = (getSourceY() + getTargetY()) / 2;
if (doglegGCell == begin) unsetFlags( SegGlobal );
if (doglegGCell != end) {
GCell* gcell = doglegGCell;
do {
if (gcell != begin)
gcell->removeVSegment( this );
gcell = gcell->getNorth( getNativeMin() );
} while ( gcell and (gcell != end) );
}
size_t depth = Session::getRoutingGauge()->getLayerDepth ( _vertical->getLayer() );
bool upLayer = true;
if (Session::getRoutingGauge()->isTwoMetals()) {
upLayer = (Session::getRoutingGauge()->isVH());
} else if (Session::getRoutingGauge()->isVH()) {
upLayer = (depth < 2);
} else {
upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
}
size_t doglegDepth = depth + ((upLayer)?1:-1);
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer ( depth + ((upLayer)?0:-1) );
Session::dogleg( this );
targetDetach();
invalidate( Flags::Topology );
autoTarget->invalidate( Flags::Topology );
AutoContact* dlContact1 = AutoContactTurn::create( doglegGCell, _vertical->getNet(), contactLayer );
cdebug_log(149,0) << dlContact1 << endl;
AutoContact* dlContact2 = AutoContactTurn::create( doglegGCell, _vertical->getNet(), contactLayer );
cdebug_log(149,0) << dlContact2 << endl;
AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Horizontal );
cdebug_log(149,0) << segment1 << endl;
segment1->setLayer( doglegDepth );
segment1->_setAxis( doglegAxis );
segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned );
cdebug_log(149,0) << "New " << dlContact1->base() << "." << endl;
cdebug_log(149,0) << "New " << dlContact2->base() << "." << endl;
Session::dogleg( segment1 );
targetAttach( dlContact1 );
AutoSegment* segment2 = AutoVertical::create ( dlContact2, autoTarget, Flags::Vertical );
autoTarget->cacheAttach( segment2 );
segment2->setLayer( depth );
segment2->_setAxis( getX() );
segment2->setFlags( (isSlackened()?SegSlackened:0) );
Session::dogleg( segment2 );
if (autoSource->isTerminal() and autoTarget->isTerminal()) {
dlContact1->setFlags ( CntWeakTerminal );
dlContact2->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
} else if (autoSource->isTerminal()) {
autoTarget->unsetFlags( CntWeakTerminal );
dlContact1->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
} else if (autoTarget->isTerminal()) {
unsetFlags( SegTargetTerminal );
setFlags( SegWeakTerminal1 );
autoSource->unsetFlags( CntWeakTerminal );
dlContact2->setFlags ( CntWeakTerminal );
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
} else if (isWeakTerminal()) {
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 );
}
// if (isSourceTerminal()) {
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegWeakTerminal1 );
// autoTarget->unsetFlags( CntWeakTerminal );
// dlContact1->setFlags ( CntWeakTerminal );
// if (autoTarget->getGCell() == doglegGCell)
// dlContact1->migrateConstraintBox( autoTarget );
// } else if (isTargetTerminal()) {
// unsetFlags( SegTargetTerminal );
// setFlags( SegWeakTerminal1 );
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegTargetTerminal );
// autoSource->unsetFlags( CntWeakTerminal );
// dlContact2->setFlags ( CntWeakTerminal );
// if (autoSource->getGCell() == doglegGCell)
// dlContact2->migrateConstraintBox( autoSource );
// } else if (isWeakTerminal()) {
// segment1->setFlags( SegWeakTerminal1 );
// segment2->setFlags( SegWeakTerminal1 );
// }
if (isAnalog()) {
segment1->setFlags( SegAnalog );
segment2->setFlags( SegAnalog );
}
if (isNoMoveUp()) {
segment1->setFlags( SegNoMoveUp );
segment2->setFlags( SegNoMoveUp );
}
cdebug_log(149,0) << "Session::dogleg[x+1] perpand: " << segment1 << endl;
cdebug_log(149,0) << "Session::dogleg[x+2] new paral: " << segment2 << endl;
cdebug_log(149,0) << "Session::dogleg[x+0] original: " << this << endl;
dlContact1->updateCache();
dlContact2->updateCache();
//autoTarget->updateCache();
segment2->canonize( flags );
if (not isCanonical()) canonize( flags );
updateNativeConstraints();
segment2->updateNativeConstraints();
if ( isLocal()) autoSource->setFlags( AutoContactFlag::CntHDogleg );
if (segment2->isLocal()) autoTarget->setFlags( AutoContactFlag::CntHDogleg );
if (autoTarget->canDrag() and not autoSource->canDrag()) {
if (not autoTarget->getGCell()->isDevice() and (segment1->getGCell() == autoTarget->getGCell())) {
Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Vertical);
segment1->mergeUserConstraints( dragConstraints );
cdebug_log(149,0) << "Perpandicular has drag constraints: " << dragConstraints << endl;
}
}
return (upLayer) ? Flags::AboveLayer : Flags::BelowLayer;
}
string AutoVertical::_getString () const
{
string s = AutoSegment::_getString();
return s;
}
Record* AutoVertical::_getRecord () const
{
Record* record = AutoSegment::_getRecord ();
record->add ( getSlot ( "_vertical", _vertical ) );
return record;
}
} // End of Anabatic namespace.

View File

@ -1,111 +0,0 @@
# -*- explicit-buffer-name: "CMakeLists.txt<anabatic/src>" -*-
if ( CHECK_DETERMINISM )
add_definitions ( -DCHECK_DETERMINISM )
endif ( CHECK_DETERMINISM )
include_directories( ${ANABATIC_SOURCE_DIR}/src
${CORIOLIS_INCLUDE_DIR}
${ETESIAN_INCLUDE_DIR}
${HURRICANE_INCLUDE_DIR}
${CONFIGURATION_INCLUDE_DIR}
${FLUTE_INCLUDE_DIR}
${Boost_INCLUDE_DIRS}
${QtX_INCLUDE_DIRS}
${Python_INCLUDE_DIRS}
)
set( includes anabatic/Constants.h
anabatic/Configuration.h
anabatic/Matrix.h
anabatic/EdgeCapacity.h
anabatic/Edge.h anabatic/Edges.h
anabatic/GCell.h #anabatic/GCells.h
anabatic/AnabaticEngine.h
anabatic/Dijkstra.h
anabatic/AutoContact.h
anabatic/AutoContactTerminal.h
anabatic/AutoContactTurn.h
anabatic/AutoContactHTee.h
anabatic/AutoContactVTee.h
anabatic/AutoSegment.h anabatic/AutoSegments.h
anabatic/AutoHorizontal.h
anabatic/AutoVertical.h
anabatic/Session.h
anabatic/NetBuilder.h
anabatic/NetBuilderM2.h
anabatic/NetBuilderHV.h
anabatic/NetBuilderVH.h
anabatic/NetBuilderHybridVH.h
anabatic/ChipTools.h
)
set( pyIncludes anabatic/PyStyleFlags.h )
set( cpps Constants.cpp
Configuration.cpp
Matrix.cpp
EdgeCapacity.cpp
Edge.cpp
Edges.cpp
GCell.cpp
Dijkstra.cpp
AutoContact.cpp
AutoContactTerminal.cpp
AutoContactTurn.cpp
AutoContactHTee.cpp
AutoContactVTee.cpp
AutoSegment.cpp AutoSegments.cpp
AutoHorizontal.cpp
AutoVertical.cpp
Session.cpp
NetConstraints.cpp
NetOptimals.cpp
NetBuilder.cpp
NetBuilderM2.cpp
NetBuilderHV.cpp
NetBuilderVH.cpp
NetBuilderHybridVH.cpp
ChipTools.cpp
LayerAssign.cpp
AntennaProtect.cpp
PreRouteds.cpp
AnabaticEngine.cpp
)
set( pyCpps PyStyleFlags.cpp
PyAnabatic.cpp
)
set( depLibs ${ETESIAN_LIBRARIES}
${CORIOLIS_PYTHON_LIBRARIES}
${CORIOLIS_LIBRARIES}
${HURRICANE_PYTHON_LIBRARIES}
${HURRICANE_GRAPHICAL_LIBRARIES}
${HURRICANE_LIBRARIES}
${CONFIGURATION_LIBRARY}
${CIF_LIBRARY}
${AGDS_LIBRARY}
${COLOQUINTE_LIBRARIES}
${FLUTE_LIBRARIES}
${LEFDEF_LIBRARIES}
${OA_LIBRARIES}
${QtX_LIBRARIES}
${Boost_LIBRARIES}
${LIBXML2_LIBRARIES}
${Python3_LIBRARIES}
-lutil
)
add_library( anabatic ${cpps} )
set_target_properties( anabatic PROPERTIES VERSION 1.0 SOVERSION 1 )
target_link_libraries( anabatic ${depLibs} )
add_python_module( "${pyCpps}"
"${pyIncludes}"
"pyanabatic;1.0;1"
Anabatic
"anabatic;${depLibs}"
include/coriolis2/anabatic
)
install( TARGETS anabatic DESTINATION lib${LIB_SUFFIX} )
install( FILES ${includes} DESTINATION include/coriolis2/anabatic )

View File

@ -1,191 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./ChipTools.cpp" |
// +-----------------------------------------------------------------+
#include <string>
#include <sstream>
#include "hurricane/Warning.h"
#include "hurricane/Bug.h"
#include "hurricane/Torus.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/RoutingPad.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/AllianceFramework.h"
#include "anabatic/Session.h"
#include "anabatic/AutoContact.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/AutoHorizontal.h"
#include "anabatic/AutoVertical.h"
#include "anabatic/GCell.h"
#include "anabatic/AnabaticEngine.h"
namespace {
using namespace std;
using namespace CRL;
using namespace Hurricane;
using namespace Anabatic;
enum SegmentType { LocalSegments=0x10, GlobalSegments=0x20 };
bool isChip ( Cell* cell, Instance*& core, Cell*& referencePad )
{
AllianceFramework* af = AllianceFramework::get();
int pads = 0;
int cores = 0;
core = NULL;
referencePad = NULL;
forEach ( Instance*, iinstance, cell->getInstances() ) {
if ( af->isPad(iinstance->getMasterCell()) ) {
++pads;
if (not referencePad)
referencePad = iinstance->getMasterCell();
} else {
++cores;
core = *iinstance;
}
}
return (pads > 0) and (cores == 1);
}
void reselectPadRp ( Cell* cell )
{
AllianceFramework* af = AllianceFramework::get();
forEach ( Net*, inet, cell->getNets() ) {
if ( inet->getType() == Net::Type::GROUND ) continue;
if ( inet->getType() == Net::Type::POWER ) continue;
if ( inet->getType() == Net::Type::CLOCK ) continue;
forEach ( RoutingPad*, irp, inet->getRoutingPads() ) {
Instance* instance = irp->getOccurrence().getPath().getTailInstance();
if ( instance ) {
Cell* masterCell = instance->getMasterCell();
if ( af->isPad(masterCell) )
irp->setOnBestComponent(RoutingPad::LowestLayer);
}
} // RoutingPad*.
} // Net*.
}
} // End of anonymous namespace.
namespace Anabatic {
void AnabaticEngine::chipPrep ()
{
if (isChip()) {
reselectPadRp( getCell() );
}
}
ChipTools::ChipTools ( Cell* cell )
: _cell (cell)
, _core (NULL)
, _referencePad (NULL)
, _isChip (false)
, _chipBb (cell->getBoundingBox())
, _leftPadsBb ()
, _rightPadsBb ()
, _topPadsBb ()
, _bottomPadsBb ()
, _chipCorona ()
, _padWidth (0)
, _padHeight (0)
, _padPowerWidth(0)
, _padClockWidth(0)
{
_isChip = ::isChip( _cell, _core, _referencePad );
if (_isChip) {
_padHeight = _referencePad->getAbutmentBox().getHeight();
_padWidth = _referencePad->getAbutmentBox().getWidth();
Box outer = _cell->getBoundingBox().inflate ( -_padHeight );
_chipCorona = Torus ( outer, _core->getBoundingBox() );
_leftPadsBb = Box ( _chipBb.getXMin() , _chipBb.getYMin(), _chipCorona.getOuterBox().getXMin(), _chipBb.getYMax() );
_rightPadsBb = Box ( _chipCorona.getOuterBox().getXMax(), _chipBb.getYMin(), _chipBb.getXMax(), _chipBb.getYMax() );
_bottomPadsBb = Box ( _chipBb.getXMin() , _chipBb.getYMin(), _chipBb.getXMax(), _chipCorona.getOuterBox().getYMin() );
_topPadsBb = Box ( _chipBb.getXMin(), _chipCorona.getOuterBox().getYMax(), _chipBb.getXMax(), _chipBb.getYMax() );
Layer* metal3 = DataBase::getDB()->getTechnology()->getLayer( "METAL3" );
Net* net = _referencePad->getNet( "ck" );
forEach ( Horizontal*, ihorizontal, net->getHorizontals() ) {
if (ihorizontal->getLayer() == metal3) {
_padClockWidth = ihorizontal->getWidth();
break;
}
}
net = _referencePad->getNet( "vddi" );
forEach ( Horizontal*, ihorizontal, net->getHorizontals() ) {
if (ihorizontal->getLayer() == metal3) {
_padPowerWidth = ihorizontal->getWidth();
break;
}
}
cmess1 << " o Design is a complete chip." << endl;
cmess1 << " - Core: <" << _core->getName() << ">/<"
<< _core->getMasterCell()->getName() << ">." << endl;
cmess1 << " - Reference pad: <" << _referencePad->getName() << ">" << endl;
cmess1 << " - Corona: " << _chipCorona << "." << endl;
} else {
_chipCorona = Torus ( _cell->getBoundingBox(), _cell->getBoundingBox() );
}
}
string ChipTools::_getString () const
{
ostringstream s;
s << "<" << _getTypeName() << " " << _cell->getName()
<< " core:" << getString(((_core) ? _core->getName() : "NULL"))
<< ">";
return s.str();
}
Record* ChipTools::_getRecord () const
{
Record* record = new Record ( _getString() );
record->add ( getSlot ( "_cell" , _cell ) );
record->add ( getSlot ( "_core" , _core ) );
record->add ( getSlot ( "_referencePad", _referencePad ) );
record->add ( getSlot ( "_isChip" , &_isChip ) );
record->add ( getSlot ( "_chipBb" , &_chipBb ) );
record->add ( getSlot ( "_leftPadsBb" , &_leftPadsBb ) );
record->add ( getSlot ( "_rightPadsBb" , &_rightPadsBb ) );
record->add ( getSlot ( "_topPadsBb" , &_topPadsBb ) );
record->add ( getSlot ( "_bottomPadsBb", &_bottomPadsBb ) );
record->add ( getSlot ( "_chipCorona" , &_chipCorona ) );
return record;
}
} // End of Anabatic namespace.

View File

@ -1,629 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "Configuration.cpp<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2016-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Configuration.cpp" |
// +-----------------------------------------------------------------+
#include <iostream>
#include <iomanip>
#include <vector>
#include "hurricane/configuration/Configuration.h"
#include "hurricane/Warning.h"
#include "hurricane/Error.h"
#include "hurricane/Technology.h"
#include "hurricane/DataBase.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Pin.h"
#include "hurricane/Pad.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/Cell.h"
#include "crlcore/Utilities.h"
#include "crlcore/CellGauge.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/RoutingLayerGauge.h"
#include "crlcore/AllianceFramework.h"
#include "anabatic/Configuration.h"
#include "anabatic/GCell.h"
namespace Anabatic {
using std::cout;
using std::cerr;
using std::endl;
using std::setprecision;
using std::ostringstream;
using std::vector;
using Hurricane::tab;
using Hurricane::Warning;
using Hurricane::Error;
using Hurricane::Transformation;
using Hurricane::Technology;
using Hurricane::DataBase;
using Hurricane::BasicLayer;
using Hurricane::RegularLayer;
using Hurricane::Segment;
using Hurricane::Pad;
using Hurricane::Pin;
using Hurricane::Plug;
using Hurricane::Path;
using Hurricane::Occurrence;
using Hurricane::NetExternalComponents;
using CRL::AllianceFramework;
using CRL::RoutingGauge;
using CRL::RoutingLayerGauge;
// -------------------------------------------------------------------
// Class : "Anabatic::Configuration".
Configuration::Configuration ( const CellGauge* cg, const RoutingGauge* rg )
: _gdepthv (ndepth)
, _gdepthh (ndepth)
, _ddepthv (ndepth)
, _ddepthh (ndepth)
, _ddepthc (ndepth)
, _netBuilderStyle (Cfg::getParamString("anabatic.netBuilderStyle","HV,3RL+")->asString() )
, _routingStyle (Cfg::getParamInt ("anabatic.routingStyle" ,StyleFlags::NoStyle)->asInt() )
, _cg (NULL)
, _rg (NULL)
, _extensionCaps ()
, _saturateRatio (Cfg::getParamPercentage("anabatic.saturateRatio",80.0)->asDouble())
, _saturateRp (Cfg::getParamInt ("anabatic.saturateRp" ,8 )->asInt())
, _globalThreshold (0)
, _allowedDepth (0)
, _edgeLength (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeLength",24)->asInt()))
, _edgeWidth (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeWidth" , 4)->asInt()))
, _edgeCostH (Cfg::getParamDouble("anabatic.edgeCostH" , 9.0)->asDouble())
, _edgeCostK (Cfg::getParamDouble("anabatic.edgeCostK" , -10.0)->asDouble())
, _edgeHInc (Cfg::getParamDouble("anabatic.edgeHInc" , 1.5)->asDouble())
, _edgeHScaling (Cfg::getParamDouble("anabatic.edgeHScaling" , 1.0)->asDouble())
, _globalIterations (Cfg::getParamInt ("anabatic.globalIterations", 10 )->asInt())
, _diodeName (Cfg::getParamString("etesian.diodeName" , "dio_x0")->asString() )
, _antennaGateMaxWL (Cfg::getParamInt ("etesian.antennaGateMaxWL" , 0 )->asInt())
, _antennaDiodeMaxWL(Cfg::getParamInt ("etesian.antennaDiodeMaxWL", 0 )->asInt())
{
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
string gaugeName = Cfg::getParamString("anabatic.routingGauge","sxlib")->asString();
if (not cg)
cg = AllianceFramework::get()->getCellGauge( gaugeName );
if (not cg) {
string cellGaugeName = Cfg::getParamString("anabatic.cellGauge","sxlib")->asString();
cg = AllianceFramework::get()->getCellGauge( cellGaugeName );
}
if (not cg)
throw Error( "AnabaticEngine::Configuration(): Unable to find cell gauge \"%s\""
, gaugeName.c_str() );
if (not rg)
rg = AllianceFramework::get()->getRoutingGauge( gaugeName );
if (not rg)
throw Error( "AnabaticEngine::Configuration(): Unable to find routing gauge \"%s\""
, gaugeName.c_str() );
_cg = cg->getClone();
_rg = rg->getClone();
_allowedDepth = rg->getDepth()-1;
if (Cfg::hasParameter("anabatic.topRoutingLayer"))
_setTopRoutingLayer( Cfg::getParamString("anabatic.topRoutingLayer")->asString() );
_gmetalh = DataBase::getDB()->getTechnology()->getLayer("gmetalh");
_gmetalv = DataBase::getDB()->getTechnology()->getLayer("gmetalv");
_gcontact = DataBase::getDB()->getTechnology()->getLayer("gcontact");
if (_gcontact == NULL) cerr << Warning("Cannot get \"gcontact\" layer from the Technology.") << endl;
if (_gmetalv == NULL) cerr << Warning("Cannot get \"gmetalv\" layer from the Technology.") << endl;
if (_gmetalh == NULL) cerr << Warning("Cannot get \"gmetalh\" layer from the Technology.") << endl;
//DbU::Unit sliceHeight = _cg->getSliceHeight();
_ddepthc = (_allowedDepth > 1) ? 1 : 0;
const vector<RoutingLayerGauge*>& layerGauges = rg->getLayerGauges();
for ( size_t depth=0 ; depth < layerGauges.size() ; ++depth ) {
if ( (_gdepthh == ndepth)
and layerGauges[depth]->isHorizontal()
and (layerGauges[depth]->getType() == Constant::LayerGaugeType::Default) ) {
_gdepthh = depth;
_ddepthh = depth;
}
if ( (_gdepthv == ndepth)
and layerGauges[depth]->isVertical()
and (layerGauges[depth]->getType() == Constant::LayerGaugeType::Default) ) {
_gdepthv = depth;
_ddepthv = depth;
}
const RegularLayer* regularLayer = dynamic_cast<const RegularLayer*>( layerGauges[depth]->getLayer() );
if (regularLayer)
_extensionCaps.push_back( regularLayer->getExtentionCap() );
else {
const BasicLayer* basicLayer = dynamic_cast<const BasicLayer*>( layerGauges[depth]->getLayer() );
if (basicLayer) {
_extensionCaps.push_back( layerGauges[depth]->getHalfWireWidth() );
} else {
_extensionCaps.push_back( 0 );
cerr << Warning( "Routing layer at depth %d is *not* a RegularLayer, cannot guess extension cap.\n"
" (%s)"
, depth
, getString(layerGauges[depth]->getLayer()).c_str()
) << endl;
}
}
}
if (_antennaGateMaxWL and not _antennaDiodeMaxWL) {
_antennaDiodeMaxWL = _antennaGateMaxWL;
cerr << Warning( "Anabatic::Configuration(): \"etesian.antennaGateMaxWL\" is defined but not \"etesian.antennaDiodeMaxWL\".\n"
" Setting both to %s"
, DbU::getValueString(_antennaGateMaxWL).c_str()
) << endl;
}
}
Configuration::Configuration ( const Configuration& other )
: _gmetalh (other._gmetalh)
, _gmetalv (other._gmetalv)
, _gcontact (other._gcontact)
, _gdepthv (other._gdepthv)
, _gdepthh (other._gdepthh)
, _ddepthv (other._ddepthv)
, _ddepthh (other._ddepthh)
, _ddepthc (other._ddepthc)
, _netBuilderStyle (other._netBuilderStyle)
, _routingStyle (other._routingStyle)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps (other._extensionCaps)
, _saturateRatio (other._saturateRatio)
, _globalThreshold (other._globalThreshold)
, _allowedDepth (other._allowedDepth)
, _edgeCostH (other._edgeCostH)
, _edgeCostK (other._edgeCostK)
, _edgeHInc (other._edgeHInc)
, _edgeHScaling (other._edgeHScaling)
, _globalIterations (other._globalIterations)
, _diodeName (other._diodeName)
, _antennaGateMaxWL (other._antennaGateMaxWL)
, _antennaDiodeMaxWL(other._antennaDiodeMaxWL)
{
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
if (other._cg) _cg = other._cg->getClone();
if (other._rg) _rg = other._rg->getClone();
}
Configuration::~Configuration ()
{
cdebug_log(145,0) << "About to delete attribute _rg (RoutingGauge)." << endl;
_cg->destroy ();
_rg->destroy ();
}
Configuration* Configuration::clone () const
{ return new Configuration(*this); }
bool Configuration::isTwoMetals () const
{ return _rg->isTwoMetals(); }
bool Configuration::isHybrid () const
{ return _routingStyle & StyleFlags::Hybrid; }
bool Configuration::isHV () const
{ return _rg->isHV(); }
bool Configuration::isVH () const
{ return _rg->isVH(); }
bool Configuration::isGMetal ( const Layer* layer ) const
{ return (layer and ((layer == _gmetalh) or (layer == _gmetalv))); }
bool Configuration::isGContact ( const Layer* layer ) const
{ return (layer and (layer == _gcontact)); }
const Layer* Configuration::getGContactLayer () const
{ return _gcontact; }
const Layer* Configuration::getGHorizontalLayer () const
{ return _gmetalh; }
const Layer* Configuration::getGVerticalLayer () const
{ return _gmetalv; }
size_t Configuration::getDepth () const
{ return _rg->getDepth(); }
size_t Configuration::getAllowedDepth () const
{ return _allowedDepth; }
size_t Configuration::getLayerDepth ( const Layer* layer ) const
{ return _rg->getLayerDepth(layer); }
CellGauge* Configuration::getCellGauge () const
{ return _cg; }
RoutingGauge* Configuration::getRoutingGauge () const
{ return _rg; }
RoutingLayerGauge* Configuration::getLayerGauge ( size_t depth ) const
{ return _rg->getLayerGauge(depth); }
const Layer* Configuration::getRoutingLayer ( size_t depth ) const
{ return _rg->getRoutingLayer(depth); }
Layer* Configuration::getContactLayer ( size_t depth ) const
{ return _rg->getContactLayer(depth); }
DbU::Unit Configuration::getSliceHeight () const
{ return _cg->getSliceHeight(); }
DbU::Unit Configuration::getSliceStep () const
{ return _cg->getSliceStep(); }
DbU::Unit Configuration::getPitch ( const Layer* layer, Flags flags ) const
{ return getPitch( getLayerDepth(layer), flags ); }
DbU::Unit Configuration::getOffset ( const Layer* layer ) const
{ return getOffset( getLayerDepth(layer) ); }
DbU::Unit Configuration::getExtensionCap ( const Layer* layer ) const
{ return getExtensionCap( getLayerDepth(layer) ); }
DbU::Unit Configuration::getWireWidth ( const Layer* layer ) const
{ return getWireWidth( getLayerDepth(layer) ); }
DbU::Unit Configuration::getPWireWidth ( const Layer* layer ) const
{ return getPWireWidth( getLayerDepth(layer) ); }
Flags Configuration::getDirection ( const Layer* layer ) const
{ return getDirection( getLayerDepth(layer) ); }
float Configuration::getSaturateRatio () const
{ return _saturateRatio; }
size_t Configuration::getSaturateRp () const
{ return _saturateRp; }
DbU::Unit Configuration::getGlobalThreshold () const
{ return _globalThreshold; }
DbU::Unit Configuration::getPitch ( size_t depth, Flags flags ) const
{
if (flags == Flags::NoFlags) return _rg->getLayerPitch(depth);
if (flags & Flags::AboveLayer) {
if (depth < getAllowedDepth())
return _rg->getLayerPitch( depth + 1 );
else {
if ( (depth > 0) and (_rg->getLayerType(depth-1) != Constant::PinOnly) )
return _rg->getLayerPitch( depth - 1 );
}
}
if (flags & Flags::BelowLayer) {
if ( (depth > 0) and (_rg->getLayerType(depth-1) != Constant::PinOnly) )
return _rg->getLayerPitch( depth - 1 );
else {
if (depth < getAllowedDepth())
return _rg->getLayerPitch( depth + 1 );
}
}
// Should issue at least a warning here.
return _rg->getLayerPitch(depth);
}
DbU::Unit Configuration::getOffset ( size_t depth ) const
{ return _rg->getLayerOffset(depth); }
DbU::Unit Configuration::getWireWidth ( size_t depth ) const
{ return _rg->getLayerWireWidth(depth); }
DbU::Unit Configuration::getPWireWidth ( size_t depth ) const
{ return _rg->getLayerPWireWidth(depth); }
DbU::Unit Configuration::getExtensionCap ( size_t depth ) const
{ return _extensionCaps[depth]; }
Flags Configuration::getDirection ( size_t depth ) const
{ return _rg->getLayerDirection(depth); }
void Configuration::setAllowedDepth ( size_t allowedDepth )
{ _allowedDepth = (allowedDepth > getDepth()) ? getDepth() : allowedDepth; }
void Configuration::_setTopRoutingLayer ( Name name )
{
for ( size_t depth=0 ; depth<_rg->getDepth() ; ++depth ) {
if (_rg->getRoutingLayer(depth)->getName() == name) {
_allowedDepth = _rg->getLayerGauge(depth)->getDepth();
return;
}
}
cerr << Error( "In Configuration::Concrete::_setTopRoutingLayer():\n"
" The routing gauge <%s> has no layer named <%s>"
, getString(_rg->getName()).c_str()
, getString(name).c_str() ) << endl;
}
void Configuration::setSaturateRatio ( float ratio )
{ _saturateRatio = ratio; }
void Configuration::setSaturateRp ( size_t threshold )
{ _saturateRp = threshold; }
void Configuration::setGlobalThreshold ( DbU::Unit threshold )
{ _globalThreshold = threshold; }
DbU::Unit Configuration::getEdgeLength () const
{ return _edgeLength; }
DbU::Unit Configuration::getEdgeWidth () const
{ return _edgeWidth; }
float Configuration::getEdgeCostH () const
{ return _edgeCostH; }
float Configuration::getEdgeCostK () const
{ return _edgeCostK; }
float Configuration::getEdgeHInc () const
{ return _edgeHInc; }
float Configuration::getEdgeHScaling () const
{ return _edgeHScaling; }
int Configuration::getGlobalIterations () const
{ return _globalIterations; }
DbU::Unit Configuration::isOnRoutingGrid ( RoutingPad* rp ) const
{
Box ab = rp->getCell()->getBoundingBox();
Box bb = rp->getBoundingBox();
Point center = rp->getCenter();
RoutingLayerGauge* gauge = getLayerGauge( 1 );
if (gauge->isHorizontal()) return 0;
DbU::Unit nearestX = gauge->getTrackPosition( ab.getXMin(), ab.getXMax(), center.getX(), Constant::Nearest );
if ( (nearestX >= bb.getXMin()) and (nearestX <= bb.getXMax()) ) return 0;
return nearestX;
}
bool Configuration::selectRpComponent ( RoutingPad* rp ) const
{
cdebug_log(112,1) << "selectRpComponent(): " << rp << endl;
if (rp->isAtTopLevel()) {
cdebug_log(112,0) << "> RP is at top level, must not change it." << endl;
cdebug_tabw(112,-1);
return true;
}
#define BETTER_FOR_TSMC 0
#if BETTER_FOR_TSMC
rp->setOnBestComponent( RoutingPad::BiggestArea );
cdebug_tabw(112,-1);
return true;
#else
Box ab = rp->getCell()->getAbutmentBox();
const Layer* metal1 = getLayerGauge( 0 )->getLayer();
RoutingLayerGauge* gauge = getLayerGauge( 1 );
Occurrence occurrence = rp->getPlugOccurrence();
Plug* plug = dynamic_cast<Plug*>( occurrence.getEntity() );
Net* masterNet = plug->getMasterNet();
Path path = Path( occurrence.getPath(), plug->getInstance() );
Transformation transformation = path.getTransformation();
Segment* current = dynamic_cast<Segment*>( rp->getOccurrence().getEntity() );
if (current and (current->getLayer()->getMask() != metal1->getMask())) {
cdebug_log(112,0) << "> using default non-metal1 segment." << endl;
cdebug_tabw(112,-1);
return true;
}
DbU::Unit bestSpan = 0;
Component* bestComponent = NULL;
cdebug_log(112,0) << "Looking into: " << masterNet->getCell() << endl;
for ( Component* component : masterNet->getComponents() ) {
cdebug_log(112,0) << "@ " << component << endl;
if (not NetExternalComponents::isExternal(component)) {
cdebug_log(112,0) << " Not an external component, skip." << endl;
continue;
}
if (dynamic_cast<Pin*>(component)) {
cdebug_log(112,0) << " Pins are always considered best candidates:" << component << endl;
bestComponent = component;
break;
}
Component* candidate = dynamic_cast<Segment*>( component );
if (not candidate
or (candidate->getLayer()->getMask() != metal1->getMask()) )
candidate = dynamic_cast<Pin*>(component);
if (not candidate)
candidate = dynamic_cast<Pad*>( component );
if (not candidate) continue;
Box bb = transformation.getBox( candidate->getBoundingBox() );
DbU::Unit trackPos = 0;
DbU::Unit minPos = DbU::Max;
DbU::Unit maxPos = DbU::Min;
if (gauge->isVertical()) {
trackPos = gauge->getTrackPosition( ab.getXMin()
, ab.getXMax()
, bb.getCenter().getX()
, Constant::Nearest );
minPos = bb.getXMin();
maxPos = bb.getXMax();
cdebug_log(112,0) << "Vertical gauge: " << gauge << endl;
cdebug_log(112,0) << "ab.getXMin(): " << DbU::getValueString(bb.getXMin()) << endl;
cdebug_log(112,0) << "ab.getXMax(): " << DbU::getValueString(bb.getXMax()) << endl;
cdebug_log(112,0) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getX()) << endl;
} else {
trackPos = gauge->getTrackPosition( ab.getYMin()
, ab.getYMax()
, bb.getCenter().getY()
, Constant::Nearest );
minPos = bb.getYMin();
maxPos = bb.getYMax();
cdebug_log(112,0) << "Horizontal gauge: " << gauge << endl;
cdebug_log(112,0) << "ab.getYMin(): " << DbU::getValueString(bb.getYMin()) << endl;
cdebug_log(112,0) << "ab.getYMax(): " << DbU::getValueString(bb.getYMax()) << endl;
cdebug_log(112,0) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getY()) << endl;
}
cdebug_log(112,0) << "| " << occurrence.getPath() << endl;
cdebug_log(112,0) << "| " << transformation << endl;
cdebug_log(112,0) << "| " << bb << " of:" << candidate << endl;
cdebug_log(112,0) << "| Nearest Pos: " << DbU::getValueString(trackPos) << endl;
if ( (trackPos >= minPos) and (trackPos <= maxPos) ) {
if (not bestComponent or (bestSpan < maxPos-minPos)) {
bestComponent = component;
bestSpan = maxPos - minPos;
}
}
}
if (bestComponent) {
rp->setExternalComponent( bestComponent );
cdebug_log(112,0) << "Using best candidate:" << bestComponent << endl;
cdebug_tabw(112,-1);
return true;
}
cdebug_tabw(112,-1);
return false;
#endif
}
void Configuration::print ( Cell* cell ) const
{
if (not cmess1.enabled()) return;
string topLayerName = "UNKOWN";
const Layer* topLayer = _rg->getRoutingLayer( _allowedDepth );
if (topLayer)
topLayerName = getString( topLayer->getName() );
cout << " o Configuration of ToolEngine<Anabatic> for Cell <" << cell->getName() << ">" << endl;
cout << Dots::asIdentifier(" - Routing Gauge" ,getString(_rg->getName())) << endl;
cout << Dots::asString (" - Top routing layer" ,topLayerName) << endl;
cout << Dots::asUInt (" - Maximum GR iterations" ,_globalIterations) << endl;
}
string Configuration::_getTypeName () const
{
return "Configuration";
}
string Configuration::_getString () const
{
ostringstream os;
os << "<" << _getTypeName() << " " << _rg->getName() << ">";
return os.str();
}
Record* Configuration::_getRecord () const
{
Record* record = new Record ( _getString() );
record->add( getSlot( "_gdepthh" , _gdepthh ) );
record->add( getSlot( "_gdepthv" , _gdepthv ) );
record->add( getSlot( "_rg" , _rg ) );
record->add( getSlot( "_gmetalh" , _gmetalh ) );
record->add( getSlot( "_gmetalv" , _gmetalv ) );
record->add( getSlot( "_gcontact" , _gcontact ) );
record->add( getSlot( "_allowedDepth" , _allowedDepth ) );
record->add( getSlot( "_edgeCostH" , _edgeCostH ) );
record->add( getSlot( "_edgeCostK" , _edgeCostK ) );
record->add( getSlot( "_edgeHInc" , _edgeHInc ) );
record->add( getSlot( "_edgeHScaling" , _edgeHScaling ) );
record->add( getSlot( "_globalIterations", _globalIterations ) );
record->add( DbU::getValueSlot( "_antennaGateMaxWL" , &_antennaGateMaxWL ) );
record->add( DbU::getValueSlot( "_antennaDiodeMaxWL", &_antennaDiodeMaxWL ) );
return record;
}
} // Anabatic namespace.

View File

@ -1,286 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "Constants.cpp<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Constants.cpp" |
// +-----------------------------------------------------------------+
#include "hurricane/Error.h"
#include "anabatic/Constants.h"
namespace Anabatic {
using std::hex;
using std::string;
using std::ostringstream;
using Hurricane::BaseFlags;
using Hurricane::Error;
// -------------------------------------------------------------------
// Class : "Anabatic::Flags".
const BaseFlags Flags::NoFlags = 0;
// Flags used for both objects states & functions arguments.
const BaseFlags Flags::Horizontal = (1L << 0);
const BaseFlags Flags::Vertical = (1L << 1);
const BaseFlags Flags::Source = (1L << 2);
const BaseFlags Flags::Target = (1L << 3);
const BaseFlags Flags::Invalidated = (1L << 4);
// Flags for GCell objects states only.
const BaseFlags Flags::DeviceGCell = (1L << 5);
const BaseFlags Flags::HChannelGCell = (1L << 6);
const BaseFlags Flags::VChannelGCell = (1L << 7);
const BaseFlags Flags::StrutGCell = (1L << 8);
const BaseFlags Flags::MatrixGCell = (1L << 9);
const BaseFlags Flags::IoPadGCell = (1L << 10);
const BaseFlags Flags::Saturated = (1L << 11);
const BaseFlags Flags::StdCellRow = (1L << 12);
const BaseFlags Flags::ChannelRow = (1L << 13);
const BaseFlags Flags::HRailGCell = (1L << 14);
const BaseFlags Flags::VRailGCell = (1L << 15);
const BaseFlags Flags::GoStraight = (1L << 16);
// Flags for Edge objects states only.
const BaseFlags Flags::NullCapacity = (1L << 5);
const BaseFlags Flags::InfiniteCapacity = (1L << 6);
// Flags for Anabatic objects states only.
const BaseFlags Flags::DemoMode = (1L << 5);
const BaseFlags Flags::WarnOnGCellOverload = (1L << 6);
const BaseFlags Flags::DestroyGCell = (1L << 7);
const BaseFlags Flags::DestroyBaseContact = (1L << 8);
const BaseFlags Flags::DestroyBaseSegment = (1L << 9);
const BaseFlags Flags::DisableCanonize = (1L << 10);
// Flags for NetDatas objects states only.
const BaseFlags Flags::GlobalFixed = (1L << 5);
const BaseFlags Flags::GlobalEstimated = (1L << 6);
const BaseFlags Flags::GlobalRouted = (1L << 7);
const BaseFlags Flags::DetailRouted = (1L << 8);
const BaseFlags Flags::ExcludeRoute = (1L << 9);
// Masks.
const BaseFlags Flags::WestSide = Horizontal|Target;
const BaseFlags Flags::EastSide = Horizontal|Source;
const BaseFlags Flags::SouthSide = Vertical |Target;
const BaseFlags Flags::NorthSide = Vertical |Source;
const BaseFlags Flags::AllSides = WestSide|EastSide|SouthSide|NorthSide ;
const BaseFlags Flags::EndsMask = Source|Target;
const BaseFlags Flags::DirectionMask = Horizontal|Vertical;
const BaseFlags Flags::DestroyMask = DestroyGCell|DestroyBaseContact|DestroyBaseSegment;
const BaseFlags Flags::GCellTypeMask = DeviceGCell
| HChannelGCell
| VChannelGCell
| StrutGCell
| MatrixGCell
| IoPadGCell
| StdCellRow
| ChannelRow
| HRailGCell
| VRailGCell;
const BaseFlags Flags::RowGCellMask = StdCellRow|ChannelRow;
const BaseFlags Flags::AnalogGCellMask = DeviceGCell
| HChannelGCell
| VChannelGCell
| StrutGCell
| HRailGCell
| VRailGCell;
const BaseFlags Flags::EdgeCapacityMask = Horizontal
| Vertical
| NullCapacity
| InfiniteCapacity ;
// Flags for functions arguments only.
const BaseFlags Flags::Create = (1L << 5);
const BaseFlags Flags::WithPerpands = (1L << 6);
const BaseFlags Flags::WithDoglegs = (1L << 7);
const BaseFlags Flags::WithSelf = (1L << 8);
const BaseFlags Flags::AboveLayer = (1L << 9);
const BaseFlags Flags::BelowLayer = (1L << 10);
const BaseFlags Flags::OpenSession = (1L << 11);
const BaseFlags Flags::Realignate = (1L << 12);
const BaseFlags Flags::NativeConstraints = (1L << 13);
const BaseFlags Flags::ForceMove = (1L << 14);
const BaseFlags Flags::WarnOnError = (1L << 15);
const BaseFlags Flags::Topology = (1L << 16);
const BaseFlags Flags::GlobalSegment = (1L << 17);
const BaseFlags Flags::AllowTerminal = (1L << 18);
const BaseFlags Flags::AllowLocal = (1L << 19);
const BaseFlags Flags::IgnoreContacts = (1L << 20);
const BaseFlags Flags::Propagate = (1L << 21);
const BaseFlags Flags::Superior = (1L << 22);
const BaseFlags Flags::DoglegOnLeft = (1L << 23);
const BaseFlags Flags::DoglegOnRight = (1L << 24);
const BaseFlags Flags::WithNeighbors = (1L << 25);
const BaseFlags Flags::NoCheckLayer = (1L << 26);
const BaseFlags Flags::HalfSlacken = (1L << 27);
const BaseFlags Flags::NoGCellShrink = (1L << 28);
const BaseFlags Flags::CParanoid = (1L << 29);
const BaseFlags Flags::CheckLowDensity = (1L << 30);
const BaseFlags Flags::CheckLowUpDensity = (1L << 31);
const BaseFlags Flags::NoUpdate = (1L << 32);
const BaseFlags Flags::NorthPath = (1L << 33);
const BaseFlags Flags::UseNonPref = (1L << 34);
const BaseFlags Flags::Force = (1L << 35);
const BaseFlags Flags::LayerCapOnly = (1L << 36);
const BaseFlags Flags::NoMinLength = (1L << 37);
const BaseFlags Flags::NoSegExt = (1L << 38);
const BaseFlags Flags::NullLength = (1L << 39);
const BaseFlags Flags::OnVSmall = (1L << 40);
Flags::~Flags ()
{ }
string Flags::asString ( uint32_t mode ) const
{
ostringstream s;
s << ((_flags & (uint64_t)Horizontal ) ? "h" : "-");
s << ((_flags & (uint64_t)Vertical ) ? "v" : "-");
s << ((_flags & (uint64_t)Source ) ? "S" : "-");
s << ((_flags & (uint64_t)Target ) ? "T" : "-");
s << ((_flags & (uint64_t)Invalidated) ? "i" : "-");
switch ( mode ) {
case FlagsFunction:
s << ((_flags & (uint64_t)Create ) ? "C" : "-");
s << ((_flags & (uint64_t)WithPerpands ) ? "P" : "-");
s << ((_flags & (uint64_t)WithDoglegs ) ? "D" : "-");
s << ((_flags & (uint64_t)WithSelf ) ? "s" : "-");
s << ((_flags & (uint64_t)AboveLayer ) ? "a" : "-");
s << ((_flags & (uint64_t)BelowLayer ) ? "b" : "-");
s << ((_flags & (uint64_t)OpenSession ) ? "o" : "-");
s << ((_flags & (uint64_t)Realignate ) ? "R" : "-");
s << ((_flags & (uint64_t)NativeConstraints) ? "N" : "-");
s << ((_flags & (uint64_t)ForceMove ) ? "m" : "-");
s << ((_flags & (uint64_t)WarnOnError ) ? "w" : "-");
s << ((_flags & (uint64_t)Topology ) ? "t" : "-");
s << ((_flags & (uint64_t)GlobalSegment ) ? "G" : "-");
s << ((_flags & (uint64_t)AllowTerminal ) ? "t" : "-");
s << ((_flags & (uint64_t)AllowLocal ) ? "l" : "-");
s << ((_flags & (uint64_t)IgnoreContacts ) ? "i" : "-");
s << ((_flags & (uint64_t)Propagate ) ? "p" : "-");
s << ((_flags & (uint64_t)Superior ) ? "S" : "-");
s << ((_flags & (uint64_t)DoglegOnLeft ) ? "L" : "-");
s << ((_flags & (uint64_t)DoglegOnRight ) ? "R" : "-");
s << ((_flags & (uint64_t)WithNeighbors ) ? "N" : "-");
s << ((_flags & (uint64_t)NoCheckLayer ) ? "L" : "-");
s << ((_flags & (uint64_t)HalfSlacken ) ? "h" : "-");
s << ((_flags & (uint64_t)NoGCellShrink ) ? "s" : "-");
s << ((_flags & (uint64_t)CParanoid ) ? "p" : "-");
s << ((_flags & (uint64_t)CheckLowDensity ) ? "l" : "-");
s << ((_flags & (uint64_t)CheckLowUpDensity) ? "u" : "-");
s << ((_flags & (uint64_t)NoUpdate ) ? "u" : "-");
break;
}
s << " (" << value() << ")";
return s.str();
}
string Flags::_getTypeName () const
{ return "Anabatic::Flags"; }
string Flags::_getString () const
{
string s = "";
s += (_flags & (uint64_t)Horizontal ) ? 'h' : '-';
s += (_flags & (uint64_t)Vertical ) ? 'v' : '-';
s += (_flags & (uint64_t)Source ) ? 'S' : '-';
s += (_flags & (uint64_t)Target ) ? 'T' : '-';
s += (_flags & (uint64_t)DeviceGCell ) ? 'd' : '-';
s += (_flags & (uint64_t)HChannelGCell) ? 'c' : '-';
s += (_flags & (uint64_t)VChannelGCell) ? 'c' : '-';
s += (_flags & (uint64_t)HRailGCell ) ? 'H' : '-';
s += (_flags & (uint64_t)VRailGCell ) ? 'V' : '-';
s += (_flags & (uint64_t)StrutGCell ) ? 'S' : '-';
s += (_flags & (uint64_t)MatrixGCell ) ? 'M' : '-';
s += (_flags & (uint64_t)StdCellRow ) ? 'R' : '-';
s += (_flags & (uint64_t)ChannelRow ) ? 'C' : '-';
s += (_flags & (uint64_t)GoStraight ) ? 'g' : '-';
s += ",";
s += (_flags & (uint64_t)Invalidated ) ? 'i' : '-';
s += (_flags & (uint64_t)DestroyGCell ) ? 'D' : '-';
s += (_flags & (uint64_t)AboveLayer ) ? 'A' : '-';
s += (_flags & (uint64_t)BelowLayer ) ? 'B' : '-';
return s;
}
// -------------------------------------------------------------------
// Class : "Anabatic::StyleFlags".
const BaseFlags StyleFlags::NoStyle = 0;
const BaseFlags StyleFlags::HV = (1L << 0);
const BaseFlags StyleFlags::VH = (1L << 1);
const BaseFlags StyleFlags::OTH = (1L << 2);
const BaseFlags StyleFlags::Channel = (1L << 3);
const BaseFlags StyleFlags::Hybrid = (1L << 4);
StyleFlags::~StyleFlags ()
{ }
StyleFlags StyleFlags::toFlag ( std::string textFlag )
{
if (textFlag == "HV") return HV;
if (textFlag == "VH") return VH;
if (textFlag == "OTH") return OTH;
if (textFlag == "Channel") return Channel;
if (textFlag == "Hybrid") return Hybrid;
if (textFlag == "NoStyle") return NoStyle;
std::cerr << Error( "StyleFlags::toFlag(): Unknown flag value \"%s\"", textFlag.c_str() ) << std::endl;
return NoStyle;
}
StyleFlags StyleFlags::from ( std::string textFlags )
{
size_t start = 0;
size_t stop = textFlags.find( '|' );
while ( stop != string::npos ) {
*this |= toFlag( textFlags.substr( start, stop-start-1 ));
start = stop + 1;
stop = textFlags.find( '|', start );
}
*this |= toFlag( textFlags.substr( stop+1 ));
return *this;
}
string StyleFlags::asString () const
{
ostringstream s;
if (_flags & (uint64_t)HV) { s << (s.tellp() ? "|" : "") << "HV"; }
if (_flags & (uint64_t)VH) { s << (s.tellp() ? "|" : "") << "VH"; }
if (_flags & (uint64_t)OTH) { s << (s.tellp() ? "|" : "") << "OTH"; }
if (_flags & (uint64_t)Channel) { s << (s.tellp() ? "|" : "") << "Channel"; }
if (_flags & (uint64_t)Hybrid ) { s << (s.tellp() ? "|" : "") << "Hybrid"; }
s << " (0x" << hex << _flags << ")";
return s.str();
}
string StyleFlags::_getTypeName () const
{ return "Anabatic::StyleFlags"; }
string StyleFlags::_getString () const
{ return asString(); }
} // Anabatic namespace.

File diff suppressed because it is too large Load Diff

View File

@ -1,549 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "Edge.cpp<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Edge.cpp" |
// +-----------------------------------------------------------------+
#include <iostream>
#include "hurricane/Error.h"
#include "hurricane/Segment.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "anabatic/Edge.h"
#include "anabatic/GCell.h"
#include "anabatic/AnabaticEngine.h"
namespace {
using namespace std;
using namespace Hurricane;
using Anabatic::NetData;
using Anabatic::AnabaticEngine;
class SortSegmentByLength {
public:
inline SortSegmentByLength ( AnabaticEngine* );
inline bool operator() ( const Segment*, const Segment* );
private:
AnabaticEngine* _anabatic;
};
inline SortSegmentByLength::SortSegmentByLength ( AnabaticEngine* anabatic )
: _anabatic(anabatic)
{ }
inline bool SortSegmentByLength::operator() ( const Segment* lhs, const Segment* rhs )
{
NetData* lhsNData = _anabatic->getNetData( lhs->getNet() );
NetData* rhsNData = _anabatic->getNetData( rhs->getNet() );
if (lhsNData->isGlobalFixed() and not rhsNData->isGlobalFixed()) return true;
if (rhsNData->isGlobalFixed() and not lhsNData->isGlobalFixed()) return false;
DbU::Unit delta = rhs->getLength() - lhs->getLength();
if (delta > 0) return true;
if (delta < 0) return false;
return (lhs->getId() < rhs->getId());
}
} // Anonymous namespace.
namespace Anabatic {
using std::cerr;
using std::endl;
using Hurricane::Error;
using Hurricane::RoutingPad;
Name Edge::_extensionName = "Anabatic::Edge";
DbU::Unit Edge::unity = 1;
Edge::Edge ( GCell* source, GCell* target, Flags flags )
: Super(source->getCell())
, _flags (flags|Flags::Invalidated)
, _capacities (NULL)
, _reservedCapacity (0)
, _realOccupancy (0)
, _estimateOccupancy(0.0)
, _historicCost (0.0)
, _source (source)
, _target (target)
, _axis (0)
, _segments ()
{ }
void Edge::_postCreate ()
{
Super::_postCreate();
if (_flags.isset(Flags::Horizontal)) {
_axis = std::max( _source->getYMin(), _target->getYMin() );
_source->_add( this, Flags::EastSide );
_target->_add( this, Flags::WestSide );
} else {
_axis = std::max( _source->getXMin(), _target->getXMin() );
_source->_add( this, Flags::NorthSide );
_target->_add( this, Flags::SouthSide );
}
}
Edge* Edge::create ( GCell* source, GCell* target, Flags flags )
{
if (not source) throw Error( "Edge::create(): NULL source argument." );
if (not target) throw Error( "Edge::create(): NULL target argument." );
if (source == target)
throw Error("Edge::create(): Source & target are the same (%s).", getString(source).c_str() );
if (not (flags.intersect(Flags::Horizontal|Flags::Vertical))) {
Box border = GCell::getBorder( source, target );
if (border.isEmpty())
throw Error( "Edge::create(): source & target GCells are *not* contiguous.\n"
" source:%s\n"
" target:%s"
, getString(source).c_str()
, getString(target).c_str()
);
if (border.getYMin() == border.getYMax()) flags |= Flags::Horizontal;
else flags |= Flags::Vertical;
}
Edge* edge = new Edge ( source, target, flags );
edge->_postCreate();
cdebug_log(110,1) << "Edge::create(): " << /*(void*)edge << ":" <<*/ edge << endl;
cdebug_log(110,0) << "source:" << /*(void*)source << ":" <<*/ edge->getSource() << endl;
cdebug_log(110,0) << "target:" << /*(void*)target << ":" <<*/ edge->getTarget() << endl;
cdebug_tabw(110,-1);
return edge;
}
Edge::~Edge ()
{ }
void Edge::_preDestroy ()
{
_source->getAnabatic()->_unrefCapacity( _capacities );
_source->_remove( this, _flags|Flags::Source );
_target->_remove( this, _flags|Flags::Target );
Super::_preDestroy();
}
void Edge::destroy ()
{
_preDestroy();
delete this;
}
AnabaticEngine* Edge::getAnabatic () const
{ return (_source) ? _source->getAnabatic() : NULL; }
DbU::Unit Edge::getAxisMin () const
{
if (_flags.isset(Flags::Vertical))
return std::max( _source->getXMin(), _target->getXMin() );
return std::max( _source->getYMin(), _target->getYMin() );
}
GCell* Edge::getOpposite ( const GCell* from ) const
{
if (from == _source) return _target;
if (from == _target) return _source;
cerr << Error( "Edge::getOpposite(): On %s,\n"
" \"from\" CGell id:%u is neither source nor target (S-id:%u, T-id:%u)."
, getString(this).c_str()
, from->getId()
, _source->getId()
, _target->getId()
) << endl;
return NULL;
}
Interval Edge::getSide () const
{
Interval side;
if (_flags.isset(Flags::Vertical))
side = Interval( std::max(_source->getXMin(),_target->getXMin())
, std::min(_source->getXMax(),_target->getXMax()) );
else
side = Interval( std::max(_source->getYMin(),_target->getYMin())
, std::min(_source->getYMax(),_target->getYMax()) );
return side;
}
DbU::Unit Edge::getDistance () const
{
Point sourceCenter = getSource()->getBoundingBox().getCenter();
Point targetCenter = getTarget()->getBoundingBox().getCenter();
DbU::Unit dx = targetCenter.getX() - sourceCenter.getX();
DbU::Unit dy = targetCenter.getY() - sourceCenter.getY();
if (dx < 0) dx = -dx;
//if (dx) dx += DbU::fromLambda( 0.1 );
return dx + ((dy > 0) ? dy : -dy);
}
void Edge::incRealOccupancy ( int delta )
{
unsigned int occupancy = 0;
if ((int)_realOccupancy + delta > 0) occupancy = _realOccupancy + delta;
if ((_realOccupancy <= getCapacity()) and (occupancy > getCapacity())) getAnabatic()->addOv ( this );
if ((_realOccupancy > getCapacity()) and (occupancy <= getCapacity())) getAnabatic()->removeOv( this );
_realOccupancy = occupancy;
}
void Edge::incRealOccupancy2 ( int value )
{
_realOccupancy += value;
}
Segment* Edge::getSegment ( const Net* owner ) const
{
for ( Segment* segment : _segments ) {
if (segment->getNet() == owner) return segment;
}
return NULL;
}
bool Edge::isEnding ( Segment* segment ) const
{
cdebug_log(112,0) << "Edge::isEnding() " << this << endl;
cdebug_log(112,0) << "| Sbb " << _source->getBoundingBox() << endl;
cdebug_log(112,0) << "| Tbb " << _target->getBoundingBox() << endl;
cdebug_log(112,0) << "| " << segment << endl;
if (Session::getRoutingGauge()->isTwoMetals()) {
Contact* contact = dynamic_cast<Contact*>( segment->getSource() );
cdebug_log(112,0) << "| source" << contact << endl;
if (contact) {
if ( (_source->isStdCellRow() and _source->getBoundingBox().contains(contact->getCenter()))
or (_target->isStdCellRow() and _target->getBoundingBox().contains(contact->getCenter())) )
return true;
}
contact = dynamic_cast<Contact*>( segment->getTarget() );
cdebug_log(112,0) << "| target" << contact << endl;
if (contact) {
if ( (_source->isStdCellRow() and _source->getBoundingBox().contains(contact->getCenter()))
or (_target->isStdCellRow() and _target->getBoundingBox().contains(contact->getCenter())) )
return true;
}
} else {
// This part is not used (yet). We don't call isEnding() when running
// in over-the-cell mode.
Contact* contact = dynamic_cast<Contact*>( segment->getSource() );
cdebug_log(112,0) << "| source" << contact << endl;
if (contact) {
for ( Hook* hook : contact->getBodyHook()->getHooks() ) {
if (dynamic_cast<RoutingPad*>(hook->getComponent())) {
if ( _source->getBoundingBox().contains(contact->getCenter())
or _target->getBoundingBox().contains(contact->getCenter()) )
return true;
break;
}
}
}
contact = dynamic_cast<Contact*>( segment->getTarget() );
cdebug_log(112,0) << "| target" << contact << endl;
if (contact) {
for ( Hook* hook : contact->getBodyHook()->getHooks() ) {
if (dynamic_cast<RoutingPad*>(hook->getComponent())) {
if ( _source->getBoundingBox().contains(contact->getCenter())
or _target->getBoundingBox().contains(contact->getCenter()) )
return true;
break;
}
}
}
}
return false;
}
void Edge::add ( Segment* segment )
{
_segments.push_back( segment );
Horizontal* h = dynamic_cast<Horizontal*>(segment);
Vertical* v = dynamic_cast<Vertical*>(segment);
DbU::Unit pitch = 0;
if (h) pitch = Session::getGHorizontalPitch();
if (v) pitch = Session::getGVerticalPitch();
int deltaOccupancy = 0;
if (not Session::getRoutingGauge()->isTwoMetals()) deltaOccupancy = segment->getWidth()/pitch;
else {
// In channel routing, do not increase edge occupancy on terminals,
// because the capacity has already been decreased in annotedGlobalGraph (Katana).
if (not isEnding(segment)) deltaOccupancy = segment->getWidth()/pitch;
}
incRealOccupancy( deltaOccupancy );
}
void Edge::remove ( Segment* segment )
{
for ( size_t i=0 ; i<_segments.size() ; ++i ) {
if (_segments[i] == segment) {
cdebug_log(110,0) << "On " << this << endl;
cdebug_log(110,0) << "| remove:" << segment << endl;
std::swap( _segments[i], _segments[_segments.size()-1] );
_segments.pop_back();
Horizontal* h = dynamic_cast<Horizontal*>(segment);
Vertical* v = dynamic_cast<Vertical*>(segment);
DbU::Unit pitch = 0;
if (h) pitch = Session::getGHorizontalPitch();
if (v) pitch = Session::getGVerticalPitch();
int deltaOccupancy = 0;
if (not Session::getRoutingGauge()->isTwoMetals()) deltaOccupancy = segment->getWidth()/pitch;
else {
// In channel routing, do not increase edge occupancy on terminals,
// because the capacity has already been decreased in annotedGlobalGraph (Katana).
if (not isEnding(segment)) deltaOccupancy = segment->getWidth()/pitch;
}
incRealOccupancy( -deltaOccupancy );
return;
}
}
cerr << Error( "On %s,\n segment doesn't belong: %s"
, getString(this).c_str()
, getString(segment).c_str() ) << endl;
}
void Edge::replace ( Segment* orig, Segment* repl )
{
for ( size_t i=0 ; i<_segments.size() ; ++i ) {
if (_segments[i] == orig) {
_segments[i] = repl;
return;
}
}
}
size_t Edge::ripup ()
{
AnabaticEngine* anabatic = getAnabatic();
size_t netCount = 0;
sort( _segments.begin(), _segments.end(), SortSegmentByLength(anabatic) );
if (Session::getRoutingGauge()->isTwoMetals()) {
for ( size_t i=0 ; i<_segments.size() ; ) {
if (not isEnding(_segments[i])) {
NetData* netData = anabatic->getNetData( _segments[i]->getNet() );
if (netData->isGlobalFixed ()) break;
if (netData->isGlobalRouted()) ++netCount;
anabatic->ripup( _segments[i], Flags::Propagate );
continue;
}
++i;
}
} else {
size_t truncate = (size_t)( (getCapacity()*2) / 3 );
while ( _segments.size() > truncate ) {
NetData* netData = anabatic->getNetData( _segments[truncate]->getNet() );
if (netData->isGlobalFixed ()) break;
if (netData->isGlobalRouted()) ++netCount;
anabatic->ripup( _segments[truncate], Flags::Propagate );
}
// DbU::Unit globalThreshold = Session::getSliceHeight()*3;
// for ( size_t i=0 ; i<_segments.size() ; ) {
// if (_segments[i]->getLength() >= globalThreshold) {
// NetData* netData = anabatic->getNetData( _segments[i]->getNet() );
// if (netData->isGlobalRouted()) ++netCount;
// anabatic->ripup( _segments[i], Flags::Propagate );
// } else {
// ++i;
// }
// }
}
return netCount;
}
void Edge::_setSource ( GCell* source )
{
if (source == _target)
throw Error("Edge::_setSource(): Source & target are the same (%s).", getString(source).c_str() );
invalidate( false );
_source=source;
}
void Edge::_setTarget ( GCell* target )
{
if (_source == target)
throw Error("Edge::_setTarget(): Source & target are the same (%s).", getString(target).c_str() );
invalidate( false );
_target=target;
}
void Edge::invalidate ( bool )
{
cdebug_log(110,1) << "Edge::invalidate() " << this << endl;
_flags |= Flags::Invalidated;
Super::invalidate( false );
cdebug_tabw(110,-1);
}
void Edge::materialize ()
{
cdebug_log(110,1) << "Edge::materialize() " << this << endl;
Flags flags = _flags;
Interval side = getSide();
_axis = side.getCenter();
if (getSource()->isStdCellRow() and getTarget()->isStdCellRow()) flags |= Flags::NullCapacity;
else if (getSource()->isChannelRow() and getTarget()->isChannelRow()) flags |= Flags::InfiniteCapacity;
_capacities = getAnabatic()->_createCapacity( _flags, side );
_flags.reset( Flags::Invalidated );
cdebug_log(110,0) << "Edge::materialize() " << this << endl;
Super::materialize();
cdebug_tabw(110,-1);
}
const Name& Edge::getName () const
{ return _extensionName; }
Box Edge::getBoundingBox () const
{
static DbU::Unit halfThickness = getAnabatic()->getConfiguration()->getEdgeWidth () / 2;
static DbU::Unit halfLength = getAnabatic()->getConfiguration()->getEdgeLength() / 2;
Box bb;
if (_flags.isset(Flags::Horizontal))
bb = Box( _target->getXMin() - halfLength, _axis - halfThickness
, _target->getXMin() + halfLength, _axis + halfThickness
);
else
bb = Box( _axis - halfThickness, _target->getYMin() - halfLength
, _axis + halfThickness, _target->getYMin() + halfLength
);
return bb;
}
bool Edge::isMaxCapacity ( Net* net ) const
{
unsigned int wpitch = 0;
if (net) {
cdebug_log(112,0) << "_capacity:" << getCapacity() << endl;
Hurricane::NetRoutingState* state = Hurricane::NetRoutingExtension::get( net );
wpitch = (state) ? state->getWPitch()-1 : 0;
}
return (_realOccupancy + wpitch >= getCapacity());
}
void Edge::translate ( const DbU::Unit&, const DbU::Unit& )
{
cerr << Error( "Edge::translate(): On %s,\n"
" Must never be called on a Edge object (ignored)."
, getString(this).c_str()
) << endl;
}
string Edge::_getTypeName () const
{ return getString(_extensionName); }
string Edge::_getString () const
{
Point center ( getSource()->getCenter() );
string s = Super::_getString();
s.insert( s.size()-1, " S:["+DbU::getValueString(center.getX()) );
s.insert( s.size()-1, " " +DbU::getValueString(center.getY()) );
s.insert( s.size()-1, "] " +DbU::getValueString(_axis) );
s.insert( s.size()-1, " " +getString(_realOccupancy) );
s.insert( s.size()-1, "/" +getString(getCapacity()) );
s.insert( s.size()-1, " h:" +getString(_historicCost) );
s.insert( s.size()-1, " " +getString(_flags) );
return s;
}
Record* Edge::_getRecord () const
{
Record* record = Super::_getRecord();
record->add( getSlot("_flags" , _flags ) );
record->add( getSlot("_capacities" , _capacities ) );
record->add( getSlot("_reservedCapacity" , _reservedCapacity ) );
record->add( getSlot("_realOccupancy" , _realOccupancy ) );
record->add( getSlot("_estimateOccupancy", _estimateOccupancy) );
record->add( getSlot("_source" , _source ) );
record->add( getSlot("_target" , _target ) );
record->add( DbU::getValueSlot("_axis", &_axis) );
record->add( getSlot("_segments" , &_segments ) );
return record;
}
} // Anabatic namespace.

View File

@ -1,123 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "EdgeCapacity.cpp<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2018-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./EdgeCapacity.cpp" |
// +-----------------------------------------------------------------+
#include <sstream>
#include "anabatic/EdgeCapacity.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using std::ostringstream;
EdgeCapacity::EdgeCapacity ( AnabaticEngine* anabatic, Flags direction, Interval span, size_t depth )
: _anabatic (anabatic)
, _refCount (0)
, _flags (direction)
, _depth (depth+1)
, _span (span)
, _capacities()
{
int defcap = (_flags & Flags::InfiniteCapacity) ? 100 : 0;
_capacities.reserve( _depth );
for ( size_t i=0 ; i<_depth ; ++i ) _capacities.push_back( defcap );
if (_flags & (Flags::NullCapacity|Flags::InfiniteCapacity)) return;
Box ab = _anabatic->getCell()->getAbutmentBox();
RoutingGauge* rg = _anabatic->getConfiguration()->getRoutingGauge();
span = _span;
span.inflate( 0, -1 );
if (span.isEmpty()) return;
const vector<RoutingLayerGauge*>& layerGauges = rg->getLayerGauges();
for ( size_t depth=0 ; depth < _depth ; ++depth ) {
if (layerGauges[depth]->getType() != Constant::Default) continue;
if (_flags & Flags::Horizontal) {
if (layerGauges[depth]->getDirection() != Constant::Horizontal) continue;
_capacities[depth] = layerGauges[depth]->getTrackNumber( span.getVMin() - ab.getYMin()
, span.getVMax() - ab.getYMin() );
//cdebug_log(110,0) << "Horizontal edge capacity:" << capacity << endl;
}
if (_flags & Flags::Vertical) {
if (layerGauges[depth]->getDirection() != Constant::Vertical) continue;
_capacities[depth] = layerGauges[depth]->getTrackNumber( span.getVMin() - ab.getXMin()
, span.getVMax() - ab.getXMin() );
//cdebug_log(110,0) << "Vertical edge capacity:" << capacity << endl;
}
}
}
void EdgeCapacity::forceCapacity ( unsigned int capacity )
{
bool forced = false;
RoutingGauge* rg = _anabatic->getConfiguration()->getRoutingGauge();
const vector<RoutingLayerGauge*>& layerGauges = rg->getLayerGauges();
for ( size_t i=0 ; i<_depth ; ++i ) {
if (layerGauges[i]->getType() != Constant::Default) continue;
if ( (_flags & Flags::Horizontal) xor layerGauges[i]->isHorizontal() ) continue;
if (forced) _capacities[i] = 0;
else {
_capacities[i] = capacity;
forced = true;
}
}
}
string EdgeCapacity::_getString () const
{
ostringstream os;
os << "<EdgeCapacity ";
if (_flags & Flags::Horizontal) os << "Horizontal ";
else if (_flags & Flags::Vertical ) os << "Vertical ";
else os << "Unknown ";
os << "[" << DbU::getValueString(_span.getVMin())
<< " : " << DbU::getValueString(_span.getVMax())
<< "] " << getCapacity()
<< " refs:" << _refCount
<< ">";
return os.str();
}
Record* EdgeCapacity::_getRecord () const
{
Record* record = new Record( getString(this) );
record->add( getSlot( "_anabatic", _anabatic ) );
record->add( getSlot( "_refCount", _refCount ) );
record->add( getSlot( "_flags" , &_flags ) );
record->add( getSlot( "_span" , &_span ) );
RoutingGauge* rg = getAnabatic()->getConfiguration()->getRoutingGauge();
for ( size_t depth=0 ; depth<_depth ; ++depth ) {
ostringstream s;
const Layer* layer = rg->getRoutingLayer(depth);
s << "_capacities[" << depth << ":" << ((layer) ? layer->getName() : "None") << "]";
record->add( getSlot ( s.str(), _capacities[depth] ) );
}
return record;
}
} // Anabatic namespace.

View File

@ -1,285 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "Edges.cpp<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./anabatic/Edges.cpp" |
// +-----------------------------------------------------------------+
#include "anabatic/Edges.h"
#include "anabatic/GCell.h"
namespace Anabatic {
using std::cerr;
using std::endl;
// -------------------------------------------------------------------
// Class : "Anabatic::GCell_Edges".
GCell_Edges::Locator::Locator ( const GCell* gcell, Flags filterFlags )
: EdgesHL()
, _gcell (gcell)
, _stateFlags (Flags::EastSide)
, _filterFlags(filterFlags)
, _iedge (0)
{
// cdebug_log(110,0) << "GCell_Edges::Locator::Locator() " << isValid() << endl;
if (_gcell->getEastEdges().empty() or not _filterFlags.contains(Flags::EastSide)) progress();
}
EdgesHL* GCell_Edges::Locator::getClone () const
{
// cdebug_log(110,0) << "GCell_Edges::Locator::getClone()" << endl;
return new Locator (*this);
}
Edge* GCell_Edges::Locator::getElement () const
{
if (_stateFlags.contains(Flags::EastSide )) return _gcell->getEastEdges ()[_iedge];
if (_stateFlags.contains(Flags::NorthSide)) return _gcell->getNorthEdges()[_iedge];
if (_stateFlags.contains(Flags::WestSide )) return _gcell->getWestEdges ()[_iedge];
if (_stateFlags.contains(Flags::SouthSide)) return _gcell->getSouthEdges()[_iedge];
return NULL;
}
bool GCell_Edges::Locator::isValid () const
{ return _stateFlags; }
void GCell_Edges::Locator::progress ()
{
cdebug_log(110,0) << "GCell_Edges::Locator::progress() [from] " << _stateFlags << " iedge:" << _iedge << endl;
cdebug_log(110,0) << " _filterFlags:" << _filterFlags << endl;
cdebug_log(110,0) << " East:" << _gcell->getEastEdges ().size()
<< " North:" << _gcell->getNorthEdges().size()
<< " West:" << _gcell->getWestEdges ().size()
<< " South:" << _gcell->getSouthEdges().size() << endl;
cdebug_log(110,0) << this << endl;
++_iedge;
while (_stateFlags) {
if (_stateFlags.contains(Flags::EastSide)) {
if ( (_iedge < _gcell->getEastEdges().size())
and _filterFlags.contains(Flags::EastSide)) break;
//cdebug_log(110,0) << "Switching to North side." << endl;
_stateFlags = Flags::NorthSide;
_iedge = 0;
// cdebug_log(110,0) << this << endl;
continue;
}
if (_stateFlags.contains(Flags::NorthSide)) {
if ( (_iedge < _gcell->getNorthEdges().size())
and _filterFlags.contains(Flags::NorthSide)) break;
//cdebug_log(110,0) << "Switching to West side." << endl;
_stateFlags = Flags::WestSide;
_iedge = 0;
// cdebug_log(110,0) << this << endl;
continue;
}
if (_stateFlags.contains(Flags::WestSide)) {
if ( (_iedge < _gcell->getWestEdges().size())
and _filterFlags.contains(Flags::WestSide)) break;
//cdebug_log(110,0) << "Switching to South side." << endl;
_stateFlags = Flags::SouthSide;
_iedge = 0;
continue;
}
if (_stateFlags.contains(Flags::SouthSide)) {
if ( (_iedge < _gcell->getSouthEdges().size())
and _filterFlags.contains(Flags::SouthSide)) break;
//cdebug_log(110,0) << "All edges done." << endl;
_stateFlags = 0;
_iedge = 0;
break;;
}
}
cdebug_log(110,0) << "GCell_Edges::Locator::progress() [to] " << _stateFlags << " iedge:" << _iedge << endl;
}
string GCell_Edges::Locator::_getString () const
{
string s = "<GCell_Edges::Locator";
if (_stateFlags.contains(Flags::EastSide )) s += " East[" + getString(_iedge) + "]";
if (_stateFlags.contains(Flags::NorthSide)) s += " North[" + getString(_iedge) + "]";
if (_stateFlags.contains(Flags::WestSide )) s += " West[" + getString(_iedge) + "]";
if (_stateFlags.contains(Flags::SouthSide)) s += " South[" + getString(_iedge) + "]";
if (_stateFlags == 0) s += " invalid";
s += ">";
return s;
}
EdgesHC* GCell_Edges::getClone () const
{ return new GCell_Edges (*this); }
EdgesHL* GCell_Edges::getLocator () const
{ return new Locator (_gcell,_filterFlags); }
string GCell_Edges::_getString () const
{
string s = "<GCell_Edges "
+ getString(_gcell)
+ ">";
return s;
}
// -------------------------------------------------------------------
// Class : "Anabatic::Path_Edges".
Path_Edges::Locator::Locator ( const GCell* source, const GCell* target, Flags pathFlags )
: EdgesHL()
, _source (source)
, _target (target)
, _stateFlags(Flags::NoFlags)
, _uprobe (0)
, _edge (NULL)
{
if (_source == _target) return;
Interval hoverlap = _source->getHSide().getIntersection( _target->getHSide() );
Interval voverlap = _source->getVSide().getIntersection( _target->getVSide() );
if (not voverlap.isEmpty()) {
if (_source->getXMin() > _target->getXMin()) std::swap( _source, _target );
_stateFlags |= Flags::EastSide;
_uprobe = voverlap.getCenter();
} else if (not hoverlap.isEmpty()) {
if (_source->getYMin() > _target->getYMin()) std::swap( _source, _target );
_stateFlags |= Flags::NorthSide;
_uprobe = hoverlap.getCenter();
} else {
if (_source->getXMin() > _target->getXMin()) {
std::swap( _source, _target );
}
if (_source->getYMin() < _target->getYMin()) {
if (pathFlags & Flags::NorthPath) {
_stateFlags |= Flags::NorthSide;
_uprobe = _source->getXCenter();
} else {
_stateFlags |= Flags::EastSide;
_uprobe = _source->getYCenter();
}
} else {
if (pathFlags & Flags::NorthPath) {
_stateFlags |= Flags::EastSide;
_uprobe = _source->getYCenter();
} else {
_stateFlags |= Flags::SouthSide;
_uprobe = _source->getXCenter();
}
}
}
_edge = _source->getEdgeAt( _stateFlags, _uprobe );
}
EdgesHL* Path_Edges::Locator::getClone () const
{ return new Locator (*this); }
Edge* Path_Edges::Locator::getElement () const
{ return _edge; }
bool Path_Edges::Locator::isValid () const
{ return (_edge != NULL); }
void Path_Edges::Locator::progress ()
{
if (not _edge) return;
GCell* neighbor = NULL;
if (_stateFlags.contains(Flags::SouthSide) or _stateFlags.contains(Flags::WestSide)) neighbor = _edge->getSource();
if (_stateFlags.contains(Flags::NorthSide) or _stateFlags.contains(Flags::EastSide)) neighbor = _edge->getTarget();
if (neighbor == _target) { _edge = NULL; return; }
if (_stateFlags.contains(Flags::EastSide)) {
Interval overlap = neighbor->getHSide().getIntersection( _target->getHSide() );
if (not overlap.isEmpty()) {
overlap = neighbor->getVSide().getIntersection( _target->getVSide() );
if (not overlap.isEmpty()) { _edge = NULL; return; }
_stateFlags.reset( Flags::EastSide );
_stateFlags |= (_target->getYMin() < _source->getYMin()) ? Flags::SouthSide
: Flags::NorthSide;
_uprobe = overlap.getCenter();
}
} else if (_stateFlags.contains(Flags::SouthSide)) {
Interval overlap = neighbor->getVSide().getIntersection( _target->getVSide() );
if (not overlap.isEmpty()) {
overlap = neighbor->getHSide().getIntersection( _target->getHSide() );
if (not overlap.isEmpty()) {
_edge = NULL; return; }
_stateFlags.reset( Flags::SouthSide );
_stateFlags |= Flags::EastSide;
_uprobe = overlap.getCenter();
}
} else if (_stateFlags.contains(Flags::NorthSide)) {
Interval overlap = neighbor->getVSide().getIntersection( _target->getVSide() );
if (not overlap.isEmpty()) {
overlap = neighbor->getHSide().getIntersection( _target->getHSide() );
if (not overlap.isEmpty()) { _edge = NULL; return; }
_stateFlags.reset( Flags::NorthSide );
_stateFlags |= Flags::EastSide;
_uprobe = overlap.getCenter();
}
}
_edge = neighbor->getEdgeAt( _stateFlags, _uprobe );
}
string Path_Edges::Locator::_getString () const
{
string s = "<Path_Edges::Locator @" + getString(_edge) + ">";
return s;
}
EdgesHC* Path_Edges::getClone () const
{ return new Path_Edges( *this ); }
EdgesHL* Path_Edges::getLocator () const
{ return new Locator (_source,_target,_pathFlags); }
string Path_Edges::_getString () const
{
string s = "<Path_Edges from:"
+ getString(_source) + "to:"
+ getString(_target)
+ ">";
return s;
}
} // Anabatic namespace.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,189 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "Matrix.cpp<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Matrix.cpp" |
// +-----------------------------------------------------------------+
#include <sstream>
#include <iostream>
#include <iomanip>
#include "hurricane/Cell.h"
#include "anabatic/Matrix.h"
#include "anabatic/GCell.h"
namespace Anabatic {
using std::cout;
using std::cerr;
using std::endl;
using std::setw;
using std::setfill;
using std::ostringstream;
using Hurricane::Error;
Matrix::Matrix ()
: _area ()
, _side (1)
, _gcells()
, _imax (0)
, _jmax (0)
{ }
Matrix::Matrix ( Box area, DbU::Unit side )
: _area (area)
, _side (side)
, _gcells()
, _imax (0)
, _jmax (0)
{
_imax = _area.getWidth () / side + ((_area.getWidth () % side) ? 1 : 0);
_jmax = _area.getHeight() / side + ((_area.getHeight() % side) ? 1 : 0);
_gcells.resize( _imax*_jmax );
}
Matrix::~Matrix ()
{ }
void Matrix::setCell ( Cell* cell, DbU::Unit side )
{
_area = cell->getAbutmentBox();
_side = side;
_imax = _area.getWidth () / side + ((_area.getWidth () % side) ? 1 : 0);
_jmax = _area.getHeight() / side + ((_area.getHeight() % side) ? 1 : 0);
_gcells.resize( _imax*_jmax );
cdebug_log(110,0) << "Matrix::setCell(): " << this << endl;
}
GCell* Matrix::getUnder ( DbU::Unit x, DbU::Unit y ) const
{
if (x == _area.getXMax()) --x;
if (y == _area.getYMax()) --y;
int index = xy2maxIndex(x,y);
cdebug_log(110,0) << "Matrix::getUnder() ("
<< DbU::getValueString(x) << " "
<< DbU::getValueString(y) << ") index:" << index
<< " " << ((index < 0) ? NULL : _gcells[index]->getUnder(x,y)) << endl;
return (index < 0) ? NULL : _gcells[index]->getUnder(x,y);
}
void Matrix::updateLookup ( GCell* gcell )
{
cdebug_log(110,1) << "Matrix::updateLookup(): " << gcell << endl;
if (gcell->isFlat()) {
cdebug_log(110,0) << " GCell is flat, no update." << endl;
cdebug_tabw(110,-1);
return;
}
Box gcellBb = gcell->getBoundingBox();
Box updateArea = _area.getIntersection( gcellBb );
cdebug_log(110,0) << "_side: " << DbU::getValueString(_side) << endl;
cdebug_log(110,0) << "_area: " << _area << endl;
cdebug_log(110,0) << "updateArea: " << updateArea << endl;
if (updateArea.isEmpty()) {
cerr << Error( "Matrix::updateLookup(): %s is not under area of %s."
, getString(gcell).c_str()
, getString(this).c_str()
) << endl;
}
Index indexMin = Index::asMin( this, updateArea.getXMin(), updateArea.getYMin() );
Index indexMax = Index::asMax( this, updateArea.getXMax(), updateArea.getYMax() );
int xspan = indexMax.i() - indexMin.i();
DbU::Unit dx = updateArea.getXMin() - _area.getXMin();
DbU::Unit dy = updateArea.getYMin() - _area.getYMin();
cdebug_log(110,0) << "raw_i:" << (dx / _side + ((dx%_side) ? 1 : 0))
<< " raw_j:" << (dy / _side + ((dy%_side) ? 1 : 0)) << endl;
cdebug_log(110,0) << "indexMin:" << indexMin << endl;
cdebug_log(110,0) << "indexMax:" << indexMax << endl;
cdebug_log(110,0) << "xspan: " << xspan << endl;
if (not indexMin.valid() or not indexMax.valid()) { cdebug_tabw(110,-1); return; }
int index = indexMin.index();
while ( index <= indexMax.index() ) {
cdebug_log(110,0) << "i,j = " << index2i(index) << "," << index2j(index)
<< " " << getGridPoint(index) << endl;
if (updateArea.contains(getGridPoint(index))) _gcells[index] = gcell;
if (index2j(index) <= indexMax.j()) ++index;
else index += _imax - xspan;
}
cdebug_tabw(110,-1);
}
void Matrix::resize ( Cell* cell, const vector<GCell*>& gcells )
{
setCell( cell, _side );
for ( GCell* gcell : gcells ) updateLookup( gcell );
}
void Matrix::show () const
{
cdebug_log(111,0) << this << endl;
for ( size_t i=0 ; i<_gcells.size() ; ++i ) {
//cdebug_log(111,0) << "[" << setw(3) << setfill('0') << i << setfill(' ') << "] ("
// << setw(3) << index2i(i) << ","
// << setw(3) << index2j(i) << ") " << _gcells[i] << endl;
cdebug_log(111,0) << "[" << i << "] ("
<< index2i(i) << ","
<< index2j(i) << ") " << _gcells[i] << endl;
}
}
string Matrix::_getTypeName () const
{ return "Matrix"; }
string Matrix::_getString () const
{
ostringstream os;
os << "<" << _getTypeName() << " " << _imax << "x" << _jmax
<< " " << _area << "/" << DbU::getValueString(_side) << ">";
return os.str();
}
Record* Matrix::_getRecord () const
{
Record* record = new Record( _getString() );
record->add( getSlot ("_area" , _area ) );
record->add( DbU::getValueSlot("_side" , &_side ) );
record->add( getSlot ("_imax" , _imax ) );
record->add( getSlot ("_jmax" , _jmax ) );
record->add( getSlot ("_gcells", &_gcells) );
return record;
}
} // Anabatic namespace;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,643 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./NetBuilderHybridVH.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Breakpoint.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DebugSession.h"
#include "hurricane/Layer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/DataBase.h"
#include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/NetRoutingProperty.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/RoutingPads.h"
#include "hurricane/Pin.h"
#include "hurricane/Pad.h"
#include "hurricane/Plug.h"
#include "hurricane/Cell.h"
#include "hurricane/Instance.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "crlcore/AllianceFramework.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/Measures.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoContactHTee.h"
#include "anabatic/AutoContactVTee.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/NetBuilderHybridVH.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using std::swap;
using Hurricane::Error;
using Hurricane::Pin;
NetBuilderHybridVH::NetBuilderHybridVH ()
: NetBuilder()
{ }
NetBuilderHybridVH::~NetBuilderHybridVH () { }
string NetBuilderHybridVH::getStyle ()
{ return "VH,2RL"; }
void NetBuilderHybridVH::doRp_AutoContacts ( GCell* gcell
, Component* rp
, AutoContact*& source
, AutoContact*& target
, uint64_t flags
)
{
throw Error ( "%s::dpRp_AutoContacts() method must never be called.", getTypeName().c_str() );
}
AutoContact* NetBuilderHybridVH::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags )
{
cdebug_log(145,1) << getTypeName() << "::doRp_Access()" << endl;
cdebug_log(145,0) << rp << endl;
const Layer* rpLayer = rp->getLayer();
//const Layer* viaLayer = Session::getDContactLayer();
DbU::Unit viaSide = Session::getDContactWidth();
Point position = rp->getCenter();
AutoContact* rpContact = AutoContactTerminal::create( gcell, rp, rpLayer, position, viaSide, viaSide );
cdebug_tabw(145,-1);
return rpContact;
}
AutoContact* NetBuilderHybridVH::doRp_AccessNorthSouthPin ( GCell* gcell, RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_AccessNorthSouthPin() " << rp << endl;
AutoContact* rpContact = doRp_Access( gcell, rp, NoFlags );
AutoContact* turn = NULL;
Net* net = rp->getNet();
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
if (pinDir == Pin::AccessDirection::NORTH) {
turn = AutoContactTurn::create( gcell, net, Session::getBuildRoutingLayer(0) );
AutoSegment* segment = AutoSegment::create( rpContact, turn, Flags::Vertical );
segment->setAxis( rp->getX(), Flags::Force );
segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
rpContact = turn;
turn = AutoContactTurn::create( gcell, net, Session::getBuildContactLayer(0) );
segment = AutoSegment::create( rpContact, turn, Flags::Horizontal );
rpContact = turn;
DbU::Unit axis = gcell->getYMax() - Session::getDHorizontalPitch();
cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl;
segment->setAxis( axis, Flags::Force );
//segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis );
cdebug_log(145,0) << segment << endl;
} else {
turn = rpContact;
}
cdebug_tabw(145,-1);
return turn;
}
AutoContact* NetBuilderHybridVH::doRp_AccessEastWestPin ( GCell* gcell, RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_AccessEastWestPin() " << rp << endl;
Net* net = rp->getNet();
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
AutoContact* rpContact = doRp_Access( gcell, rp, NoFlags );
AutoContact* turn = NULL;
AutoSegment* segment = NULL;
turn = AutoContactTurn::create( gcell, net, Session::getBuildContactLayer(0) );
segment = AutoSegment::create( rpContact, turn, Flags::Horizontal );
segment->setAxis( pin->getCenter().getY(), Flags::Force );
rpContact = turn;
turn = AutoContactTurn::create( gcell, net, Session::getBuildContactLayer(0) );
segment = AutoSegment::create( rpContact, turn, Flags::Vertical );
DbU::Unit axis = 0;
if (pinDir == Pin::AccessDirection::EAST)
axis = gcell->getXMax() - Session::getDVerticalPitch();
else
axis = gcell->getXMin() + Session::getDVerticalPitch();
segment->setAxis( axis );
cdebug_tabw(145,-1);
return turn;
}
bool NetBuilderHybridVH::doRp_xG_1M1 ( RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_xG_1M1()" << endl;
AutoContact* swContact = nullptr;
if (west() or south()) {
AutoContact* termContact = doRp_Access( getGCell(), rp, NoFlags );
if (west() and south()) {
swContact = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( termContact, swContact, Flags::Vertical );
} else {
if (west()) {
swContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( termContact, swContact, Flags::Vertical );
} else
swContact = termContact;
}
setSouthWestContact( swContact );
}
AutoContact* neContact = nullptr;
if (east() or north()) {
AutoContact* termContact = doRp_Access( getGCell(), rp, NoFlags );
if (east() and north()) {
neContact = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( termContact, neContact, Flags::Vertical );
} else {
if (east()) {
neContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( termContact, neContact, Flags::Vertical );
} else
neContact = termContact;
}
setNorthEastContact( neContact );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_xG_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_1M1()" << endl;
doRp_xG_1M1( getRoutingPads()[0] );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_2G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_1M1()" << endl;
doRp_xG_1M1( getRoutingPads()[0] );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::doRp_xG_xM1_xM3 ( const vector<RoutingPad*>& rps )
{
cdebug_log(145,1) << getTypeName() << "::doRp_xG_xM1()" << endl;
AutoContact* prevContact = nullptr;
AutoContact* currContact = nullptr;
for ( size_t i=0 ; i<rps.size() ; ++i ) {
prevContact = currContact;
AutoContact* currTerm = doRp_Access( getGCell(), rps[i], NoFlags );
if (i == 0) {
if (west() or south()) {
AutoContact* swContact = nullptr;
currContact = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
if (west() and south()) {
swContact = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
} else {
if (west())
swContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
else
swContact = currContact;
}
if (swContact != currContact)
AutoSegment::create( currContact, swContact, Flags::Vertical );
setSouthWestContact( swContact );
} else {
currContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
}
AutoSegment::create( currTerm, currContact, Flags::Vertical );
continue;
}
if (i+1 == rps.size()) {
if (east() or north()) {
AutoContact* neContact = nullptr;
currContact = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
if (east() and north()) {
neContact = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
} else {
if (east())
neContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
else
neContact = currContact;
}
if (neContact != currContact)
AutoSegment::create( currContact, neContact, Flags::Vertical );
setNorthEastContact( neContact );
} else {
currContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
}
} else {
currContact = AutoContactHTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
}
AutoSegment::create( currTerm , currContact, Flags::Vertical );
AutoSegment::create( prevContact, currContact, Flags::Horizontal );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_xG_xM1_xM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_xM1()" << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
doRp_xG_xM1_xM3( getRoutingPads() );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_1G_xM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_xM1()" << endl;
if (getConnexity().fields.M1 == 1)
_do_xG_1M1();
else
_do_xG_xM1_xM3();
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_xG ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG()" << endl;
const Layer* viaLayer = Session::getBuildContactLayer( 0 );
if (getConnexity().fields.globals == 2) {
setBothCornerContacts( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
} else if (getConnexity().fields.globals == 3) {
if (east() and west()) {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer ) );
if (south()) swapCornerContacts();
AutoSegment::create( getSouthWestContact(), getNorthEastContact(), Flags::Vertical );
} else {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer ) );
if (west()) swapCornerContacts();
AutoSegment::create( getSouthWestContact(), getNorthEastContact(), Flags::Horizontal );
}
} else { // fields.globals == 4.
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
setSouthWestContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer ) );
AutoSegment::create( getSouthWestContact(), turn, Flags::Horizontal );
AutoSegment::create( turn, getNorthEastContact(), Flags::Vertical );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_1G_1PinM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM1() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpContact = doRp_AccessNorthSouthPin( getGCell(), getRoutingPads()[0] );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( rpContact, turn1, Flags::Vertical );
if (north() or south()) {
AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( turn1, turn2, Flags::Horizontal );
turn1 = turn2;
}
setBothCornerContacts( turn1 );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_2G_1PinM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_1PinM1() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpContact = doRp_AccessNorthSouthPin( getGCell(), getRoutingPads()[0] );
AutoContact* tee = nullptr;
if (east() and west()) {
tee = AutoContactHTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
} else {
tee = AutoContactVTee::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
}
AutoSegment::create( rpContact, tee, Flags::Vertical );
setBothCornerContacts( tee );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_1G_xM1_1PinM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_xM1_1PinM1() [Managed Configuration - Optimized] " << getTopology() << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
RoutingPad* rpM2 = nullptr;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) rpM2 = rp;
else rpsM1.push_back( rp );
}
if (rpsM1.size() > 1)
doRp_xG_xM1_xM3( rpsM1 );
else
doRp_xG_1M1( rpsM1[0] );
AutoContact* rpContact = doRp_AccessNorthSouthPin( getGCell(), rpM2 );
AutoContact* rpM1Contact = doRp_Access( getGCell(), rpsM1.front(), NoFlags );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( rpM1Contact, turn1, Flags::Vertical );
AutoSegment::create( rpContact , turn2, Flags::Vertical );
AutoSegment::create( turn1 , turn2, Flags::Horizontal );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::doRp_1G_1PinM2 ( RoutingPad* rp )
{
cdebug_log(145,1) << getTypeName() << "::doRp_1G_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpContact = doRp_AccessEastWestPin( getGCell(), rp );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( rpContact, turn1, Flags::Horizontal );
if (east() or west()) {
AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( turn1, turn2, Flags::Vertical );
turn1 = turn2;
}
setBothCornerContacts( turn1 );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_1G_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
doRp_1G_1PinM2( getRoutingPads()[0] );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_xG_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_1PinM2()" << endl;
AutoContact* rpContact = doRp_AccessEastWestPin( getGCell(), getRoutingPads()[0] );
AutoContact* neContact = nullptr;
AutoContact* swContact = nullptr;
const Layer* viaLayer = Session::getBuildContactLayer( 0 );
if (getConnexity().fields.globals == 2) {
if (north() and south())
neContact = AutoContactVTee::create( getGCell(), getNet(), viaLayer );
else
neContact = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
AutoSegment::create( rpContact, neContact, Flags::Horizontal );
setBothCornerContacts( neContact );
} else if (getConnexity().fields.globals == 3) {
swContact = AutoContactVTee::create( getGCell(), getNet(), viaLayer );
neContact = AutoContactVTee::create( getGCell(), getNet(), viaLayer );
if (west())
AutoSegment::create( rpContact, neContact, Flags::Horizontal );
else
AutoSegment::create( rpContact, swContact, Flags::Horizontal );
AutoSegment::create( swContact, neContact, Flags::Vertical );
setNorthEastContact( neContact );
setSouthWestContact( swContact );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_1G_xM1_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_xM1_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
vector<RoutingPad*> rpsM1;
RoutingPad* rpM2 = nullptr;
for ( RoutingPad* rp : getRoutingPads() ) {
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) rpM2 = rp;
else rpsM1.push_back( rp );
}
if (rpsM1.size() > 1)
doRp_xG_xM1_xM3( rpsM1 );
else
doRp_xG_1M1( rpsM1[0] );
Pin* pin = dynamic_cast<Pin*>( rpM2->getOccurrence().getEntity() );
Pin::AccessDirection pinDir = pin->getAccessDirection();
AutoContact* rpContact = doRp_AccessEastWestPin( getGCell(), rpM2 );
AutoContact* rpM1Contact = nullptr;
if (pinDir == Pin::AccessDirection::EAST)
rpM1Contact = doRp_Access( getGCell(), rpsM1.back(), NoFlags );
else
rpM1Contact = doRp_Access( getGCell(), rpsM1.front(), NoFlags );
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( rpM1Contact, turn, Flags::Vertical );
AutoSegment::create( rpContact , turn, Flags::Horizontal );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderHybridVH::_do_1G_1M1 () { return false; }
// bool NetBuilderHybridVH::_do_xG_1Pad () { return false; }
// bool NetBuilderHybridVH::_do_xG_xM2 () { return false; }
// bool NetBuilderHybridVH::_do_1G_1M3 () { return false; }
// bool NetBuilderHybridVH::_do_xG_xM3 () { return false; }
// bool NetBuilderHybridVH::_do_xG_1M1_1M2 () { return false; }
// bool NetBuilderHybridVH::_do_4G_1M2 () { return false; }
bool NetBuilderHybridVH::_do_2G () { return false; }
bool NetBuilderHybridVH::_do_globalSegment ()
{
cdebug_log(145,1) << getTypeName() << "::_do_globalSegment()" << endl;
cdebug_log(145,0) << "getSourceFlags():" << getSourceFlags()
<< " getFlags():" << getFlags() << endl;
if (getSourceContact()) {
uint64_t segmentBound = getSegmentHookType( getFromHook() );
AutoContact* targetContact
= (segmentBound & (NorthBound|EastBound)) ? getNorthEastContact() : getSouthWestContact() ;
if (not getFromHook()) cerr << "getFromHook() is NULL !" << endl;
AutoContact* sourceContact = getSourceContact();
if (segmentBound & (NorthBound|SouthBound)) {
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( sourceContact, turn, Flags::Vertical );
sourceContact = AutoContactTurn::create( getGCell(), getNet(), Session::getBuildContactLayer(0) );
AutoSegment::create( sourceContact, turn, Flags::Horizontal );
}
Segment* baseSegment = static_cast<Segment*>( getFromHook()->getComponent() );
AutoSegment* globalSegment = AutoSegment::create( sourceContact
, targetContact
, baseSegment
);
globalSegment->setFlags( (getDegree() == 2) ? AutoSegment::SegBipoint : 0 );
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
// HARDCODED VALUE.
if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
addToFixSegments( globalSegment );
if (getConnexity().fields.globals < 2) {
cdebug_tabw(145,-1);
return false;
}
} else
setFromHook( NULL );
push( east (), getNorthEastContact() );
push( west (), getSouthWestContact() );
push( north(), getNorthEastContact() );
push( south(), getSouthWestContact() );
cdebug_tabw(145,-1);
return true;
}
void NetBuilderHybridVH::singleGCell ( AnabaticEngine* anbt, Net* net )
{
cdebug_log(145,1) << getTypeName() << "::singleGCell() " << net << endl;
vector<RoutingPad*> rps;
for ( RoutingPad* irp : net->getRoutingPads() )
rps.push_back( irp );
if (rps.size() < 2) {
cerr << Error( "%s::singleGCell(): For %s, less than two Plugs/Pins (%d)."
, getTypeName().c_str()
, getString(net).c_str()
, rps.size() ) << endl;
cdebug_tabw(145,-1);
return;
}
sortRpByX( rps, NetBuilder::NoFlags ); // increasing X.
GCell* gcell1 = anbt->getGCellUnder( rps.front()->getCenter() );
GCell* gcell2 = anbt->getGCellUnder( rps.back ()->getCenter() );
if (not gcell1) {
cerr << Error( "No GCell under %s.", getString(rps.front()).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (gcell1 != gcell2) {
cerr << Error( "Not under a single GCell %s.", getString(rps.back()).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
AutoContact* prevContact = nullptr;
AutoContact* currContact = nullptr;
for ( size_t i=0 ; i<rps.size() ; ++i ) {
prevContact = currContact;
AutoContact* currTerm = doRp_Access( gcell1, rps[i], NoFlags );
if (i == 0) {
currContact = AutoContactTurn::create( gcell1, net, Session::getBuildContactLayer(0) );
AutoSegment::create( currTerm, currContact, Flags::Vertical );
continue;
}
if (i+1 == rps.size()) {
currContact = AutoContactTurn::create( gcell1, net, Session::getBuildContactLayer(0) );
} else {
currContact = AutoContactHTee::create( gcell1, net, Session::getBuildContactLayer(0) );
}
AutoSegment::create( currTerm , currContact, Flags::Vertical );
AutoSegment::create( prevContact, currContact, Flags::Horizontal );
}
cdebug_tabw(145,-1);
}
string NetBuilderHybridVH::getTypeName () const
{ return "NetBuilderHybridVH"; }
} // Anabatic namespace.

View File

@ -1,356 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./NetBuilderM2.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Breakpoint.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DebugSession.h"
#include "hurricane/Layer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/DataBase.h"
#include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/NetRoutingProperty.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/RoutingPads.h"
#include "hurricane/Pad.h"
#include "hurricane/Plug.h"
#include "hurricane/Cell.h"
#include "hurricane/Instance.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "crlcore/AllianceFramework.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/Measures.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoContactHTee.h"
#include "anabatic/AutoContactVTee.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/NetBuilderM2.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using std::swap;
NetBuilderM2::NetBuilderM2 ()
: NetBuilder()
{ }
NetBuilderM2::~NetBuilderM2 () { }
string NetBuilderM2::getStyle ()
{ return "2RL-"; }
void NetBuilderM2::doRp_AutoContacts ( GCell* gcell
, Component* rp
, AutoContact*& source
, AutoContact*& target
, uint64_t flags
)
{
cdebug_log(145,1) << "NetBuilderM2::doRp_AutoContacts()" << endl;
cdebug_log(145,0) << rp << endl;
source = target = NULL;
Point sourcePosition;
Point targetPosition;
const Layer* rpLayer = rp->getLayer();
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
Flags direction = Session::getDirection ( rpDepth );
DbU::Unit viaSide = Session::getViaWidth ( rpDepth );
getPositions( rp, sourcePosition, targetPosition );
if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition );
if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition );
GCell* sourceGCell = Session::getAnabatic()->getGCellUnder( sourcePosition );
GCell* targetGCell = Session::getAnabatic()->getGCellUnder( targetPosition );
if (rpDepth == 0) {
rpLayer = Session::getContactLayer(0);
direction = Flags::Horizontal;
viaSide = Session::getViaWidth( rpDepth );
}
// Non-M1 terminal or punctual M1 protections.
if ((rpDepth != 0) or (sourcePosition == targetPosition)) {
map<Component*,AutoSegment*>::iterator irp = getRpLookup().find( rp );
if (irp == getRpLookup().end()) {
AutoContact* sourceProtect = AutoContactTerminal::create( sourceGCell
, rp
, rpLayer
, sourcePosition
, viaSide, viaSide
);
AutoContact* targetProtect = AutoContactTerminal::create( targetGCell
, rp
, rpLayer
, targetPosition
, viaSide, viaSide
);
sourceProtect->setFlags( CntFixed );
targetProtect->setFlags( CntFixed );
AutoSegment* segment = AutoSegment::create( sourceProtect, targetProtect, direction );
segment->setFlags( AutoSegment::SegFixed );
getRpLookup().insert( make_pair(rp,segment) );
}
}
if (sourcePosition != targetPosition) {
if (flags & DoSourceContact)
source = AutoContactTerminal::create( sourceGCell
, rp
, rpLayer
, sourcePosition
, viaSide, viaSide
);
if (flags & DoTargetContact)
target = AutoContactTerminal::create( targetGCell
, rp
, rpLayer
, targetPosition
, viaSide, viaSide
);
}
if (not source and not target) {
source = target = AutoContactTerminal::create( gcell
, rp
, rpLayer
, rp->getCenter()
, viaSide, viaSide
);
}
cdebug_tabw(145,-1);
return;
}
AutoContact* NetBuilderM2::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags )
{
cdebug_log(145,1) << getTypeName() << "::doRp_Access()" << endl;
cdebug_log(145,0) << rp << endl;
Point sourcePosition;
Point targetPosition;
const Layer* rpLayer = rp->getLayer();
const Layer* viaLayer = Session::getDContactLayer();
DbU::Unit viaSide = Session::getDContactWidth();
DbU::Unit ypitch = Session::getDVerticalPitch();
getPositions( rp, sourcePosition, targetPosition );
if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition );
if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition );
Point position = rp->getCenter();
if (not (flags & Middle)) {
if (flags & NorthBound) position = targetPosition;
if (flags & SouthBound) position = sourcePosition;
}
DbU::Unit ycontact = (flags & SouthBound) ? gcell->getYMin() : gcell->getYMax()-ypitch;
AutoContact* rpContact = AutoContactTerminal::create( gcell, rp, rpLayer, position, viaSide, viaSide );
AutoContact* contact1 = AutoContactTurn::create( gcell, getNet(), viaLayer );
AutoContact* contact2 = AutoContactTurn::create( gcell, getNet(), viaLayer );
contact1->setPosition( position.getX(), ycontact );
contact2->setPosition( position.getX(), ycontact );
rpContact->setFlags( CntFixed );
contact1 ->setFlags( CntFixed );
contact2 ->setFlags( CntFixed );
AutoSegment* fixed = AutoSegment::create( rpContact, contact1, Flags::Vertical );
AutoSegment* dogleg = AutoSegment::create( contact1 , contact2, Flags::Horizontal|Flags::UseNonPref );
fixed ->setFlags( AutoSegment::SegFixed );
dogleg->setFlags( AutoSegment::SegFixed );
cdebug_tabw(145,-1);
return contact2;
}
bool NetBuilderM2::_do_1G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1()" << endl;
uint64_t flags = NoFlags;
if (north()) flags |= NorthBound;
else if (south()) flags |= SouthBound;
AutoContact* contact = NULL;
contact = doRp_Access( getGCell(), getRoutingPads()[0], flags );
setNorthEastContact( contact );
push( north(), contact, SouthWest );
push( south(), contact, SouthWest );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderM2::_do_2G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_1M1()" << endl;
AutoContact* contact = NULL;
contact = doRp_Access( getGCell(), getRoutingPads()[0], SouthBound|NorthBound );
push( north(), contact, SouthWest|Middle );
contact = doRp_Access( getGCell(), getRoutingPads()[0], SouthBound|NorthBound );
push( south(), contact, SouthWest|Middle );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderM2::_do_xG ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG()" << endl;
vector<Hook*> hooksNS = getNorths();
hooksNS.insert( hooksNS.end(), getSouths().begin(), getSouths().end() );
sortHookByX( hooksNS, NoFlags );
const Layer* viaLayer = Session::getDContactLayer();
AutoContact* contactW = NULL;
AutoContact* contactE = NULL;
// Simple turn.
if ( (west() and not east() and (hooksNS.size() == 1))
or (east() and not west() and (hooksNS.size() == 1)) ) {
contactW = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
push( west() , contactW, SouthWest );
push( east() , contactW, SouthWest );
push( hooksNS[0], contactW, SouthWest );
cdebug_tabw(145,-1);
return true;
}
// Simple HTee.
if (west() and east() and (hooksNS.size() == 1)) {
contactW = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
push( west() , contactW, SouthWest );
push( east() , contactW, SouthWest );
push( hooksNS[0], contactW, SouthWest );
cdebug_tabw(145,-1);
return true;
}
cdebug_log(145,0) << "West side processing." << endl;
// West side processing.
if (west()) {
contactW = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
push( west() , contactW, SouthWest );
push( hooksNS[0], contactW, SouthWest );
} else {
contactW = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
push( hooksNS[0], contactW, SouthWest );
}
cdebug_log(145,0) << "Middle processing." << endl;
// Middle (North & South) processing.
if (hooksNS.size() > 2) {
for ( size_t i=1 ; i<hooksNS.size()-1 ; ++i ) {
AutoContact* current = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
AutoSegment::create( contactW, current, Flags::Horizontal );
push( hooksNS[i], current, SouthWest );
contactW = current;
}
}
cdebug_log(145,0) << "East side processing." << endl;
// East side processing.
if (east()) {
contactE = AutoContactHTee::create( getGCell(), getNet(), viaLayer );
push( east(), contactE, SouthWest );
if (hooksNS.size() > 1)
push( hooksNS[hooksNS.size()-1], contactE, SouthWest );
} else {
contactE = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
push( hooksNS[hooksNS.size()-1], contactE, SouthWest );
}
AutoSegment::create( contactW, contactE, Flags::Horizontal );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderM2::_do_globalSegment ()
{
cdebug_log(145,1) << getTypeName() << "::_do_globalSegment()" << endl;
if (getSourceContact()) {
Segment* segment = static_cast <Segment*> ( getFromHook()->getComponent() );
AutoSegment* globalSegment = AutoSegment::create( getSourceContact(), getSouthWestContact(), segment );
globalSegment->setFlags( (getDegree() == 2) ? AutoSegment::SegBipoint : 0 );
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
// HARDCODED VALUE.
if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
addToFixSegments( globalSegment );
if (getConnexity().fields.globals < 2) {
cdebug_tabw(145,-1);
return false;
}
} else
setFromHook( NULL );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderM2::_do_1G_xM1 () { return false; }
bool NetBuilderM2::_do_xG_1Pad () { return false; }
bool NetBuilderM2::_do_1G_1PinM2 () { return false; }
bool NetBuilderM2::_do_xG_xM2 () { return false; }
bool NetBuilderM2::_do_1G_1M3 () { return false; }
bool NetBuilderM2::_do_xG_xM3 () { return false; }
bool NetBuilderM2::_do_xG_1M1_1M2 () { return false; }
bool NetBuilderM2::_do_xG_xM1_xM3 () { return false; }
bool NetBuilderM2::_do_4G_1M2 () { return false; }
bool NetBuilderM2::_do_2G () { return false; }
string NetBuilderM2::getTypeName () const
{ return "NetBuilderM2"; }
} // Anabatic namespace.

View File

@ -1,650 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2018-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./NetBuilderVH.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Breakpoint.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DebugSession.h"
#include "hurricane/Layer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/Technology.h"
#include "hurricane/DataBase.h"
#include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/NetRoutingProperty.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/RoutingPads.h"
#include "hurricane/Pad.h"
#include "hurricane/Pin.h"
#include "hurricane/Plug.h"
#include "hurricane/Cell.h"
#include "hurricane/Instance.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "crlcore/AllianceFramework.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/Measures.h"
#include "anabatic/AutoContactTerminal.h"
#include "anabatic/AutoContactTurn.h"
#include "anabatic/AutoContactHTee.h"
#include "anabatic/AutoContactVTee.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/NetBuilderVH.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using std::swap;
using Hurricane::Transformation;
using Hurricane::Warning;
using Hurricane::Error;
using Hurricane::Pin;
NetBuilderVH::NetBuilderVH ()
: NetBuilder()
{ }
NetBuilderVH::~NetBuilderVH () { }
string NetBuilderVH::getStyle ()
{ return "VH,3RL+"; }
void NetBuilderVH::doRp_AutoContacts ( GCell* gcell
, Component* rp
, AutoContact*& source
, AutoContact*& target
, uint64_t flags
)
{
cdebug_log(145,1) << getTypeName() << "::doRp_AutoContacts()" << endl;
cdebug_log(145,0) << rp << endl;
source = target = NULL;
Point sourcePosition;
Point targetPosition;
const Layer* rpLayer = rp->getLayer();
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
Flags direction = Session::getDirection ( rpDepth );
DbU::Unit viaSide = Session::getViaWidth ( rpDepth );
getPositions( rp, sourcePosition, targetPosition );
if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition );
if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition );
GCell* sourceGCell = Session::getAnabatic()->getGCellUnder( sourcePosition );
GCell* targetGCell = Session::getAnabatic()->getGCellUnder( targetPosition );
if (rpDepth == 0) {
rpLayer = Session::getContactLayer(0);
direction = Flags::Vertical;
viaSide = Session::getViaWidth( rpDepth );
RoutingPad* rrp = dynamic_cast<RoutingPad*>( rp );
if (rrp) {
// if (not getAnabatic()->getConfiguration()->selectRpComponent(rrp)) {
// cerr << Warning( "%s::doRp_AutoContacts(): %s has no components on grid."
// , getTypeName().c_str()
// , getString(rp).c_str() ) << endl;
// }
} else {
cerr << Warning( "%s::doRp_AutoContacts(): %s is *not* a RoutingPad."
, getTypeName().c_str()
, getString(rp).c_str() ) << endl;
}
}
// Non-M1 terminal or punctual M1 protections.
if ( (rpDepth != 0) or (sourcePosition == targetPosition) ) {
map<Component*,AutoSegment*>::iterator irp = getRpLookup().find( rp );
if (irp == getRpLookup().end()) {
AutoContact* sourceProtect = AutoContactTerminal::create( sourceGCell
, rp
, rpLayer
, sourcePosition
, viaSide, viaSide
);
AutoContact* targetProtect = AutoContactTerminal::create( targetGCell
, rp
, rpLayer
, targetPosition
, viaSide, viaSide
);
sourceProtect->setFlags( CntFixed );
targetProtect->setFlags( CntFixed );
AutoSegment* segment = AutoSegment::create( sourceProtect, targetProtect, direction );
segment->setFlags( AutoSegment::SegFixed );
getRpLookup().insert( make_pair(rp,segment) );
}
}
if (sourcePosition != targetPosition) {
if (flags & DoSourceContact)
source = AutoContactTerminal::create( sourceGCell
, rp
, rpLayer
, sourcePosition
, viaSide, viaSide
);
if (flags & DoTargetContact)
target = AutoContactTerminal::create( targetGCell
, rp
, rpLayer
, targetPosition
, viaSide, viaSide
);
}
if ( (rpDepth > 0) and not Session::getRoutingGauge()->isSuperPitched() ) {
rpLayer = Session::getContactLayer( rpDepth );
}
if (not source and not target) {
source = target = AutoContactTerminal::create( gcell
, rp
, rpLayer
, rp->getCenter()
, viaSide, viaSide
);
}
cdebug_tabw(145,-1);
return;
}
AutoContact* NetBuilderVH::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags )
{
cdebug_log(145,1) << getTypeName() << "::doRp_Access() - flags:" << flags << endl;
AutoContact* rpContactSource = NULL;
AutoContact* rpContactTarget = NULL;
const Layer* rpLayer = rp->getLayer();
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
flags |= checkRoutingPadSize( rp );
doRp_AutoContacts( gcell, rp, rpContactSource, rpContactTarget, flags );
if (rpDepth % 2 == 0) { // RP should be vertical (M1, M3).
if (not (flags & (HAccess|HAccessEW))) {
AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) );
AutoContact* subContact2 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) );
AutoSegment::create( rpContactSource, subContact1, Flags::Vertical , rpDepth+2 );
AutoSegment::create( subContact1, subContact2, Flags::Horizontal, rpDepth+1 );
rpContactSource = subContact2;
} else {
if (flags & VSmall) {
AutoContact* subContact1 = NULL;
if (flags & HAccessEW)
subContact1 = AutoContactHTee::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) );
else
subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) );
AutoSegment::create( rpContactSource, subContact1, Flags::Vertical );
rpContactSource = subContact1;
}
}
} else { // RP should be horizontal (M2).
if (flags & (HAccess|HAccessEW)) {
AutoContact* subContact1 = NULL;
if (flags & HAccessEW)
subContact1 = AutoContactHTee::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) );
else
subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) );
AutoSegment::create( rpContactSource, subContact1, Flags::Vertical, rpDepth+1 );
rpContactSource = subContact1;
}
}
cdebug_tabw(145,-1);
return rpContactSource;
}
bool NetBuilderVH::_do_1G_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
Pin* pin = dynamic_cast<Pin*>( getRoutingPads()[0]->getOccurrence().getEntity() );
if ( (pin->getAccessDirection() != Pin::AccessDirection::SOUTH)
and (pin->getAccessDirection() != Pin::AccessDirection::NORTH) ) {
cerr << Error( "%s::do_1G_1PinM2(): %s *must* be north or south."
, getTypeName().c_str()
, getString(pin).c_str() ) << endl;
}
uint64_t flags = NoFlags;
if (east()) { flags |= HAccess|VSmall; }
else if (west()) { flags |= HAccess|VSmall; }
setBothCornerContacts( doRp_Access(getGCell(),getRoutingPads()[0],flags) );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_xG_1PinM2 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_1PinM2() [Managed Configuration] " << getTopology() << endl;
Pin* pin = dynamic_cast<Pin*>( getRoutingPads()[0]->getOccurrence().getEntity() );
if ( (pin->getAccessDirection() != Pin::AccessDirection::SOUTH)
and (pin->getAccessDirection() != Pin::AccessDirection::NORTH) ) {
cerr << Error( "%s::do_xG_1PinM2(): %s *must* be north or south."
, getTypeName().c_str()
, getString(pin).c_str() ) << endl;
}
RoutingPad* rp = getRoutingPads()[0];
AutoContact* pinContact = NULL;
doRp_AutoContacts( getGCell(), rp, pinContact, pinContact, HSmall|VSmall );
if (not north() and not south()) {
AutoContact* subContact1 = AutoContactHTee::create( getGCell(), rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinContact, subContact1, Flags::Vertical );
setBothCornerContacts( subContact1 );
} else {
AutoContact* subContact1 = AutoContactVTee::create( getGCell(), rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinContact, subContact1, Flags::Vertical );
if (east() and west()) {
AutoContact* subContact2 = AutoContactVTee::create( getGCell(), rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( subContact1, subContact2, Flags::Vertical );
setSouthWestContact( (south()) ? subContact1 : subContact2 );
setNorthEastContact( (south()) ? subContact2 : subContact1 );
} else
setBothCornerContacts( subContact1 );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_1G_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl;
Pin* pin = dynamic_cast<Pin*>( getRoutingPads()[0]->getOccurrence().getEntity() );
if ( (pin->getAccessDirection() != Pin::AccessDirection::EAST)
and (pin->getAccessDirection() != Pin::AccessDirection::WEST) ) {
cerr << Error( "%s::do_1G_1PinM2(): %s *must* be east or west."
, getTypeName().c_str()
, getString(pin).c_str() ) << endl;
}
AutoContact* pinContact = NULL;
doRp_AutoContacts( getGCell(), getRoutingPads()[0], pinContact, pinContact, HSmall|VSmall );
if (east() or west()) {
AutoContact* subContact1 = AutoContactTurn::create( getGCell(), getRoutingPads()[0]->getNet(), Session::getContactLayer(1) );
AutoContact* subContact2 = AutoContactTurn::create( getGCell(), getRoutingPads()[0]->getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinContact , subContact1, Flags::Horizontal );
AutoSegment::create( subContact1, subContact2, Flags::Vertical );
pinContact = subContact2;
} else {
AutoContact* subContact1 = NULL;
subContact1 = AutoContactTurn::create( getGCell(), getRoutingPads()[0]->getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinContact, subContact1, Flags::Horizontal );
pinContact = subContact1;
}
setBothCornerContacts( pinContact );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_xG_1PinM3 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG_1PinM3() [Managed Configuration] " << getTopology() << endl;
RoutingPad* rp = getRoutingPads()[0];
Pin* pin = dynamic_cast<Pin*>( rp->getOccurrence().getEntity() );
if ( (pin->getAccessDirection() != Pin::AccessDirection::EAST)
and (pin->getAccessDirection() != Pin::AccessDirection::WEST) ) {
cerr << Error( "%s::do_xG_1PinM3(): %s *must* be east or west."
, getTypeName().c_str()
, getString(pin).c_str() ) << endl;
}
AutoContact* pinContact = NULL;
doRp_AutoContacts( getGCell(), rp, pinContact, pinContact, HSmall|VSmall );
if (not east() and not west()) {
AutoContact* subContact1 = AutoContactVTee::create( getGCell(), rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinContact, subContact1, Flags::Horizontal );
setBothCornerContacts( subContact1 );
} else {
AutoContact* subContact1 = AutoContactHTee::create( getGCell(), rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( pinContact, subContact1, Flags::Horizontal );
if (north() and south()) {
AutoContact* subContact2 = AutoContactHTee::create( getGCell(), rp->getNet(), Session::getContactLayer(1) );
AutoSegment::create( subContact1, subContact2, Flags::Horizontal );
setSouthWestContact( (west()) ? subContact1 : subContact2 );
setNorthEastContact( (west()) ? subContact2 : subContact1 );
} else
setBothCornerContacts( subContact1 );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_1G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1() [Managed Configuration - Optimized] " << getTopology() << endl;
uint64_t flags = NoFlags;
if (east()) { flags |= HAccess|VSmall; }
else if (west()) { flags |= HAccess|VSmall; }
setBothCornerContacts( doRp_Access(getGCell(),getRoutingPads()[0],flags) );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_1G_xM1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_1G_" << (int)getConnexity().fields.M1 << "M1() [Defered Configuration]" << endl;
_do_xG_xM1_xM3();
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_2G_1M1 ()
{
cdebug_log(145,1) << getTypeName() << "::_do_2G_1M1 [Managed Configuration]" << endl;
cdebug_log(145,0) << "north: " << north() << endl;
cdebug_log(145,0) << "south: " << south() << endl;
cdebug_log(145,0) << "east: " << east() << endl;
cdebug_log(145,0) << "west: " << west() << endl;
AutoContact* tee = NULL;
if (east() and west()) {
tee = doRp_Access( getGCell(), getRoutingPads()[0], HAccessEW|VSmall );
} else {
AutoContact* turn = doRp_Access( getGCell(), getRoutingPads()[0], HAccess|VSmall );
if (east() or west())
tee = AutoContactHTee::create( getGCell(), getNet(), Session::getDContactLayer() );
else
tee = AutoContactVTee::create( getGCell(), getNet(), Session::getDContactLayer() );
AutoSegment::create( turn, tee, Flags::Horizontal );
}
setBothCornerContacts( tee );
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_xG_xM1_xM3 ()
{
// Implicit hypothesis : we have at least two globals and at least one terminal.
cdebug_log(145,1) << getTypeName()
<< "::_do_xG_" << (int)getConnexity().fields.M1
<< "M1_" << (int)getConnexity().fields.M3
<< "M3() [G:" << (int)getConnexity().fields.globals << " Managed Configuration]" << endl;
cdebug_log(145,0) << "getConnexity(): " << getConnexity().connexity << endl;
cdebug_log(145,0) << "north: " << north() << endl;
cdebug_log(145,0) << "south: " << south() << endl;
cdebug_log(145,0) << "east: " << east() << endl;
cdebug_log(145,0) << "west: " << west() << endl;
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
size_t iLast = getRoutingPads().size()-1;
AutoContact* leftContact = NULL;
AutoContact* rightContact = NULL;
if (south() or west()) {
leftContact = doRp_Access( getGCell(), getRoutingPads()[0], HAccessEW|VSmall );
if (south() and west()) {
setSouthWestContact( AutoContactHTee::create( getGCell(), getNet(), Session::getDContactLayer() ) );
AutoSegment::create( getSouthWestContact(), leftContact, Flags::Horizontal );
} else {
if (west())
setSouthWestContact( leftContact );
else {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), Session::getDContactLayer() ) );
AutoSegment::create( leftContact, getSouthWestContact(), Flags::Horizontal );
}
}
} else {
leftContact = doRp_Access( getGCell(), getRoutingPads()[0], HAccess|VSmall );
}
for ( size_t i=1 ; i<getRoutingPads().size()-1 ; ++i ) {
rightContact = doRp_Access( getGCell(), getRoutingPads()[i], HAccessEW|VSmall );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
leftContact = rightContact;
}
if (north() or east()) {
if (getRoutingPads().size() > 1) {
rightContact = doRp_Access( getGCell(), getRoutingPads()[iLast], HAccessEW|VSmall );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
} else {
rightContact = leftContact;
}
if (north() and east()) {
setNorthEastContact( AutoContactHTee::create( getGCell(), getNet(), Session::getDContactLayer() ) );
AutoSegment::create( rightContact, getNorthEastContact(), Flags::Horizontal );
} else {
if (east())
setNorthEastContact( rightContact );
else {
setNorthEastContact( AutoContactTurn::create( getGCell(), getNet(), Session::getDContactLayer() ) );
AutoSegment::create( rightContact, getNorthEastContact(), Flags::Horizontal );
}
}
} else {
rightContact = doRp_Access( getGCell(), getRoutingPads()[iLast], HAccess|VSmall );
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_2G ()
{
cdebug_log(145,0) << getTypeName() << "::_do_2G()" << endl;
return _do_xG();
}
bool NetBuilderVH::_do_xG ()
{
cdebug_log(145,1) << getTypeName() << "::_do_xG()" << endl;
const Layer* viaLayer = Session::getDContactLayer();
if (getConnexity().fields.globals == 2) {
setBothCornerContacts( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
} else if (getConnexity().fields.globals == 3) {
if (east() and west()) {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer ) );
if (south()) swapCornerContacts();
AutoSegment::create( getSouthWestContact(), getNorthEastContact(), Flags::Vertical );
} else {
setSouthWestContact( AutoContactTurn::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer ) );
if (west()) swapCornerContacts();
AutoSegment::create( getSouthWestContact(), getNorthEastContact(), Flags::Horizontal );
}
} else { // fields.globals == 4.
AutoContact* turn = AutoContactTurn::create( getGCell(), getNet(), viaLayer );
setSouthWestContact( AutoContactHTee::create( getGCell(), getNet(), viaLayer ) );
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer ) );
AutoSegment::create( getSouthWestContact(), turn, Flags::Horizontal );
AutoSegment::create( turn, getNorthEastContact(), Flags::Vertical );
}
cdebug_tabw(145,-1);
return true;
}
bool NetBuilderVH::_do_globalSegment ()
{
cdebug_log(145,1) << getTypeName() << "::_do_globalSegment()" << endl;
if (getSourceContact()) {
AutoContact* targetContact
= ( getSegmentHookType(getFromHook()) & (NorthBound|EastBound) )
? getNorthEastContact() : getSouthWestContact() ;
AutoSegment* globalSegment = AutoSegment::create( getSourceContact()
, targetContact
, static_cast<Segment*>( getFromHook()->getComponent() )
);
globalSegment->setFlags( (getDegree() == 2) ? AutoSegment::SegBipoint : 0 );
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
// HARDCODED VALUE.
if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
addToFixSegments( globalSegment );
if (getConnexity().fields.globals < 2) {
cdebug_tabw(145,-1);
return false;
}
} else
setFromHook( NULL );
push( east (), getNorthEastContact() );
push( west (), getSouthWestContact() );
push( north(), getNorthEastContact() );
push( south(), getSouthWestContact() );
cdebug_tabw(145,-1);
return true;
}
void NetBuilderVH::singleGCell ( AnabaticEngine* anbt, Net* net )
{
cdebug_log(145,1) << getTypeName() << "::singleGCell() " << net << endl;
vector<RoutingPad*> rps;
for ( RoutingPad* rp : net->getRoutingPads() ) {
if (Session::getRoutingGauge()->getLayerDepth(rp->getLayer()) == 0) {
rps.push_back( rp );
continue;
}
cerr << Error( "%s::singleGCell(): Non metal1 terminals are not managed yet.\n"
" (%s)"
, getTypeName().c_str()
, getString(rp).c_str()
) << endl;
cdebug_tabw(145,-1);
return;
}
if (rps.size() < 2) {
cerr << Error( "%s::singleGCell(): For %s, less than two Plugs/Pins (%d)."
, getTypeName().c_str()
, getString(net).c_str()
, rps.size() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (rps.empty()) {
cerr << Error( "%s::singleGCell(): No terminals for Net \"%s\"."
, getTypeName().c_str()
, getString(net->getName()).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
sortRpByX( rps, NetBuilder::NoFlags ); // increasing X.
GCell* gcell1 = anbt->getGCellUnder( (*rps.begin ())->getCenter() );
GCell* gcell2 = anbt->getGCellUnder( (*rps.rbegin())->getCenter() );
if (not gcell1) {
cerr << Error( "%s::singleGCell(): No GCell under %s."
, getTypeName().c_str()
, getString(*(rps.begin())).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
if (gcell1 != gcell2) {
cerr << Error( "%s::singleGCell(): Not under a single GCell %s."
, getTypeName().c_str()
, getString(*(rps.rbegin())).c_str() ) << endl;
cdebug_tabw(145,-1);
return;
}
cdebug_log(145,0) << "singleGCell " << gcell1 << endl;
AutoContact* source = NULL;
AutoContact* target = NULL;
for ( size_t irp=1 ; irp<rps.size() ; ++irp ) {
source = doRp_Access( gcell1, rps[irp-1], HAccess|VSmall );
target = doRp_Access( gcell1, rps[irp ], HAccess|VSmall );
AutoSegment::create( source, target, Flags::Horizontal );
}
cdebug_tabw(145,-1);
}
string NetBuilderVH::getTypeName () const
{ return "NetBuilderVH"; }
} // Anabatic namespace.

View File

@ -1,288 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2013, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./NetConstraints.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/DebugSession.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Net.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Pad.h"
#include "hurricane/Plug.h"
#include "hurricane/Instance.h"
#include "hurricane/Vertical.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Cell.h"
#include "anabatic/AutoContact.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/Session.h"
#include "anabatic/AnabaticEngine.h"
namespace {
// \addtogroup NetConstraints
// \{
/* \function void propagateConstraintFromRp ( RoutingPad* rp )
* \param rp The \c RoutingPad starting point.
*
* Do a full constraint propagation starting from this \c RoutingPad.
*/
// \}
using namespace std;
using namespace CRL;
using namespace Hurricane;
using namespace Anabatic;
// -----------------------------------------------------------------
// Local Functions.
void propagateConstraintFromRp ( RoutingPad* rp )
{
cdebug_log(146,1) << "propagateConstraintFromRp() - " << rp << endl;
for ( Component* component : rp->getSlaveComponents() ) {
cdebug_log(146,0) << "slave component: " << component << endl;
AutoContact* sourceContact = Session::lookup( dynamic_cast<Contact*>(component) );
if (sourceContact) {
Box constraintBox = sourceContact->getConstraintBox();
cdebug_log(146,0) << "Start slave: " << sourceContact << endl;
cdebug_log(146,0) << "Constraint: " << constraintBox << endl;
set<AutoSegment*> verticalSegments;
set<AutoSegment*> horizontalSegments;
for ( AutoSegment* segment : sourceContact->getAutoSegments() ) {
cdebug_log(146,0) << "Examining: " << segment << endl;
AutoContact* targetContact = segment->getOppositeAnchor(sourceContact);
if (targetContact) {
if (segment->isHorizontal()) {
cdebug_log(146,0) << "On horizontal stack " << segment << endl;
horizontalSegments.insert( segment );
} else {
cdebug_log(146,0) << "On vertical stack " << segment << endl;
verticalSegments.insert( segment );
}
}
}
// Propagate constraint through horizontally aligned segments.
cdebug_log(146,0) << "Propagate constraint on horizontal segments" << endl;
for ( AutoSegment* horizontal : horizontalSegments ) {
AutoContact* contact = NULL;
for ( AutoSegment* aligned : horizontal->getAligneds(Flags::WithSelf) ) {
cdebug_log(146,0) << "aligned horizontal: " << aligned << endl;
contact = aligned->getAutoTarget();
cdebug_log(146,0) << "contact: " << contact << endl;
if (contact) {
cdebug_log(146,0) << "Apply to (target): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getYMin()
, constraintBox.getYMax()
, Flags::Horizontal|Flags::WarnOnError );
}
contact = aligned->getAutoSource();
cdebug_log(146,0) << "contact: " << contact << endl;
if (contact) {
cdebug_log(146,0) << "Apply to (source): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getYMin()
, constraintBox.getYMax()
, Flags::Horizontal|Flags::WarnOnError );
}
}
}
// Propagate constraint through vertically aligned segments.
cdebug_log(146,0) << "Propagate constraint on vertical segments" << endl;
for ( AutoSegment* vertical : verticalSegments ) {
AutoContact* contact = NULL;
for ( AutoSegment* aligned : vertical->getAligneds(Flags::WithSelf) ) {
cdebug_log(146,0) << "aligned vertical: " << aligned << endl;
contact = aligned->getAutoTarget();
if (contact) {
cdebug_log(146,0) << "Apply to (target): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getXMin()
, constraintBox.getXMax()
, Flags::Vertical|Flags::WarnOnError );
}
contact = aligned->getAutoSource();
if (contact) {
cdebug_log(146,0) << "Apply to (source): " << contact << endl;
contact->restrictConstraintBox( constraintBox.getXMin()
, constraintBox.getXMax()
, Flags::Vertical|Flags::WarnOnError );
}
}
}
}
}
cdebug_log(146,0) << "propagateConstraintFromRp() - Exit" << endl;
cdebug_tabw(146,-1);
}
} // Anonymous namespace.
namespace Anabatic {
using Hurricane::Cell;
void propagateDistanceFromRp ( RoutingPad* rp )
{
cdebug_log(146,1) << "propagateDistanceFromRp() - " << rp << endl;
unsigned int distance = 0;
vector< pair<AutoContact*,AutoSegment*> > currents;
vector< pair<AutoContact*,AutoSegment*> > successors;
for ( Component* component : rp->getSlaveComponents() ) {
cdebug_log(146,0) << "slave component: " << component << endl;
AutoContact* sourceContact = Session::lookup( dynamic_cast<Contact*>(component) );
if (sourceContact) {
cdebug_log(146,0) << "Start slave: " << sourceContact << endl;
for ( AutoSegment* segment : sourceContact->getAutoSegments() ) {
cdebug_log(146,0) << "Pushing: " << segment << endl;
currents.push_back( make_pair(sourceContact,segment) );
}
}
}
while ( not currents.empty() ) {
for ( size_t i = 0 ; i<currents.size() ; ++i ) {
AutoContact* source = currents[i].first;
AutoSegment* segment = currents[i].second;
if ( (distance == 1) and (segment->getRpDistance() == 1) ) {
vector<GCell*> gcells;
segment->getGCells( gcells );
if (gcells.size() < 3)
segment->setFlags( AutoSegment::SegUnbreakable );
}
if (distance >= segment->getRpDistance()) continue;
segment->setRpDistance( distance );
cdebug_log(146,0) << "Popped: " << segment << endl;
AutoContact* target = segment->getOppositeAnchor( source );
if (target) {
for ( AutoSegment* successor : target->getAutoSegments() ) {
if (successor == segment) continue;
// if (successor->isNonPref()) {
// cdebug_log(146,0) << "Pushing (non-pref): " << successor << endl;
// currents.push_back( make_pair(target,successor) );
// } else {
cdebug_log(146,0) << "Pushing: " << successor << endl;
successors.push_back( make_pair(target,successor) );
// }
}
}
}
if (++distance > 15) break;
currents.clear();
currents.swap( successors );
}
cdebug_log(146,0) << "propagateDistanceFromRp() - Exit" << endl;
cdebug_tabw(146,-1);
}
void AnabaticEngine::computeNetConstraints ( Net* net )
{
DebugSession::open( net, 146, 150);
cdebug_log(149,0) << "Anabatic::computeNetConstraints( " << net << " )" << endl;
cdebug_tabw(146,1);
vector<RoutingPad*> routingPads;
for ( Component* component : net->getComponents() ) {
Contact* contact = dynamic_cast<Contact*>( component );
if (contact) {
AutoContact* autoContact = Session::lookup( contact );
if (autoContact)
autoContact->restoreNativeConstraintBox();
} else {
Segment* segment = dynamic_cast<Segment*>( component );
if (segment) {
AutoSegment* autoSegment = Session::lookup( segment );
if (autoSegment)
autoSegment->setRpDistance( 15 );
} else {
RoutingPad* routingPad = dynamic_cast<RoutingPad*>( component );
if (routingPad) routingPads.push_back( routingPad );
}
}
}
for ( size_t i=0 ; i<routingPads.size() ; i++ ) {
propagateConstraintFromRp( routingPads[i] );
propagateDistanceFromRp ( routingPads[i] );
}
for ( Segment* segment : net->getSegments() ) {
AutoSegment* autoSegment = Session::lookup( segment );
if (not autoSegment) continue;
if (autoSegment->isUnbreakable()) continue;
if (autoSegment->getRpDistance() >= 2) continue;
if (autoSegment->getRpDistance() == 1) continue;
vector<GCell*> gcells;
autoSegment->getGCells( gcells );
if (gcells.size() > 2) continue;
//if ( (gcells.size() == 2)
// and ( not autoSegment->getAutoSource()->isTerminal()
// or not autoSegment->getAutoTarget()->isTerminal()) ) continue;
autoSegment->setFlags( AutoSegment::SegUnbreakable );
}
// forEach ( Segment*, isegment, net->getSegments() ) {
// AutoSegment* autoSegment = Session::lookup( *isegment );
// if (autoSegment) autoSegment->toConstraintAxis();
// }
cdebug_tabw(146,-1);
DebugSession::close();
}
} // Anabatic namespace.

View File

@ -1,84 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./NetOptimals.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/DebugSession.h"
#include "hurricane/Net.h"
#include "hurricane/Segment.h"
#include "anabatic/Session.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using namespace std;
using Hurricane::tab;
using Hurricane::ForEachIterator;
using Hurricane::Net;
using Hurricane::Segment;
using Hurricane::DebugSession;
void AnabaticEngine::_computeNetOptimals ( Net* net )
{
DebugSession::open( net, 145, 150 );
cdebug_log(149,0) << "Anabatic::_computeNetOptimals( " << net << " )" << endl;
cdebug_tabw(145,1);
vector<AutoSegment*> segments;
for ( Segment* segment : net->getSegments() ) {
AutoSegment* autoSegment = Session::lookup( segment );
if (autoSegment) segments.push_back( autoSegment );
}
sort( segments.begin(), segments.end(), AutoSegment::CompareId() );
set<AutoSegment*> processeds;
for ( AutoSegment* segment : segments ) {
if (processeds.find(segment) != processeds.end()) continue;
segment->computeOptimal( processeds );
}
cdebug_tabw(145,-1);
DebugSession::close();
}
void AnabaticEngine::toOptimals ( Net* net )
{
DebugSession::open( net, 145, 150 );
cdebug_log(149,0) << "Anabatic::_toOptimals( " << net << " )" << endl;
cdebug_tabw(145,1);
vector<AutoSegment*> segments;
forEach ( Segment*, segment, net->getSegments() ) {
AutoSegment* autoSegment = Session::lookup( *segment );
if (autoSegment) segments.push_back( autoSegment );
}
sort( segments.begin(), segments.end(), AutoSegment::CompareId() );
for ( size_t i=0 ; i<segments.size() ; i++ ) {
if (segments[i]->isCanonical()) segments[i]->toOptimalAxis();
}
cdebug_tabw(145,-1);
DebugSession::close();
}
} // Anabatic namespace.

View File

@ -1,256 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2014-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./PreRouteds.cpp" |
// +-----------------------------------------------------------------+
#include "hurricane/Warning.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/DeepNet.h"
#include "hurricane/Pin.h"
#include "hurricane/RoutingPad.h"
#include "crlcore/AllianceFramework.h"
#include "anabatic/AnabaticEngine.h"
namespace Anabatic {
using std::cerr;
using std::cout;
using std::endl;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::BasicLayer;
using Hurricane::RegularLayer;
using Hurricane::Component;
using Hurricane::Pin;
using Hurricane::Plug;
using Hurricane::DeepNet;
using Hurricane::Cell;
using Hurricane::NetRoutingExtension;
using CRL::RoutingGauge;
using CRL::RoutingLayerGauge;
using CRL::AllianceFramework;
void AnabaticEngine::setupSpecialNets ()
{
AllianceFramework* af = AllianceFramework::get();
for ( Net* net : _cell->getNets() ) {
const char* excludedType = NULL;
if (net->getType() == Net::Type::POWER ) excludedType = "POWER";
if (net->getType() == Net::Type::GROUND) excludedType = "GROUND";
if (excludedType) {
cparanoid << Warning( "%s is not a routable net (%s,excluded)."
, getString(net).c_str(), excludedType ) << endl;
}
if (af->isBLOCKAGE(net->getName())) excludedType = "BLOCKAGE";
if (excludedType) {
NetData* ndata = getNetData( net, Flags::Create );
NetRoutingState* state = ndata->getNetRoutingState();
state->setFlags( NetRoutingState::Fixed );
ndata->setGlobalRouted( true );
}
}
}
size_t AnabaticEngine::setupPreRouteds ()
{
cmess1 << " o Looking for fixed or manually global routed nets." << endl;
openSession();
size_t toBeRouteds = 0;
Box ab = getCell()->getAbutmentBox();
ab.inflate( -1 );
for ( Net* net : getCell()->getNets() ) {
if (net == _blockageNet) continue;
if (net->getType() == Net::Type::POWER ) continue;
if (net->getType() == Net::Type::GROUND) continue;
// Don't skip the clock.
vector<Pin*> pins;
vector<Segment*> segments;
vector<Contact*> contacts;
bool isManualGlobalRouted = false;
bool isManualDetailRouted = false;
bool isFixed = false;
size_t rpCount = 0;
for( Component* component : net->getComponents() ) {
Pin* pin = dynamic_cast<Pin *>( component );
if (pin) {
pins.push_back( pin );
continue;
}
if (dynamic_cast<Plug*>(component)) continue;
const RegularLayer* layer = dynamic_cast<const RegularLayer*>(component->getLayer());
if (layer and (layer->getBasicLayer()->getMaterial() == BasicLayer::Material::blockage))
continue;
if ( not Session::isGaugeLayer(component->getLayer())
and not Session::isGLayer (component->getLayer())) {
const BasicLayer* basicLayer = dynamic_cast<const BasicLayer*>( component->getLayer() );
if (basicLayer and (basicLayer->getMaterial() == BasicLayer::Material::cut))
continue;
throw Error( "AnabaticEngine::setupPreRouted(): A component of \"%s\" has a routing gauge umanaged layer.\n"
" (%s)"
, getString(net->getName()).c_str()
, getString(component).c_str()
);
}
Horizontal* horizontal = dynamic_cast<Horizontal*>(component);
if (horizontal) {
if ( not ab.contains(horizontal->getSourcePosition())
and not ab.contains(horizontal->getTargetPosition()) ) continue;
segments.push_back( horizontal );
if (Session::isGLayer(component->getLayer())) {
isManualGlobalRouted = true;
} else {
isManualDetailRouted = true;
if (horizontal->getWidth() != Session::getWireWidth(horizontal->getLayer()))
isFixed = true;
}
} else {
Vertical* vertical = dynamic_cast<Vertical*>(component);
if (vertical) {
if ( not ab.contains(vertical->getSourcePosition())
and not ab.contains(vertical->getTargetPosition()) ) continue;
if (Session::isGLayer(component->getLayer())) {
isManualGlobalRouted = true;
} else {
isManualDetailRouted = true;
segments.push_back( vertical );
if (vertical->getWidth() != Session::getWireWidth(vertical->getLayer()))
isFixed = true;
}
} else {
Pin* pin = dynamic_cast<Pin*>(component);
if (pin) {
//cerr << "| " << pin << endl;
if (not ab.intersect(pin->getBoundingBox())) continue;
pins.push_back( pin );
} else {
Contact* contact = dynamic_cast<Contact*>(component);
if (contact) {
if (not ab.contains(contact->getCenter())) continue;
if (Session::isGLayer(component->getLayer())) {
isManualGlobalRouted = true;
} else {
isManualGlobalRouted = true;
contacts.push_back( contact );
if ( (contact->getWidth () != Session::getViaWidth(contact->getLayer()))
or (contact->getHeight() != Session::getViaWidth(contact->getLayer()))
or (contact->getLayer () == Session::getContactLayer(0)) )
isFixed = true;
}
} else {
RoutingPad* rp = dynamic_cast<RoutingPad*>(component);
if (rp) {
++rpCount;
} else {
// Plug* plug = dynamic_cast<Plug*>(component);
// if (plug) {
// cerr << "buildPreRouteds(): " << plug << endl;
// ++rpCount;
// }
}
}
}
}
}
}
// cerr << net << " deepNet:" << net->isDeepNet()
// << " pins:" << pins.size()
// << " segments:" << segments.size() << endl;
if (not net->isDeepNet() and (pins.size() >= 1) and (segments.size() < 2)) {
++toBeRouteds;
continue;
}
if ( (not isFixed)
and (not isManualGlobalRouted)
and (not isManualDetailRouted)
and net->isDeepNet()) {
Net* rootNet = dynamic_cast<Net*>(
dynamic_cast<DeepNet*>(net)->getRootNetOccurrence().getEntity() );
for( Component* component : rootNet->getComponents() ) {
if (dynamic_cast<Horizontal*>(component)) { isFixed = true; break; }
if (dynamic_cast<Vertical*> (component)) { isFixed = true; break; }
if (dynamic_cast<Contact*> (component)) { isFixed = true; break; }
}
}
if (isFixed or isManualDetailRouted or isManualGlobalRouted or (rpCount < 2)) {
NetData* ndata = getNetData( net, Flags::Create );
NetRoutingState* state = ndata->getNetRoutingState();
state->unsetFlags( NetRoutingState::AutomaticGlobalRoute );
if (isManualGlobalRouted) {
state->setFlags( NetRoutingState::ManualGlobalRoute );
ndata->setGlobalFixed( true );
}
if (isManualDetailRouted)
state->setFlags( NetRoutingState::ManualDetailRoute );
ndata->setGlobalRouted( true );
if (rpCount < 2)
state->setFlags( NetRoutingState::Unconnected );
if (isFixed) {
if (rpCount > 1)
cmess2 << " - <" << net->getName() << "> is fixed." << endl;
state->unsetFlags( NetRoutingState::ManualGlobalRoute|NetRoutingState::ManualDetailRoute );
state->setFlags ( NetRoutingState::Fixed );
} else if (isManualGlobalRouted) {
cmess2 << " - <" << net->getName() << "> is manually global routed." << endl;
} else if (isManualDetailRouted) {
if (rpCount > 1) {
++toBeRouteds;
cmess2 << " - <" << net->getName() << "> is manually detail routed." << endl;
for ( auto contact : contacts ) {
AutoContact::createFrom( contact );
}
for ( auto segment : segments ) {
AutoContact* source = Session::lookup( dynamic_cast<Contact*>( segment->getSource() ));
AutoContact* target = Session::lookup( dynamic_cast<Contact*>( segment->getTarget() ));
if (not source or not target) {
cerr << Error( "Unable to protect %s", getString(segment).c_str() ) << endl;
continue;
}
AutoSegment* autoSegment = AutoSegment::create( source, target, segment );
autoSegment->setFlags( AutoSegment::SegUserDefined|AutoSegment::SegAxisSet );
}
}
}
} else {
++toBeRouteds;
}
}
Session::close();
return toBeRouteds;
}
} // Anabatic namespace.

View File

@ -1,114 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./PyAnabatic.cpp" |
// +-----------------------------------------------------------------+
#include "hurricane/isobar/PyHurricane.h"
#include "hurricane/isobar/PyCell.h"
#include "anabatic/PyStyleFlags.h"
namespace Anabatic {
using std::cerr;
using std::endl;
using Hurricane::tab;
using Isobar::__cs;
#if !defined(__PYTHON_MODULE__)
// +=================================================================+
// | "PyAnabatic" Shared Library Code Part |
// +=================================================================+
# else // End of PyHurricane Shared Library Code Part.
// +=================================================================+
// | "PyAnabatic" Python Module Code Part |
// +=================================================================+
extern "C" {
// +-------------------------------------------------------------+
// | "PyAnabatic" Module Methods |
// +-------------------------------------------------------------+
static PyMethodDef PyAnabatic_Methods[] =
{ {NULL, NULL, 0, NULL} /* sentinel */
};
static PyModuleDef PyAnabatic_ModuleDef =
{ PyModuleDef_HEAD_INIT
, "Anabatic" /* m_name */
, "Low level database for global & detailed routing."
/* m_doc */
, -1 /* m_size */
, PyAnabatic_Methods /* m_methods */
, NULL /* m_reload */
, NULL /* m_traverse */
, NULL /* m_clear */
, NULL /* m_free */
};
// ---------------------------------------------------------------
// Module Initialization : "initAnabatic ()"
PyMODINIT_FUNC PyInit_Anabatic ( void )
{
cdebug_log(32,0) << "PyInit_Anabatic()" << endl;
PyStyleFlags_LinkPyType();
PYTYPE_READY( StyleFlags );
PyObject* module = PyModule_Create( &PyAnabatic_ModuleDef );
if (module == NULL) {
cerr << "[ERROR]\n"
<< " Failed to initialize Anabatic module." << endl;
return NULL;
}
Py_INCREF( &PyTypeStyleFlags );
PyModule_AddObject( module, "StyleFlags", (PyObject*)&PyTypeStyleFlags );
PyObject* dictionnary = PyModule_GetDict(module);
PyObject* constant;
LoadObjectConstant( dictionnary,EngineLoadGrByNet ,"EngineLoadGrByNet" );
LoadObjectConstant( dictionnary,EngineLoadGrByGCell ,"EngineLoadGrByGCell" );
LoadObjectConstant( dictionnary,EngineLayerAssignByLength ,"EngineLayerAssignByLength" );
LoadObjectConstant( dictionnary,EngineLayerAssignByTrunk ,"EngineLayerAssignByTrunk" );
LoadObjectConstant( dictionnary,EngineLayerAssignNoGlobalM2V,"EngineLayerAssignNoGlobalM2V" );
LoadObjectConstant( dictionnary,EngineNoNetLayerAssign ,"EngineNoNetLayerAssign" );
PyStyleFlags_postModuleInit();
return module;
}
} // End of extern "C".
#endif // End of Python Module Code Part.
} // End of Anabatic namespace.

View File

@ -1,123 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./PyStyleFlags.h" |
// +-----------------------------------------------------------------+
#include "anabatic/PyStyleFlags.h"
namespace Anabatic {
using std::cerr;
using std::endl;
using std::hex;
using std::ostringstream;
using Hurricane::tab;
using Hurricane::Error;
using Hurricane::Warning;
using Isobar::ProxyProperty;
using Isobar::ProxyError;
using Isobar::ConstructorError;
using Isobar::HurricaneError;
using Isobar::HurricaneWarning;
using Isobar::ParseOneArg;
using Isobar::ParseTwoArg;
using Isobar::getPyHash;
extern "C" {
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(StyleFlags,status,function)
// +=================================================================+
// | "PyStyleFlags" Python Module Code Part |
// +=================================================================+
#if defined(__PYTHON_MODULE__)
PyMethodDef PyStyleFlags_Methods[] =
{ {NULL, NULL, 0, NULL} /* sentinel */
};
PythonOnlyDeleteMethod(StyleFlags)
DirectReprMethod (PyStyleFlags_Repr, PyStyleFlags, StyleFlags)
DirectStrMethod (PyStyleFlags_Str, PyStyleFlags, StyleFlags)
DirectCmpByValueMethod(PyStyleFlags_Cmp, IsPyStyleFlags, PyStyleFlags)
DirectHashMethod (PyStyleFlags_Hash, StyleFlags)
extern void PyStyleFlags_LinkPyType() {
cdebug_log(20,0) << "PyStyleFlags_LinkType()" << endl;
PyTypeStyleFlags.tp_dealloc = (destructor) PyStyleFlags_DeAlloc;
PyTypeStyleFlags.tp_richcompare = (richcmpfunc)PyStyleFlags_Cmp;
PyTypeStyleFlags.tp_repr = (reprfunc) PyStyleFlags_Repr;
PyTypeStyleFlags.tp_str = (reprfunc) PyStyleFlags_Str;
PyTypeStyleFlags.tp_hash = (hashfunc) PyStyleFlags_Hash;
PyTypeStyleFlags.tp_methods = PyStyleFlags_Methods;
}
#else // End of Python Module Code Part.
// +=================================================================+
// | "PyStyleFlags" Shared Library Code Part |
// +=================================================================+
// Link/Creation Method.
PyTypeObjectDefinitions(StyleFlags)
extern void PyStyleFlags_postModuleInit ()
{
PyObject* constant = NULL;
LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::NoStyle, "NoStyle" );
LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::HV , "HV" );
LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::VH , "VH" );
LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::OTH , "OTH" );
LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::Channel, "Channel" );
LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::Hybrid , "Hybrid" );
}
#endif // Shared Library Code Part.
} // extern "C".
#if !defined(__PYTHON_MODULE__)
extern StyleFlags PyInt_AsStyleFlags ( PyObject* object )
{
uint64_t value = (uint64_t)Isobar::PyAny_AsLong( object );
if ( (value == (uint64_t)StyleFlags::NoStyle)
or (value == (uint64_t)StyleFlags::HV)
or (value == (uint64_t)StyleFlags::VH)
or (value == (uint64_t)StyleFlags::OTH)
or (value == (uint64_t)StyleFlags::Channel)
or (value == (uint64_t)StyleFlags::Hybrid))
return value;
return StyleFlags::NoStyle;
}
#endif
} // Isobar namespace.

View File

@ -1,492 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "Session.cpp<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Session.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/Cell.h"
#include "hurricane/UpdateSession.h"
#include "crlcore/RoutingGauge.h"
#include "crlcore/RoutingLayerGauge.h"
#include "anabatic/Configuration.h"
#include "anabatic/Session.h"
#include "anabatic/AutoContact.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/AnabaticEngine.h"
namespace {
const char* reopenSession = "Anabatic::Session::_open(): Session already open for %s (internal error).";
const char* openSessionError = "%s: Session has not been opened (internal error).";
} // End of local namespace.
namespace Anabatic {
using namespace std;
using Hurricane::tab;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::ForEachIterator;
using Hurricane::UpdateSession;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::Cell;
using CRL::RoutingLayerGauge;
// -------------------------------------------------------------------
// Class : "Anabatic::Session".
Session* Session::_session = NULL;
Session* Session::get ( const char* message )
{
if (not _session and message)
throw Error( openSessionError, message );
return _session;
}
Session::Session ( AnabaticEngine* anbt )
: _anabatic (anbt)
, _technology (anbt->getConfiguration()->getRoutingGauge()->getTechnology())
, _cellGauge (anbt->getConfiguration()->getCellGauge())
, _routingGauge (anbt->getConfiguration()->getRoutingGauge())
, _autoContacts ()
, _doglegs ()
, _segmentInvalidateds()
, _segmentRevalidateds()
, _netInvalidateds ()
, _netRevalidateds ()
{
_autoContacts .reserve( 1024 );
_doglegs .reserve( 1024 );
_segmentInvalidateds.reserve( 1024 );
_segmentRevalidateds.reserve( 1024 );
}
void Session::_postCreate ()
{
UpdateSession::open();
_session = this;
}
Session::~Session ()
{ }
void Session::_preDestroy ()
{
if (_anabatic->getState() <= EngineActive) {
_revalidate ();
_anabatic->updateDensity();
}
UpdateSession::close();
}
bool Session::_doDestroyBaseContact () { return _anabatic->doDestroyBaseContact(); }
bool Session::_doDestroyBaseSegment () { return _anabatic->doDestroyBaseSegment(); }
bool Session::_doDestroyTool () { return _anabatic->doDestroyTool(); }
Configuration* Session::_getConfiguration () { return _anabatic->getConfiguration(); }
void Session::_invalidate ( Net* net )
{
cdebug_log(149,0) << "Session::invalidate(Net*) - " << net << endl;
_netInvalidateds.insert(net);
}
void Session::_canonize ()
{
cdebug_log(145,1) << "Anabatic::Session::_canonize()" << endl;
if (_segmentInvalidateds.empty()) {
cdebug_log(145,0) << "Invalidated AutoSegment collection <_segmentInvalidateds> is empty." << endl;
cdebug_tabw(145,-1);
return;
}
set<Segment*> exploredSegments;
vector<AutoSegment*> aligneds;
// Should no longer be necessary to ensure determinism.
//sort( _segmentInvalidateds.begin(), _segmentInvalidateds.end(), AutoSegment::CompareId() );
for ( size_t i=0 ; i<_segmentInvalidateds.size() ; i++ ) {
AutoSegment* seedSegment = _segmentInvalidateds[i];
AutoSegment* canonical = seedSegment;
if (exploredSegments.find(seedSegment->base()) == exploredSegments.end()) {
cdebug_log(145,0) << "New chunk from: " << seedSegment << endl;
aligneds.push_back( seedSegment );
bool isWeakGlobal = seedSegment->isGlobal();
if (not seedSegment->isNotAligned()) {
forEach ( AutoSegment*, aligned, seedSegment->getAligneds() ) {
cdebug_log(145,0) << "Aligned: " << *aligned << endl;
aligneds.push_back ( *aligned );
exploredSegments.insert ( aligned->base() );
isWeakGlobal = isWeakGlobal or aligned->isGlobal();
if (AutoSegment::CompareId()( *aligned, canonical ))
canonical = *aligned;
}
}
cdebug_tabw(145,1);
canonical->setFlags( AutoSegment::SegCanonical );
cdebug_log(145,0) << "Canonical: " << canonical << endl;
Interval userConstraints = canonical->getUserConstraints();
for ( size_t j=0 ; j<aligneds.size() ; j++ ) {
if (isWeakGlobal and not aligneds[j]->isGlobal()) aligneds[j]->setFlags ( AutoSegment::SegWeakGlobal );
else aligneds[j]->unsetFlags( AutoSegment::SegWeakGlobal );
if (aligneds[j] == canonical) continue;
if (aligneds[j]->isCanonical()) {
cerr << Error("Session::_canonize(): On %s\n"
" Segment is no longer the canonical one, this must not happens."
,getString(aligneds[j]).c_str()) << endl;
}
aligneds[j]->unsetFlags( AutoSegment::SegCanonical );
cdebug_log(145,0) << "Secondary: " << aligneds[j] << endl;
userConstraints.intersection( aligneds[j]->getUserConstraints() );
}
if (aligneds.empty()) canonical->setFlags( AutoSegment::SegNotAligned );
if (not getRoutingGauge()->isSymbolic()
and (userConstraints.getSize() < Session::getPitch(1)*2) ) {
cerr << Warning( "Session::_canonize(): On %s\n"
" Combined user constraints are too tight [%s : %s]."
, getString(canonical).c_str()
, DbU::getValueString(userConstraints.getVMin()).c_str()
, DbU::getValueString(userConstraints.getVMax()).c_str()
) << endl;
}
cdebug_log(149,0) << "Align on canonical:" << canonical << endl;
cdebug_log(145,0) << "Combined user constraints: " << userConstraints << endl;
//canonical->setAxis( canonical->getAxis(), Flags::Realignate );
if (canonical->isUnsetAxis() and not canonical->isFixed())
canonical->toOptimalAxis( Flags::Realignate|Flags::Propagate );
else
canonical->setAxis( canonical->getAxis(), Flags::Realignate|Flags::Propagate );
aligneds.clear();
cdebug_tabw(145,-1);
}
}
cdebug_tabw(145,-1);
}
void Session::_revalidateTopology ()
{
cdebug_log(145,1) << "Anabatic::Session::_revalidateTopology()" << endl;
_anabatic->disableCanonize();
for ( Net* net : _netInvalidateds ) {
cdebug_log(145,0) << "Anabatic::Session::_revalidateTopology(Net*)" << net << endl;
_anabatic->updateNetTopology ( net );
_anabatic->computeNetConstraints( net );
_anabatic->_computeNetOptimals ( net );
//_anabatic->_computeNetTerminals ( net );
}
_anabatic->enableCanonize();
_canonize ();
AutoSegment* segment = NULL;
for ( size_t i=0 ; i<_segmentInvalidateds.size() ; ++i ) {
segment = _segmentInvalidateds[i];
if (segment->isCanonical()) {
if (segment->isUnsetAxis()) segment->toOptimalAxis();
else segment->toConstraintAxis();
}
}
_netRevalidateds.clear();
_netRevalidateds.swap( _netInvalidateds );
cdebug_tabw(145,-1);
}
size_t Session::_revalidate ()
{
cdebug_log(145,1) << "Anabatic::Session::revalidate()" << endl;
cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl;
cdebug_log(145,0) << "_autoContacts.size(): " << _autoContacts.size() << endl;
size_t count = 0;
if (not _netInvalidateds.empty()) _revalidateTopology();
cdebug_log(145,0) << "AutoContacts Revalidate (after _revalidateTopology())." << endl;
for ( size_t i=0 ; i < _autoContacts.size() ; i++, count++ )
_autoContacts[i]->updateGeometry();
_autoContacts.clear();
cdebug_log(145,0) << "AutoSegments Revalidate (after AutoContact::updateGeometry())." << endl;
cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl;
_segmentRevalidateds.clear();
std::sort( _segmentInvalidateds.begin(), _segmentInvalidateds.end()
, AutoSegment::CompareByRevalidate() );
for ( size_t i=0 ; i < _segmentInvalidateds.size() ; ++i, ++count ) {
_segmentInvalidateds[i]->revalidate();
if ( not _destroyedSegments.empty()
and (_destroyedSegments.find(_segmentInvalidateds[i]) != _destroyedSegments.end()) )
continue;
_segmentRevalidateds.push_back( _segmentInvalidateds[i] );
}
_segmentInvalidateds.clear();
cdebug_log(145,0) << "AutoSegments/AutoContacts queued deletion." << endl;
Flags flags = _anabatic->flags() & Flags::DestroyMask;
_anabatic->flags() = Flags::DestroyMask;
set<AutoSegment*>::iterator isegment = _destroyedSegments.begin();
for ( ; isegment != _destroyedSegments.end() ; isegment++ ) {
AutoContact* source = (*isegment)->getAutoSource();
AutoContact* target = (*isegment)->getAutoTarget();
(*isegment)->destroy();
if (source and source->canDestroy(true)) source->destroy();
if (target and target->canDestroy(true)) target->destroy();
}
_anabatic->flags() = flags;
set<AutoSegment*>().swap( _destroyedSegments );
cdebug_tabw(145,-1);
return count;
}
Session* Session::_open ( AnabaticEngine* anbt )
{
cdebug_log(145,0) << "Anabatic::Session::_open()" << endl;
if (_session) {
if (_session->_anabatic != anbt)
throw Error( reopenSession, getString(_session->getAnabatic()).c_str() );
return _session;
}
Session* session = new Session ( anbt );
session->_postCreate();
return session;
}
void Session::close ()
{
cdebug_log(145,1) << "Session::close()" << endl;
if (not _session) throw Error( openSessionError, "Session::Close()" );
_session->_preDestroy();
delete _session;
_session = NULL;
cdebug_tabw(145,-1);
}
Flags Session::getDirection ( size_t depth )
{
RoutingGauge* rg = get("getDirection()")->_routingGauge;
switch ( rg->getLayerDirection(depth) ) {
case Constant::Horizontal: return Flags::Horizontal;
case Constant::Vertical: return Flags::Vertical;
}
return Flags::NoFlags;
}
DbU::Unit Session::_getPitch ( size_t depth, Flags flags ) const
{
if (flags == Flags::NoFlags) return _routingGauge->getLayerPitch(depth);
if (flags & Flags::AboveLayer) {
if (depth < getAllowedDepth())
return _routingGauge->getLayerPitch( depth + 1 );
else {
if ( (depth > 0) and (_routingGauge->getLayerType(depth-1) != Constant::PinOnly) )
return _routingGauge->getLayerPitch( depth - 1 );
}
}
if (flags & Flags::BelowLayer) {
if ( (depth > 0) and (_routingGauge->getLayerType(depth-1) != Constant::PinOnly) )
return _routingGauge->getLayerPitch( depth - 1 );
else {
if (depth < getAllowedDepth())
return _routingGauge->getLayerPitch( depth + 1 );
}
}
// Should issue at least a warning here.
return _routingGauge->getLayerPitch(depth);
}
DbU::Unit Session::_getNearestTrackAxis ( const Layer* layer, DbU::Unit axis, uint32_t mode )
{
Box ab = _anabatic->getCell()->getAbutmentBox();
RoutingLayerGauge* lg = _routingGauge->getLayerGauge( layer );
if (not lg) return axis;
DbU::Unit minAxis = 0;
DbU::Unit maxAxis = 0;
if (lg->getDirection() == Constant::Horizontal) {
minAxis = ab.getYMin();
maxAxis = ab.getYMax();
} else {
minAxis = ab.getXMin();
maxAxis = ab.getXMax();
}
DbU::Unit trackAxis = lg->getTrackPosition( minAxis
, lg->getTrackIndex( minAxis
, maxAxis
, axis
, mode ) );
return trackAxis;
}
Point Session::_getNearestGridPoint ( Point p, Box constraint )
{
Box ab = _anabatic->getCell()->getAbutmentBox();
RoutingLayerGauge* lg = _routingGauge->getVerticalGauge();
DbU::Unit x = lg->getTrackPosition( ab.getXMin()
, lg->getTrackIndex( ab.getXMin()
, ab.getXMax()
, p.getX()
, Constant::Nearest ) );
if (x < constraint.getXMin()) x += lg->getPitch();
if (x > constraint.getXMax()) x -= lg->getPitch();
lg = _routingGauge->getHorizontalGauge();
DbU::Unit y = lg->getTrackPosition( ab.getYMin()
, lg->getTrackIndex( ab.getYMin()
, ab.getYMax()
, p.getY()
, Constant::Nearest ) );
if (y < constraint.getYMin()) y += lg->getPitch();
if (y > constraint.getYMax()) y -= lg->getPitch();
y = std::max( y, constraint.getYMin() );
y = std::min( y, constraint.getYMax() );
return Point(x,y);
}
StyleFlags Session::getRoutingStyle ()
{ return get("getRoutingStyle()")->_anabatic->getRoutingStyle(); }
bool Session::isInDemoMode ()
{ return get("isInDemoMode()")->_anabatic->isInDemoMode(); }
bool Session::isChannelStyle ()
{ return get("isChannelStyle()")->_anabatic->isChannelStyle(); }
float Session::getSaturateRatio ()
{ return get("getSaturateRatio()")->_anabatic->getSaturateRatio(); }
size_t Session::getSaturateRp ()
{ return get("getSaturateRp()")->_anabatic->getSaturateRp(); }
bool Session::doWarnGCellOverload ()
{ return get("doWarnGCellOverload()")->_anabatic->doWarnOnGCellOverload(); }
void Session::setAnabaticFlags ( Flags flags )
{ get("setKabaticFlags()")->_anabatic->flags() = flags; }
void Session::link ( AutoContact* autoContact )
{ return get("link(AutoContact*)")->_anabatic->_link( autoContact ); }
void Session::link ( AutoSegment* autoSegment )
{ return get("link(AutoSegment*)")->_anabatic->_link( autoSegment ); }
void Session::unlink ( AutoContact* autoContact )
{ return get("unlink(AutoContact*)")->_anabatic->_unlink( autoContact ); }
void Session::unlink ( AutoSegment* autoSegment )
{ return get("unlink(AutoSegment*)")->_anabatic->_unlink( autoSegment ); }
AutoContact* Session::lookup ( Contact* contact )
{ return get("lookup(Contact*)")->_anabatic->_lookup( contact ); }
AutoSegment* Session::lookup ( Segment* segment )
{ return get("lookup(Segment*)")->_anabatic->_lookup( segment ); }
string Session::_getString () const
{
return "<" + _getTypeName() + " "
+ getString(_anabatic->getCell()->getName())
+ ">";
}
Record* Session::_getRecord () const
{
Record* record = new Record ( _getString() );
record->add ( getSlot ( "_anabatic" , _anabatic ) );
record->add ( getSlot ( "_autoContacts", &_autoContacts ) );
//record->add ( getSlot ( "_autoSegments", &_autoSegments ) );
return record;
}
} // End of Anabatic namespace.

View File

@ -1,471 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AnabaticEngine.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <memory>
#include <string>
#include <vector>
#include <set>
#include "hurricane/NetRoutingProperty.h"
namespace Hurricane {
class Instance;
class CellViewer;
}
#include "crlcore/ToolEngine.h"
#include "anabatic/Configuration.h"
#include "anabatic/Matrix.h"
#include "anabatic/GCell.h"
#include "anabatic/AutoContact.h"
#include "anabatic/AutoSegments.h"
#include "anabatic/ChipTools.h"
namespace Anabatic {
using std::string;
using std::vector;
using Hurricane::Name;
using Hurricane::Record;
using Hurricane::Interval;
using Hurricane::Cell;
using Hurricane::CellViewer;
using Hurricane::NetRoutingState;
using CRL::ToolEngine;
class NetBuilder;
class AnabaticEngine;
// -------------------------------------------------------------------
// Class : "Anabatic::RawGCellsUnder".
class RawGCellsUnder {
public:
class Element {
public:
inline Element ( GCell*, Edge* );
inline GCell* gcell () const;
inline Edge* edge () const;
private:
GCell* _gcell;
Edge* _edge;
};
public:
RawGCellsUnder ( const AnabaticEngine*, Segment* );
RawGCellsUnder ( const AnabaticEngine*, Point source, Point target );
void commonCtor ( const AnabaticEngine*, Point source, Point target );
inline bool empty () const;
inline size_t size () const;
inline GCell* gcellAt ( size_t ) const;
inline GCell* gcellRAt ( size_t ) const;
inline Edge* edgeAt ( size_t ) const;
inline const vector<Element>& getElements () const;
private:
RawGCellsUnder ( const RawGCellsUnder& );
RawGCellsUnder& operator= ( const RawGCellsUnder& );
private:
vector<Element> _elements;
};
inline RawGCellsUnder::Element::Element ( GCell* gcell, Edge* edge ) : _gcell(gcell), _edge(edge) { }
inline GCell* RawGCellsUnder::Element::gcell () const { return _gcell; }
inline Edge* RawGCellsUnder::Element::edge () const { return _edge; }
inline bool RawGCellsUnder::empty () const { return _elements.empty(); }
inline size_t RawGCellsUnder::size () const { return _elements.size(); }
inline const vector<RawGCellsUnder::Element>&
RawGCellsUnder::getElements () const { return _elements; }
inline Edge* RawGCellsUnder::edgeAt ( size_t i ) const { return (i<size()) ? _elements[i].edge () : NULL; }
inline GCell* RawGCellsUnder::gcellAt ( size_t i ) const { return (i<size()) ? _elements[i].gcell() : NULL; }
inline GCell* RawGCellsUnder::gcellRAt ( size_t i ) const { return (i<size()) ? _elements[size()-1-i].gcell() : NULL; }
typedef std::shared_ptr<RawGCellsUnder> GCellsUnder;
// -------------------------------------------------------------------
// Class : "Anabatic::NetData".
class NetData {
public:
NetData ( Net*, AnabaticEngine* );
inline bool isGlobalEstimated () const;
inline bool isGlobalRouted () const;
inline bool isGlobalFixed () const;
inline bool isMixedPreRoute () const;
inline bool isFixed () const;
inline bool isExcluded () const;
inline bool isNoMoveUp ( Segment* ) const;
inline Net* getNet () const;
inline NetRoutingState* getNetRoutingState () const;
inline const Box& getSearchArea () const;
inline DbU::Unit getHalfPerimeter () const;
inline size_t getRpCount () const;
inline size_t getDiodeRpCount () const;
inline DbU::Unit getSparsity () const;
inline void setNetRoutingState ( NetRoutingState* );
inline void setSearchArea ( Box );
inline void setGlobalEstimated ( bool );
inline void setGlobalRouted ( bool );
inline void setGlobalFixed ( bool );
inline void setExcluded ( bool );
inline void setRpCount ( size_t );
inline void setNoMoveUp ( Segment* );
private:
NetData ( const NetData& );
NetData& operator= ( const NetData& );
inline void _update ();
private:
Net* _net;
NetRoutingState* _state;
Box _searchArea;
size_t _rpCount;
size_t _diodeCount;
DbU::Unit _sparsity;
Flags _flags;
std::set<Segment*,DBo::CompareById> _noMoveUp;
};
inline bool NetData::isGlobalEstimated () const { return _flags & Flags::GlobalEstimated; }
inline bool NetData::isGlobalRouted () const { return _flags & Flags::GlobalRouted; }
inline bool NetData::isGlobalFixed () const { return _flags & Flags::GlobalFixed; }
inline bool NetData::isMixedPreRoute () const { return (_state) ? _state->isMixedPreRoute() : false; }
inline bool NetData::isFixed () const { return (_state) ? _state->isFixed () : false; }
inline bool NetData::isExcluded () const { return _flags & Flags::ExcludeRoute; }
inline bool NetData::isNoMoveUp ( Segment* segment ) const { return (_noMoveUp.find(segment) != _noMoveUp.end()); }
inline Net* NetData::getNet () const { return _net; }
inline NetRoutingState* NetData::getNetRoutingState () const { return _state; }
inline const Box& NetData::getSearchArea () const { return _searchArea; }
inline DbU::Unit NetData::getHalfPerimeter () const { return (_searchArea.isEmpty()) ? 0.0 : (_searchArea.getWidth()+_searchArea.getHeight()); }
inline size_t NetData::getRpCount () const { return _rpCount; }
inline size_t NetData::getDiodeRpCount () const { return _diodeCount; }
inline void NetData::setNetRoutingState ( NetRoutingState* state ) { _state=state; }
inline DbU::Unit NetData::getSparsity () const { return _sparsity; }
inline void NetData::setGlobalEstimated ( bool state ) { _flags.set(Flags::GlobalEstimated,state); }
inline void NetData::setGlobalRouted ( bool state ) { _flags.set(Flags::GlobalRouted ,state); }
inline void NetData::setGlobalFixed ( bool state ) { _flags.set(Flags::GlobalFixed ,state); }
inline void NetData::setExcluded ( bool state ) { _flags.set(Flags::ExcludeRoute ,state); }
inline void NetData::setRpCount ( size_t count ) { _rpCount=count; _update(); }
inline void NetData::setNoMoveUp ( Segment* segment ) { _noMoveUp.insert(segment); }
inline void NetData::_update ()
{ if (_rpCount) _sparsity=getHalfPerimeter()/_rpCount; else _sparsity=0; }
class SparsityOrder {
public:
inline bool operator() ( const NetData* lhs, const NetData* rhs ) const
{
if (lhs->isMixedPreRoute() != rhs->isMixedPreRoute()) return lhs->isMixedPreRoute();
if ((lhs->getRpCount() > 10) or (rhs->getRpCount() > 10)) {
if (lhs->getRpCount() != rhs->getRpCount())
return lhs->getRpCount() > rhs->getRpCount();
}
if (lhs->getSparsity() != rhs->getSparsity()) return lhs->getSparsity() < rhs->getSparsity();
return lhs->getNet()->getId() < rhs->getNet()->getId();
}
};
// -------------------------------------------------------------------
// Class : "Anabatic::AnabaticEngine".
typedef std::set<Net*,Entity::CompareById> NetSet;
typedef std::map<uint64_t,NetData*> NetDatas;
class AnabaticEngine : public ToolEngine {
public:
static const uint32_t DigitalMode = (1 << 0);
static const uint32_t AnalogMode = (1 << 1);
static const uint32_t MixedMode = (1 << 2);
static const uint32_t AverageHVDensity = 1; // Average between all densities.
static const uint32_t AverageHDensity = 2; // Average between all H densities.
static const uint32_t AverageVDensity = 3; // Average between all V densities.
static const uint32_t MaxHVDensity = 4; // Maximum between average H and average V.
static const uint32_t MaxVDensity = 5; // Maximum of V densities.
static const uint32_t MaxHDensity = 6; // Maximum of H densities.
static const uint32_t MaxDensity = 7; // Maximum of H & V densities.
public:
typedef ToolEngine Super;
public:
static AnabaticEngine* create ( Cell* );
static AnabaticEngine* get ( const Cell* );
inline bool isCanonizeDisabled () const;
inline bool isDigitalMode () const;
inline bool isAnalogMode () const;
inline bool isMixedMode () const;
inline bool isChannelStyle () const;
inline bool isHybridStyle () const;
static const Name& staticGetName ();
virtual const Name& getName () const;
virtual Configuration* getConfiguration ();
virtual const Configuration* getConfiguration () const;
inline std::string getNetBuilderStyle () const;
inline StyleFlags getRoutingStyle () const;
inline uint64_t getDensityMode () const;
inline CellViewer* getViewer () const;
inline void setViewer ( CellViewer* );
inline EngineState getState () const;
inline const Matrix* getMatrix () const;
inline const vector<GCell*>& getGCells () const;
inline const vector<Edge*>& getOvEdges () const;
inline GCell* getSouthWestGCell () const;
inline GCell* getGCellUnder ( DbU::Unit x, DbU::Unit y ) const;
inline GCell* getGCellUnder ( Point ) const;
inline GCellsUnder getGCellsUnder ( Segment* ) const;
inline GCellsUnder getGCellsUnder ( Point source, Point target ) const;
inline Edges getEdgesUnderPath ( GCell* source, GCell* target, Flags pathFlags=Flags::NorthPath ) const;
Interval getUSide ( Flags direction ) const;
int getCapacity ( Interval, Flags ) const;
size_t getNetsFromEdge ( const Edge*, NetSet& );
virtual void openSession ();
inline void setState ( EngineState state );
inline void setDensityMode ( uint64_t );
inline void disableCanonize ();
inline void enableCanonize ();
inline void addOv ( Edge* );
inline void removeOv ( Edge* );
inline const NetDatas& getNetDatas () const;
NetData* getNetData ( Net*, Flags flags=Flags::NoFlags );
void setupNetDatas ();
void exclude ( const Name& netName );
void exclude ( Net* );
void updateMatrix ();
bool checkPlacement () const;
// Dijkstra related functions.
inline int getStamp () const;
inline int incStamp ();
Contact* breakAt ( Segment*, GCell* );
void ripup ( Segment*, Flags );
bool unify ( Contact* );
// Global routing related functions.
void globalRoute ();
void cleanupGlobal ();
void relaxOverConstraineds ();
// Detailed routing related functions.
inline bool isInDemoMode () const;
inline bool isChip () const;
inline bool doWarnOnGCellOverload () const;
inline bool doDestroyBaseContact () const;
inline bool doDestroyBaseSegment () const;
inline bool doDestroyTool () const;
inline DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getAntennaDiodeMaxWL () const;
inline DbU::Unit getGlobalThreshold () const;
inline float getSaturateRatio () const;
inline size_t getSaturateRp () const;
inline DbU::Unit getExtensionCap () const;
inline Cell* getDiodeCell () const;
inline Net* getBlockageNet () const;
inline const ChipTools& getChipTools () const;
inline const vector<NetData*>& getNetOrdering () const;
void invalidateRoutingPads ();
void updateDensity ();
size_t checkGCellDensities ();
void setupNetBuilder ();
inline void setRoutingMode ( uint32_t );
inline void resetRoutingMode ( uint32_t );
inline void setGlobalThreshold ( DbU::Unit );
inline void setSaturateRatio ( float );
inline void setSaturateRp ( size_t );
inline void setBlockageNet ( Net* );
void chipPrep ();
void computeEdgeCapacities ( int maxHCap, int maxVCap, int termSatThreshold, int maxTermSat );
void antennaProtect ( Net*, uint32_t& failed, uint32_t& total );
void antennaProtect ();
void setupSpecialNets ();
size_t setupPreRouteds ();
void loadGlobalRouting ( uint32_t method );
void computeNetConstraints ( Net* );
void toOptimals ( Net* );
void updateNetTopology ( Net* );
bool moveUpNetTrunk ( AutoSegment*, set<Net*>& globalNets, GCell::Set& invalidateds );
void layerAssign ( uint32_t method );
void finalizeLayout ();
void exportExternalNets ();
inline const AutoContactLut& _getAutoContactLut () const;
inline const AutoSegmentLut& _getAutoSegmentLut () const;
void _link ( AutoContact* );
void _link ( AutoSegment* );
void _unlink ( AutoContact* );
void _unlink ( AutoSegment* );
AutoContact* _lookup ( Contact* ) const;
AutoSegment* _lookup ( Segment* ) const;
EdgeCapacity* _createCapacity ( Flags, Interval );
size_t _unrefCapacity ( EdgeCapacity* );
void _loadGrByNet ();
void _computeNetOptimals ( Net* );
void _computeNetTerminals ( Net* );
void _alignate ( Net* );
void _desaturate ( unsigned int depth, set<Net*>&, unsigned long& total, unsigned long& globals );
void _layerAssignByLength ( unsigned long& total, unsigned long& global, set<Net*>& );
void _layerAssignByLength ( Net*, unsigned long& total, unsigned long& global, set<Net*>& );
void _layerAssignByTrunk ( unsigned long& total, unsigned long& global, set<Net*>& );
void _layerAssignByTrunk ( Net*, set<Net*>&, unsigned long& total, unsigned long& global );
void _layerAssignNoGlobalM2V ( unsigned long& total, unsigned long& global, set<Net*>& );
void _layerAssignNoGlobalM2V ( Net*, set<Net*>&, unsigned long& total, unsigned long& global );
void _saveNet ( Net* );
void _destroyAutoContacts ();
void _destroyAutoSegments ();
void _check ( Net* net ) const;
bool _check ( const char* message ) const;
void printMeasures ( const string& tag ) const;
// Misc. functions.
inline const Flags& flags () const;
inline Flags& flags ();
void reset ();
inline void _add ( GCell* );
inline void _remove ( GCell* );
inline void _updateLookup ( GCell* );
inline void _updateGContacts ( Flags flags=Flags::Horizontal|Flags::Vertical );
inline void _resizeMatrix ();
inline bool _inDestroy () const;
// Inspector support.
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
protected:
AnabaticEngine ( Cell* );
virtual ~AnabaticEngine ();
virtual void _postCreate ();
virtual void _preDestroy ();
void _gutAnabatic ();
virtual Configuration* _createConfiguration ();
private:
AnabaticEngine ( const AnabaticEngine& );
AnabaticEngine& operator= ( const AnabaticEngine& );
private:
static Name _toolName;
protected:
Configuration* _configuration;
private:
ChipTools _chipTools;
EngineState _state;
Matrix _matrix;
vector<GCell*> _gcells;
vector<Edge*> _ovEdges;
vector<NetData*> _netOrdering;
NetDatas _netDatas;
CellViewer* _viewer;
Flags _flags;
int _stamp;
uint32_t _routingMode;
uint64_t _densityMode;
AutoSegmentLut _autoSegmentLut;
AutoContactLut _autoContactLut;
EdgeCapacityLut _edgeCapacitiesLut;
Net* _blockageNet;
Cell* _diodeCell;
};
inline bool AnabaticEngine::isDigitalMode () const { return (_routingMode & DigitalMode); };
inline bool AnabaticEngine::isAnalogMode () const { return (_routingMode & AnalogMode); };
inline bool AnabaticEngine::isMixedMode () const { return (_routingMode & MixedMode); };
inline bool AnabaticEngine::isChannelStyle () const { return (_configuration->getRoutingStyle() & StyleFlags::Channel); };
inline bool AnabaticEngine::isHybridStyle () const { return (_configuration->getRoutingStyle() & StyleFlags::Hybrid); };
inline void AnabaticEngine::setRoutingMode ( uint32_t mode ) { _routingMode |= mode; };
inline void AnabaticEngine::resetRoutingMode ( uint32_t mode ) { _routingMode &= ~mode; };
inline EngineState AnabaticEngine::getState () const { return _state; }
inline void AnabaticEngine::setState ( EngineState state ) { _state = state; }
inline CellViewer* AnabaticEngine::getViewer () const { return _viewer; }
inline void AnabaticEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; }
inline const Matrix* AnabaticEngine::getMatrix () const { return &_matrix; }
inline const vector<GCell*>& AnabaticEngine::getGCells () const { return _gcells; }
inline const vector<Edge*>& AnabaticEngine::getOvEdges () const { return _ovEdges; }
inline GCell* AnabaticEngine::getSouthWestGCell () const { return _gcells[0]; }
inline GCell* AnabaticEngine::getGCellUnder ( DbU::Unit x, DbU::Unit y ) const { return _matrix.getUnder(x,y); }
inline GCell* AnabaticEngine::getGCellUnder ( Point p ) const { return _matrix.getUnder(p); }
inline GCellsUnder AnabaticEngine::getGCellsUnder ( Segment* s ) const { return std::shared_ptr<RawGCellsUnder>( new RawGCellsUnder(this,s) ); }
inline GCellsUnder AnabaticEngine::getGCellsUnder ( Point source, Point target ) const { return std::shared_ptr<RawGCellsUnder>( new RawGCellsUnder(this,source,target) ); }
inline Edges AnabaticEngine::getEdgesUnderPath ( GCell* source, GCell* target, Flags pathFlags ) const { return new Path_Edges(source,target,pathFlags); }
inline uint64_t AnabaticEngine::getDensityMode () const { return _densityMode; }
inline void AnabaticEngine::setDensityMode ( uint64_t mode ) { _densityMode=mode; }
inline void AnabaticEngine::setBlockageNet ( Net* net ) { _blockageNet = net; }
inline const AutoContactLut& AnabaticEngine::_getAutoContactLut () const { return _autoContactLut; }
inline const AutoSegmentLut& AnabaticEngine::_getAutoSegmentLut () const { return _autoSegmentLut; }
inline const Flags& AnabaticEngine::flags () const { return _flags; }
inline Flags& AnabaticEngine::flags () { return _flags; }
inline bool AnabaticEngine::doDestroyBaseContact () const { return _flags & Flags::DestroyBaseContact; }
inline bool AnabaticEngine::doDestroyBaseSegment () const { return _flags & Flags::DestroyBaseSegment; }
inline bool AnabaticEngine::doDestroyTool () const { return _state >= EngineGutted; }
inline bool AnabaticEngine::doWarnOnGCellOverload () const { return _flags & Flags::WarnOnGCellOverload; }
inline bool AnabaticEngine::isCanonizeDisabled () const { return _flags & Flags::DisableCanonize; }
inline bool AnabaticEngine::isInDemoMode () const { return _flags & Flags::DemoMode; }
inline bool AnabaticEngine::isChip () const { return _chipTools.isChip(); }
inline std::string AnabaticEngine::getNetBuilderStyle () const { return _configuration->getNetBuilderStyle(); }
inline StyleFlags AnabaticEngine::getRoutingStyle () const { return _configuration->getRoutingStyle(); }
inline DbU::Unit AnabaticEngine::getAntennaGateMaxWL () const { return _configuration->getAntennaGateMaxWL(); }
inline DbU::Unit AnabaticEngine::getAntennaDiodeMaxWL () const { return _configuration->getAntennaDiodeMaxWL(); }
inline DbU::Unit AnabaticEngine::getGlobalThreshold () const { return _configuration->getGlobalThreshold(); }
inline float AnabaticEngine::getSaturateRatio () const { return _configuration->getSaturateRatio(); }
inline size_t AnabaticEngine::getSaturateRp () const { return _configuration->getSaturateRp(); }
inline void AnabaticEngine::setSaturateRatio ( float ratio ) { _configuration->setSaturateRatio(ratio); }
inline void AnabaticEngine::setSaturateRp ( size_t threshold ) { _configuration->setSaturateRp(threshold); }
inline Cell* AnabaticEngine::getDiodeCell () const { return _diodeCell; }
inline Net* AnabaticEngine::getBlockageNet () const { return _blockageNet; }
inline const ChipTools& AnabaticEngine::getChipTools () const { return _chipTools; }
inline const vector<NetData*>& AnabaticEngine::getNetOrdering () const { return _netOrdering; }
inline void AnabaticEngine::setGlobalThreshold ( DbU::Unit threshold ) { _configuration->setGlobalThreshold(threshold); }
inline const NetDatas& AnabaticEngine::getNetDatas () const { return _netDatas; }
inline void AnabaticEngine::_updateLookup ( GCell* gcell ) { _matrix.updateLookup(gcell); }
inline void AnabaticEngine::_resizeMatrix () { _matrix.resize( getCell(), getGCells() ); }
inline void AnabaticEngine::_updateGContacts ( Flags flags ) { for ( GCell* gcell : getGCells() ) gcell->updateGContacts(flags); }
inline bool AnabaticEngine::_inDestroy () const { return _flags & Flags::DestroyMask; }
inline void AnabaticEngine::disableCanonize () { _flags |= Flags::DisableCanonize; }
inline void AnabaticEngine::enableCanonize () { _flags.reset( Flags::DisableCanonize ); }
inline void AnabaticEngine::_add ( GCell* gcell )
{
_gcells.push_back( gcell );
//std::sort( _gcells.begin(), _gcells.end(), Entity::CompareById() );
}
inline void AnabaticEngine::_remove ( GCell* gcell )
{
for ( auto igcell = _gcells.begin() ; igcell != _gcells.end() ; ++igcell )
if (*igcell == gcell) {
if (_inDestroy()) (*igcell) = NULL;
else _gcells.erase(igcell);
break;
}
}
inline int AnabaticEngine::getStamp () const { return _stamp; }
inline int AnabaticEngine::incStamp () { return ++_stamp; }
inline void AnabaticEngine::addOv ( Edge* edge ) {
_ovEdges.push_back(edge);
}
inline void AnabaticEngine::removeOv ( Edge* edge )
{
for ( auto iedge = _ovEdges.begin() ; iedge != _ovEdges.end() ; ++iedge ) {
if (*iedge == edge) { _ovEdges.erase(iedge); return; }
}
}
extern const char* badMethod;
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AnabaticEngine);

View File

@ -1,373 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoContact.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOCONTACT_H
#define ANABATIC_AUTOCONTACT_H
#include <vector>
#include <map>
#include "hurricane/Contact.h"
#include "hurricane/ExtensionGo.h"
#include "anabatic/Constants.h"
#include "anabatic/AutoSegment.h"
#include "anabatic/GCell.h"
namespace Anabatic {
using std::cerr;
using std::endl;
using Hurricane::order;
using Hurricane::setInBound;
using Hurricane::tab;
using Hurricane::Name;
using Hurricane::Entity;
using Hurricane::Net;
using Hurricane::Component;
using Hurricane::Components;
using Hurricane::Layer;
using Hurricane::Contact;
using Hurricane::ExtensionGo;
class AnabaticEngine;
class AutoHorizontal;
class AutoVertical;
class AutoContact;
typedef std::map<Contact*,AutoContact*,Entity::CompareById> AutoContactLut;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContact".
enum AutoContactFlag { CntFixed = (1 << 0)
, CntTerminal = (1 << 1)
, CntTurn = (1 << 2)
, CntHTee = (1 << 3)
, CntVTee = (1 << 4)
, CntInvalidated = (1 << 6)
, CntInvalidatedCache = (1 << 7)
, CntInvalidatedWidth = (1 << 8)
, CntInCreationStage = (1 << 9)
, CntBadTopology = (1 << 10)
, CntIgnoreAnchor = (1 << 11)
, CntWeakTerminal = (1 << 12)
, CntUserNativeConstraints = (1 << 13)
, CntOnVertical = (1 << 14)
, CntOnHorizontal = (1 << 15)
, CntDrag = (1 << 16)
, CntHDogleg = (1 << 17)
, CntVDogleg = (1 << 18)
};
class AutoContact {
public:
static AutoContact* createFrom ( Contact* );
public:
// Wrapped Contact Accessors.
inline Hook* getBodyHook ();
inline Hook* getAnchorHook ();
inline Component* getAnchor () const;
inline Net* getNet () const;
inline const Layer* getLayer () const;
inline DbU::Unit getX () const;
inline DbU::Unit getY () const;
inline DbU::Unit getDx () const;
inline DbU::Unit getDy () const;
inline Point getCenter () const;
inline Point getPosition () const;
inline DbU::Unit getWidth () const;
inline DbU::Unit getHalfWidth () const;
inline DbU::Unit getHeight () const;
inline DbU::Unit getHalfHeight () const;
inline Components getSlaveComponents () const;
// Wrapped Contact Modifiers.
inline void setLayer ( const Layer* );
inline void setWidth ( DbU::Unit );
inline void setHeight ( DbU::Unit );
inline void setSizes ( DbU::Unit width, DbU::Unit height );
inline void setX ( DbU::Unit );
inline void setY ( DbU::Unit );
inline void setPosition ( DbU::Unit x, DbU::Unit y );
inline void setPosition ( const Point& );
inline void setDx ( DbU::Unit );
inline void setDy ( DbU::Unit );
inline void setOffset ( DbU::Unit dx, DbU::Unit dy );
virtual void translate ( const DbU::Unit& tx, const DbU::Unit& ty );
// Predicates.
inline bool isInCreationStage () const;
inline bool isInvalidated () const;
inline bool isInvalidatedCache () const;
inline bool isInvalidatedWidth () const;
inline bool isTerminal () const;
inline bool isTurn () const;
bool isTee ( Flags direction ) const;
inline bool isHTee () const;
inline bool isVTee () const;
inline bool isFixed () const;
inline bool isUserNativeConstraints () const;
inline bool isHDogleg () const;
inline bool isVDogleg () const;
virtual bool isOnPin () const;
inline bool hasBadTopology () const;
bool canDestroy ( Flags flags=Flags::NoFlags ) const;
bool canMoveUp ( const AutoSegment* moved ) const;
inline bool canDrag () const;
// Accessors.
inline Contact* base () const;
static size_t getAllocateds ();
static const Name& getStaticName ();
virtual const Name& getName () const;
inline size_t getId () const;
inline Flags getFlags () const;
virtual Box getBoundingBox () const;
inline GCell* getGCell () const;
virtual AutoSegment* getOpposite ( const AutoSegment* ) const = 0;
virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const = 0;
virtual AutoSegment* getSegment ( unsigned int ) const = 0;
virtual AutoHorizontal* getHorizontal1 () const;
virtual AutoHorizontal* getHorizontal2 () const;
virtual AutoVertical* getVertical1 () const;
virtual AutoVertical* getVertical2 () const;
void getDepthSpan ( size_t& minDepth, size_t& maxDepth ) const;
inline unsigned int getMinDepth () const;
inline unsigned int getMaxDepth () const;
void getLengths ( DbU::Unit* lengths, AutoSegment::DepthLengthSet& );
virtual Box getNativeConstraintBox () const;
Interval getNativeUConstraints ( Flags direction ) const;
Interval getUConstraints ( Flags direction ) const;
inline DbU::Unit getCBXMin () const;
inline DbU::Unit getCBXMax () const;
inline DbU::Unit getCBYMin () const;
inline DbU::Unit getCBYMax () const;
inline Box getConstraintBox () const;
Box& intersectConstraintBox ( Box& box ) const;
// Collections.
AutoSegments getAutoSegments ();
// Modifiers.
void invalidate ( Flags flags=Flags::NoFlags );
virtual void cacheDetach ( AutoSegment* ) = 0;
virtual void cacheAttach ( AutoSegment* ) = 0;
virtual void updateCache () = 0;
void updateLayer ();
void updateSize ();
virtual void updateGeometry () = 0;
virtual void updateTopology () = 0;
void showTopologyError ( const std::string&, Flags flags=Flags::NoFlags );
virtual void checkTopology ();
virtual void forceOnGrid ( Point );
inline void setFlags ( Flags );
inline void unsetFlags ( Flags );
void setGCell ( GCell* );
inline void setCBXMin ( DbU::Unit xMin );
inline void setCBXMax ( DbU::Unit xMax );
inline void setCBYMin ( DbU::Unit yMin );
inline void setCBYMax ( DbU::Unit yMax );
void setConstraintBox ( const Box& box );
bool restrictConstraintBox ( DbU::Unit constraintMin
, DbU::Unit constraintMax
, Flags flags=Flags::WarnOnError );
void restoreNativeConstraintBox ();
void migrateConstraintBox ( AutoContact* other );
void setLayerAndWidth ( size_t delta, size_t depth );
void destroy ();
// Inspector Management.
Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
private:
// Internal: Attributes.
static size_t _maxId;
static size_t _allocateds;
static const Name _goName;
protected:
size_t _id;
Contact* _contact;
GCell* _gcell;
Flags _flags;
DbU::Unit _xMin;
DbU::Unit _xMax;
DbU::Unit _yMin;
DbU::Unit _yMax;
protected:
// Constructors & Destructors.
AutoContact ( GCell*, Contact* );
virtual ~AutoContact ();
static void _preCreate ( GCell*, Net*, const Layer* );
virtual void _postCreate ();
virtual void _preDestroy ();
private:
AutoContact ( const AutoContact& );
AutoContact& operator= ( const AutoContact& );
protected:
inline int _boundX ( DbU::Unit x ) const;
inline int _boundY ( DbU::Unit x ) const;
static void _getTopology ( Contact*, Component*& anchor, Horizontal**&, Vertical**&, size_t );
virtual void _invalidate ( Flags flags ) = 0;
};
// Wrapped Contact Inline Functions.
inline Hook* AutoContact::getBodyHook () { return _contact->getBodyHook(); }
inline Hook* AutoContact::getAnchorHook () { return _contact->getAnchorHook(); }
inline Component* AutoContact::getAnchor () const { return _contact->getAnchor(); }
inline Net* AutoContact::getNet () const { return _contact->getNet(); }
inline const Layer* AutoContact::getLayer () const { return _contact->getLayer(); }
inline DbU::Unit AutoContact::getX () const { return _contact->getX(); }
inline DbU::Unit AutoContact::getY () const { return _contact->getY(); }
inline DbU::Unit AutoContact::getDx () const { return _contact->getDx(); }
inline DbU::Unit AutoContact::getDy () const { return _contact->getDy(); }
inline Point AutoContact::getCenter () const { return _contact->getCenter(); }
inline Point AutoContact::getPosition () const { return _contact->getPosition(); }
inline DbU::Unit AutoContact::getWidth () const { return _contact->getWidth(); }
inline DbU::Unit AutoContact::getHalfWidth () const { return _contact->getHalfWidth(); }
inline DbU::Unit AutoContact::getHeight () const { return _contact->getHeight(); }
inline DbU::Unit AutoContact::getHalfHeight () const { return _contact->getHalfHeight(); }
inline Components AutoContact::getSlaveComponents () const { return _contact->getSlaveComponents(); }
inline void AutoContact::setLayer ( const Layer* layer ) { _contact->setLayer(layer); }
inline void AutoContact::setWidth ( DbU::Unit w ) { _contact->setWidth(w); }
inline void AutoContact::setHeight ( DbU::Unit h ) { _contact->setHeight(h); }
inline void AutoContact::setSizes ( DbU::Unit w, DbU::Unit h ) { _contact->setSizes(w,h); }
inline void AutoContact::setX ( DbU::Unit x ) { _contact->setX(x); }
inline void AutoContact::setY ( DbU::Unit y ) { _contact->setY(y); }
inline void AutoContact::setPosition ( DbU::Unit x, DbU::Unit y ) { _contact->setPosition(x,y); }
inline void AutoContact::setPosition ( const Point& p ) { _contact->setPosition(p); }
inline void AutoContact::setDx ( DbU::Unit dx ) { _contact->setDx(dx); }
inline void AutoContact::setDy ( DbU::Unit dy ) { _contact->setDy(dy); }
inline void AutoContact::setOffset ( DbU::Unit dx, DbU::Unit dy ) { _contact->setOffset(dx,dy); }
// AutoContact Inline Functions.
inline bool AutoContact::isInCreationStage () const { return _flags&CntInCreationStage; }
inline bool AutoContact::isInvalidated () const { return _flags&CntInvalidated; }
inline bool AutoContact::isInvalidatedCache () const { return _flags&CntInvalidatedCache; }
inline bool AutoContact::isInvalidatedWidth () const { return _flags&CntInvalidatedWidth; }
inline bool AutoContact::isTurn () const { return _flags&CntTurn; }
inline bool AutoContact::isFixed () const { return _flags&CntFixed; }
inline bool AutoContact::isUserNativeConstraints () const { return _flags&CntUserNativeConstraints; }
inline bool AutoContact::isTerminal () const { return _flags&CntTerminal; }
inline bool AutoContact::isHTee () const { return _flags&CntHTee; }
inline bool AutoContact::isVTee () const { return _flags&CntVTee; }
inline bool AutoContact::isHDogleg () const { return _flags&CntHDogleg; }
inline bool AutoContact::isVDogleg () const { return _flags&CntVDogleg; }
inline bool AutoContact::hasBadTopology () const { return _flags&CntBadTopology; }
inline bool AutoContact::canDrag () const { return _flags&CntDrag; }
inline size_t AutoContact::getId () const { return _id; }
inline Flags AutoContact::getFlags () const { return _flags; }
inline Contact* AutoContact::base () const { return _contact; }
inline GCell* AutoContact::getGCell () const { return _gcell; }
inline Box AutoContact::getConstraintBox () const { return Box(getCBXMin(),getCBYMin(),getCBXMax(),getCBYMax()); }
inline void AutoContact::setCBXMin ( DbU::Unit xMin ) { _xMin = _boundX(xMin); }
inline void AutoContact::setCBXMax ( DbU::Unit xMax ) { _xMax = _boundX(xMax); }
inline void AutoContact::setCBYMin ( DbU::Unit yMin ) { _yMin = _boundY(yMin); }
inline void AutoContact::setCBYMax ( DbU::Unit yMax ) { _yMax = _boundY(yMax); }
inline void AutoContact::setFlags ( Flags flags ) { _flags|= flags; }
inline void AutoContact::unsetFlags ( Flags flags ) { _flags&=~flags; }
inline DbU::Unit AutoContact::getCBXMin () const { return isFixed() ? _contact->getX() : _xMin; }
inline DbU::Unit AutoContact::getCBXMax () const { return isFixed() ? _contact->getX() : _xMax; }
inline DbU::Unit AutoContact::getCBYMin () const { return isFixed() ? _contact->getY() : _yMin; }
inline DbU::Unit AutoContact::getCBYMax () const { return isFixed() ? _contact->getY() : _yMax; }
inline unsigned int AutoContact::getMinDepth () const
{ size_t minDepth, maxDepth; getDepthSpan(minDepth,maxDepth); return minDepth; }
inline unsigned int AutoContact::getMaxDepth () const
{ size_t minDepth, maxDepth; getDepthSpan(minDepth,maxDepth); return maxDepth; }
inline int AutoContact::_boundX ( DbU::Unit x ) const
{ return (x<_gcell->getXMin()) ? _gcell->getXMin()
: ((x>_gcell->getConstraintXMax()) ? _gcell->getConstraintXMax() : x); }
inline int AutoContact::_boundY ( DbU::Unit y ) const
{ return (y<_gcell->getYMin()) ? _gcell->getYMin()
: ((y>_gcell->getConstraintYMax()) ? _gcell->getConstraintYMax() : y); }
// -------------------------------------------------------------------
// Class : "Anabatic::LocatorHelper".
class LocatorHelper {
public:
inline LocatorHelper ( AutoContact*, Flags flags=Flags::NoFlags );
inline bool isValid () const;
inline AutoSegment* getSegment () const;
inline void progress ();
private:
inline unsigned int _min () const;
inline unsigned int _max () const;
private:
Flags _flags;
unsigned int _index;
AutoContact* _contact;
};
inline LocatorHelper::LocatorHelper ( AutoContact* contact, Flags flags )
: _flags(flags), _index(_min()), _contact(contact)
{
cdebug_tabw(144,1);
cdebug_log(144,0) << "CTOR LocatorHelper " << contact->_getString() << endl;
cdebug_log(144,0) << "+ _min():" << _min() << endl;
cdebug_log(144,0) << "+ _max():" << _max() << endl;
cdebug_log(144,0) << "+ getSegment(_min()):" << _contact->getSegment(_min()) << endl;
if (not _contact->getSegment(_index)) progress();
cdebug_tabw(144,-1);
}
inline bool LocatorHelper::isValid () const
{ return _index < _max(); }
inline unsigned int LocatorHelper::_min () const
{ return (_flags & (Flags::Horizontal|Flags::WithPerpands)) ? 0 : 2; }
inline unsigned int LocatorHelper::_max () const
{ return ((_flags & Flags::Horizontal) and not (_flags & Flags::WithPerpands)) ? 2 : 4; }
inline AutoSegment* LocatorHelper::getSegment () const
{
cdebug_log(144,0) << " LocatorHelper::getSegment(" << _index << ") - " << _contact->getSegment(_index) << endl;
return (_index < _max()) ? _contact->getSegment(_index) : NULL;
}
inline void LocatorHelper::progress ()
{
cdebug_tabw(144,1);
++_index;
cdebug_log(144,0) << "LocatorHelper::progress() [" << _index << "] " << _contact->getSegment(_index) << endl;
while ((_index < _max()) and (_contact->getSegment(_index) == NULL)) {
++_index;
cdebug_log(144,0) << "LocatorHelper::progress() [" << _index << "] " << _contact->getSegment(_index) << endl;
}
cdebug_tabw(144,-1);
}
// -------------------------------------------------------------------
// Helper Functions.
inline size_t abssub ( size_t a, size_t b ) { return (a>b) ? a-b : b-a; }
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoContact);
#endif // ANABATIC_AUTOCONTACT_H

View File

@ -1,72 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoContactHTee.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOCONTACT_HTEE_H
#define ANABATIC_AUTOCONTACT_HTEE_H
#include "anabatic/AutoContact.h"
namespace Anabatic {
class AutoHorizontal;
class AutoVertical;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactHTee".
class AutoContactHTee : public AutoContact {
typedef AutoContact Super;
friend class AutoContact;
public:
static AutoContactHTee* create ( GCell*, Net*, const Layer* );
protected:
// Constructors & Destructors.
AutoContactHTee ( GCell*, Contact* );
virtual ~AutoContactHTee ();
virtual void _invalidate ( Flags flags );
public:
virtual AutoHorizontal* getHorizontal1 () const;
virtual AutoHorizontal* getHorizontal2 () const;
virtual AutoVertical* getVertical1 () const;
virtual AutoSegment* getOpposite ( const AutoSegment* ) const;
virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const;
virtual AutoSegment* getSegment ( unsigned int ) const;
virtual void updateGeometry ();
virtual void updateTopology ();
virtual void cacheDetach ( AutoSegment* );
virtual void cacheAttach ( AutoSegment* );
virtual void updateCache ();
virtual string _getTypeName () const;
private:
AutoContactHTee ( const AutoContactHTee& );
AutoContactHTee& operator= ( const AutoContactHTee& );
private:
AutoHorizontal* _horizontal1;
AutoHorizontal* _horizontal2;
AutoVertical* _vertical1;
};
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoContactHTee);
#endif // ANABATIC_AUTOCONTACT_HTEE_H

View File

@ -1,95 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2012-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoContactTerminal.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOCONTACT_TERMINAL_H
#define ANABATIC_AUTOCONTACT_TERMINAL_H
#include "anabatic/AutoContact.h"
#include "anabatic/AutoSegments.h"
namespace Hurricane {
class RoutingPad;
}
namespace Anabatic {
using Hurricane::RoutingPad;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactTerminal".
class AutoContactTerminal : public AutoContact {
typedef AutoContact Super;
friend class AutoContact;
public:
static AutoContactTerminal* create ( GCell* gcell
, Component* anchor
, const Layer* layer
, Point point
, DbU::Unit width
, DbU::Unit height
);
static AutoContactTerminal* create ( GCell* gcell
, Component* anchor
, const Layer* layer
, const DbU::Unit dx
, const DbU::Unit dy
, const DbU::Unit width
, const DbU::Unit height
);
protected:
// Constructors & Destructors.
AutoContactTerminal ( GCell*, Contact* );
virtual ~AutoContactTerminal ();
virtual void _invalidate ( Flags flags );
public:
bool isEndPoint () const;
virtual bool isOnPin () const;
virtual Box getNativeConstraintBox () const;
RoutingPad* getRoutingPad () const;
inline AutoSegment* getSegment () const;
virtual AutoSegment* getSegment ( unsigned int ) const;
virtual AutoSegment* getOpposite ( const AutoSegment* ) const;
virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const;
AutoSegments getRpConnecteds () const;
virtual void updateGeometry ();
virtual void updateTopology ();
virtual void forceOnGrid ( Point );
virtual void cacheDetach ( AutoSegment* );
virtual void cacheAttach ( AutoSegment* );
virtual void updateCache ();
virtual string _getTypeName () const;
private:
AutoContactTerminal ( const AutoContactTerminal& );
AutoContactTerminal& operator= ( const AutoContactTerminal& );
protected:
AutoSegment* _segment;
};
inline AutoSegment* AutoContactTerminal::getSegment () const { return _segment; }
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoContactTerminal);
#endif // ANABATIC_AUTOCONTACT_TERMINAL_H

View File

@ -1,70 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoContactTurn.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOCONTACT_TURN_H
#define ANABATIC_AUTOCONTACT_TURN_H
#include "anabatic/AutoContact.h"
namespace Anabatic {
class AutoContactTerminal;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactTurn".
class AutoContactTurn : public AutoContact {
friend class AutoContact;
public:
static AutoContactTurn* create ( GCell*, Net*, const Layer* );
static void insert ( AutoContactTerminal* );
protected:
// Constructors & Destructors.
AutoContactTurn ( GCell*, Contact* );
virtual ~AutoContactTurn ();
virtual void _invalidate ( Flags flags );
public:
virtual AutoHorizontal* getHorizontal1 () const;
virtual AutoVertical* getVertical1 () const;
virtual AutoSegment* getOpposite ( const AutoSegment* ) const;
virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const;
virtual AutoSegment* getSegment ( unsigned int ) const;
virtual void updateGeometry ();
virtual void updateTopology ();
virtual void cacheDetach ( AutoSegment* );
virtual void cacheAttach ( AutoSegment* );
virtual void updateCache ();
virtual string _getTypeName () const;
private:
AutoContactTurn ( const AutoContactTurn& );
AutoContactTurn& operator= ( const AutoContactTurn& );
private:
AutoHorizontal* _horizontal1;
AutoVertical* _vertical1;
};
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoContactTurn);
#endif // ANABATIC_AUTOCONTACT_TURN_H

View File

@ -1,69 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoContactVTee.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOCONTACT_VTEE_H
#define ANABATIC_AUTOCONTACT_VTEE_H
#include "anabatic/AutoContact.h"
namespace Anabatic {
// -------------------------------------------------------------------
// Class : "Anabatic::AutoContactVTee".
class AutoContactVTee : public AutoContact {
typedef AutoContact Super;
friend class AutoContact;
public:
static AutoContactVTee* create ( GCell*, Net*, const Layer* );
protected:
// Constructors & Destructors.
AutoContactVTee ( GCell*, Contact* );
virtual ~AutoContactVTee ();
virtual void _invalidate ( Flags flags );
public:
virtual AutoHorizontal* getHorizontal1 () const;
virtual AutoVertical* getVertical1 () const;
virtual AutoVertical* getVertical2 () const;
virtual AutoSegment* getOpposite ( const AutoSegment* ) const;
virtual AutoSegment* getPerpandicular ( const AutoSegment* ) const;
virtual AutoSegment* getSegment ( unsigned int ) const;
virtual void updateGeometry ();
virtual void updateTopology ();
virtual void cacheDetach ( AutoSegment* );
virtual void cacheAttach ( AutoSegment* );
virtual void updateCache ();
virtual string _getTypeName () const;
private:
AutoContactVTee ( const AutoContactVTee& );
AutoContactVTee& operator= ( const AutoContactVTee& );
private:
AutoHorizontal* _horizontal1;
AutoVertical* _vertical1;
AutoVertical* _vertical2;
};
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoContactVTee);
#endif // ANABATIC_AUTOCONTACT_VTEE_H

View File

@ -1,91 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2013, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoHorizontal.h" |
// +-----------------------------------------------------------------+
#pragma once
#include "hurricane/Horizontal.h"
#include "anabatic/AutoSegment.h"
namespace Anabatic {
// -------------------------------------------------------------------
// Class : "AutoHorizontal".
class AutoHorizontal : public AutoSegment {
friend class AutoSegment;
public:
// Predicates.
virtual bool _canSlacken () const;
virtual bool canMoveULeft ( float reserve=0.0 ) const;
virtual bool canMoveURight ( float reserve=0.0 ) const;
// Accessors.
virtual Segment* base ();
virtual Segment* base () const;
virtual Horizontal* getHorizontal ();
virtual DbU::Unit getSourceU () const;
virtual DbU::Unit getTargetU () const;
virtual DbU::Unit getDuSource () const;
virtual DbU::Unit getDuTarget () const;
virtual Interval getSpanU () const;
virtual bool getConstraints ( DbU::Unit& min , DbU::Unit& max ) const;
virtual Interval getSourceConstraints ( Flags flags=0 ) const;
virtual Interval getTargetConstraints ( Flags flags=0 ) const;
virtual Flags getDirection () const;
virtual bool getGCells ( vector<GCell*>& ) const;
// Modifiers.
virtual void setDuSource ( DbU::Unit );
virtual void setDuTarget ( DbU::Unit );
virtual void _setAxis ( DbU::Unit );
virtual void updateOrient ();
virtual void updatePositions ();
virtual void updateNativeConstraints ();
virtual bool checkPositions () const;
virtual bool checkConstraints () const;
virtual Flags _makeDogleg ( GCell*, Flags flags );
virtual bool moveULeft ();
virtual bool moveURight ();
virtual bool _slacken ( Flags flags );
#if THIS_IS_DISABLED
virtual void desalignate ( AutoContact* );
#endif
// Inspector Management.
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
// Internal: Attributes.
protected:
Horizontal* _horizontal;
// Internal: Constructors.
protected:
AutoHorizontal ( Horizontal* );
virtual ~AutoHorizontal ();
virtual void _postCreate ();
virtual void _preDestroy ();
private:
AutoHorizontal ( const AutoHorizontal& );
AutoHorizontal& operator= ( const AutoHorizontal& );
};
} // End of Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoHorizontal);

View File

@ -1,709 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoSegment.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <tuple>
#include <set>
#include <iostream>
#include <functional>
#include "hurricane/Interval.h"
#include "hurricane/Segment.h"
#include "hurricane/Components.h"
#include "hurricane/Contact.h"
namespace Hurricane {
class Layer;
class Horizontal;
class Vertical;
class Cell;
}
#include "crlcore/RoutingGauge.h"
#include "anabatic/Constants.h"
#include "anabatic/GCell.h"
#include "anabatic/AutoSegments.h"
#include "anabatic/Session.h"
namespace Anabatic {
using std::tuple;
using std::array;
using std::set;
using std::cerr;
using std::endl;
using std::binary_function;
using Hurricane::StaticObservable;
using Hurricane::BaseObserver;
using Hurricane::tab;
using Hurricane::Interval;
using Hurricane::Layer;
using Hurricane::Components;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::Cell;
using CRL::RoutingGauge;
class AutoHorizontal;
class AutoVertical;
// -------------------------------------------------------------------
// Class : "AutoSegment".
class AutoSegment {
friend class AutoHorizontal;
friend class AutoVertical;
public:
static const uint64_t SegNoFlags = 0L;
static const uint64_t SegHorizontal = (1L<< 0);
static const uint64_t SegFixed = (1L<< 1);
static const uint64_t SegFixedAxis = (1L<< 2);
static const uint64_t SegGlobal = (1L<< 3);
static const uint64_t SegWeakGlobal = (1L<< 4);
static const uint64_t SegLongLocal = (1L<< 5);
static const uint64_t SegCanonical = (1L<< 6);
static const uint64_t SegBipoint = (1L<< 7);
static const uint64_t SegDogleg = (1L<< 8);
static const uint64_t SegStrap = (1L<< 9);
static const uint64_t SegSourceTop = (1L<<10);
static const uint64_t SegSourceBottom = (1L<<11);
static const uint64_t SegTargetTop = (1L<<12);
static const uint64_t SegTargetBottom = (1L<<13);
static const uint64_t SegIsReduced = (1L<<14);
static const uint64_t SegDrag = (1L<<15);
static const uint64_t SegLayerChange = (1L<<16);
static const uint64_t SegSourceTerminal = (1L<<17); // Replace Terminal.
static const uint64_t SegTargetTerminal = (1L<<18); // Replace Terminal.
static const uint64_t SegStrongTerminal = SegSourceTerminal|SegTargetTerminal;
static const uint64_t SegWeakTerminal1 = (1L<<19); // Replace TopologicalEnd.
static const uint64_t SegWeakTerminal2 = (1L<<20); // Replace TopologicalEnd.
static const uint64_t SegNotSourceAligned = (1L<<21);
static const uint64_t SegNotTargetAligned = (1L<<22);
static const uint64_t SegUnbound = (1L<<23);
static const uint64_t SegHalfSlackened = (1L<<24);
static const uint64_t SegSlackened = (1L<<25);
static const uint64_t SegAxisSet = (1L<<26);
static const uint64_t SegInvalidated = (1L<<27);
static const uint64_t SegInvalidatedSource = (1L<<28);
static const uint64_t SegInvalidatedTarget = (1L<<29);
static const uint64_t SegInvalidatedLayer = (1L<<30);
static const uint64_t SegCreated = (1L<<31);
static const uint64_t SegUserDefined = (1L<<32);
static const uint64_t SegAnalog = (1L<<33);
static const uint64_t SegWide = (1L<<34);
static const uint64_t SegShortNet = (1L<<35);
static const uint64_t SegUnbreakable = (1L<<36);
static const uint64_t SegNonPref = (1L<<37);
static const uint64_t SegAtMinArea = (1L<<38);
static const uint64_t SegNoMoveUp = (1L<<39);
static const uint64_t SegOnVSmall = (1L<<40);
// Masks.
static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2;
static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned;
static const uint64_t SegSpinTop = SegSourceTop |SegTargetTop;
static const uint64_t SegSpinBottom = SegSourceBottom |SegTargetBottom;
static const uint64_t SegDepthSpin = SegSpinTop |SegSpinBottom;
public:
class Observable : public StaticObservable<1> {
public:
enum Indexes { TrackSegment = 0
};
public:
inline Observable ();
private:
Observable ( const StaticObservable& );
Observable& operator= ( const StaticObservable& );
};
public:
enum ObserverFlag { Create = (1 << 0)
, Destroy = (1 << 1)
, Invalidate = (1 << 2)
, Revalidate = (1 << 3)
, RevalidatePPitch = (1 << 4)
};
public:
typedef std::function< void(AutoSegment*) > RevalidateCb_t;
public:
static void setAnalogMode ( bool );
static bool getAnalogMode ();
static void setShortNetMode ( bool );
inline static DbU::Unit getViaToTopCap ( size_t depth );
inline static DbU::Unit getViaToBottomCap ( size_t depth );
inline static DbU::Unit getViaToSameCap ( size_t depth );
inline static DbU::Unit getMinimalLength ( size_t depth );
static AutoSegment* create ( AutoContact* source
, AutoContact* target
, Segment* hurricaneSegment
);
static AutoSegment* create ( AutoContact* source
, AutoContact* target
, Flags dir
, size_t depth=RoutingGauge::nlayerdepth
);
void destroy ();
// Wrapped Segment Functions.
virtual Segment* base () const = 0;
virtual Segment* base () = 0;
virtual Horizontal* getHorizontal () { return NULL; };
virtual Vertical* getVertical () { return NULL; };
inline Cell* getCell () const;
inline Net* getNet () const;
inline const Layer* getLayer () const;
inline Box getBoundingBox () const;
inline Hook* getSourceHook ();
inline Hook* getTargetHook ();
inline Contact* getSource () const;
inline Contact* getTarget () const;
inline Component* getOppositeAnchor ( Component* ) const;
inline Components getAnchors () const;
virtual DbU::Unit getX () const;
virtual DbU::Unit getY () const;
inline DbU::Unit getWidth () const;
inline DbU::Unit getContactWidth () const;
inline DbU::Unit getLength () const;
inline DbU::Unit getSpanLength () const;
inline DbU::Unit getAnchoredLength () const;
inline DbU::Unit getSourcePosition () const;
inline DbU::Unit getTargetPosition () const;
inline DbU::Unit getSourceX () const;
inline DbU::Unit getSourceY () const;
inline DbU::Unit getTargetX () const;
inline DbU::Unit getTargetY () const;
inline void invert ();
inline void setLayer ( const Layer* );
inline void setLayer ( size_t depth );
inline void setWidth ( DbU::Unit );
// Predicates.
inline bool isHorizontal () const;
inline bool isVertical () const;
inline bool isGlobal () const;
inline bool isWeakGlobal () const;
inline bool isLongLocal () const;
inline bool isLocal () const;
inline bool isFixed () const;
inline bool isFixedAxis () const;
inline bool isBipoint () const;
inline bool isWeakTerminal () const;
inline bool isWeakTerminal1 () const;
inline bool isWeakTerminal2 () const;
inline bool isTerminal () const;
inline bool isUnbreakable () const;
inline bool isNonPref () const;
inline bool isNonPrefOnVSmall () const;
inline bool isDrag () const;
inline bool isAtMinArea () const;
inline bool isNotSourceAligned () const;
inline bool isNotTargetAligned () const;
inline bool isNotAligned () const;
bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const;
inline bool isSourceTerminal () const;
inline bool isTargetTerminal () const;
inline bool isLayerChange () const;
inline bool isStackedStrap () const;
inline bool isSpinTop () const;
inline bool isSpinBottom () const;
inline bool isSpinTopOrBottom () const;
inline bool isReduced () const;
inline bool isStrap () const;
inline bool isDogleg () const;
inline bool isUnbound () const;
inline bool isInvalidated () const;
inline bool isInvalidatedLayer () const;
inline bool isCreated () const;
inline bool isCanonical () const;
inline bool isUnsetAxis () const;
inline bool isSlackened () const;
inline bool isUserDefined () const;
bool isNearMinArea () const;
bool isReduceCandidate () const;
bool isUTurn () const;
inline bool isAnalog () const;
inline bool isWide () const;
inline bool isShortNet () const;
inline bool isNoMoveUp () const;
virtual bool _canSlacken () const = 0;
bool canReduce ( Flags flags=Flags::WithPerpands ) const;
bool mustRaise () const;
Flags canDogleg ( Interval );
virtual bool canMoveULeft ( float reserve=0.0 ) const = 0;
virtual bool canMoveURight ( float reserve=0.0 ) const = 0;
bool canMoveUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const;
bool canPivotUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const;
bool canPivotDown ( float reserve=0.0, Flags flags=Flags::NoFlags ) const;
bool canSlacken ( Flags flags=Flags::NoFlags ) const;
virtual bool checkPositions () const = 0;
virtual bool checkConstraints () const = 0;
bool checkDepthSpin () const;
// Accessors.
inline unsigned long getId () const;
inline uint64_t getFlags () const;
virtual Flags getDirection () const = 0;
inline GCell* getGCell () const;
virtual bool getGCells ( vector<GCell*>& ) const = 0;
inline AutoContact* getAutoSource () const;
inline AutoContact* getAutoTarget () const;
AutoContact* getOppositeAnchor ( AutoContact* ) const;
size_t getPerpandicularsBound ( set<AutoSegment*>& );
inline AutoSegment* getParent () const;
inline unsigned int getRpDistance () const;
inline unsigned int getDepth () const;
inline DbU::Unit getPitch () const;
DbU::Unit getPPitch () const;
#if DISABLED
DbU::Unit getExtensionCap () const;
#endif
DbU::Unit getExtensionCap ( Flags ) const;
inline DbU::Unit getAxis () const;
void getEndAxes ( DbU::Unit& sourceAxis, DbU::Unit& targetAxis ) const;
virtual DbU::Unit getSourceU () const = 0;
virtual DbU::Unit getTargetU () const = 0;
virtual DbU::Unit getDuSource () const = 0;
virtual DbU::Unit getDuTarget () const = 0;
inline DbU::Unit getOrigin () const;
inline DbU::Unit getExtremity () const;
virtual Interval getSpanU () const = 0;
Interval getMinSpanU () const;
virtual Interval getSourceConstraints ( Flags flags=Flags::NoFlags ) const = 0;
virtual Interval getTargetConstraints ( Flags flags=Flags::NoFlags ) const = 0;
virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const = 0;
inline bool getConstraints ( Interval& i ) const;
inline const Interval& getUserConstraints () const;
inline const Interval& getNativeConstraints () const;
virtual DbU::Unit getSlack () const;
inline DbU::Unit getOptimalMin () const;
inline DbU::Unit getOptimalMax () const;
inline DbU::Unit getNativeMin () const;
inline DbU::Unit getNativeMax () const;
Interval& getOptimal ( Interval& i ) const;
virtual DbU::Unit getCost ( DbU::Unit axis ) const;
virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max );
inline AutoSegment* getCanonical ( Interval& i );
float getMaxUnderDensity ( Flags flags );
inline uint32_t getReduceds () const;
uint32_t getNonReduceds ( Flags flags=Flags::WithPerpands ) const;
// Modifiers.
inline void unsetFlags ( uint64_t );
inline void setFlags ( uint64_t );
void setFlagsOnAligneds ( uint64_t );
inline void setRpDistance ( unsigned int );
inline void incReduceds ();
inline void decReduceds ();
virtual void setDuSource ( DbU::Unit du ) = 0;
virtual void setDuTarget ( DbU::Unit du ) = 0;
void computeTerminal ();
virtual void updateOrient () = 0;
virtual void updatePositions () = 0;
virtual void updateNativeConstraints () = 0;
void updateSourceSpin ();
void updateTargetSpin ();
void sourceDetach ();
void targetDetach ();
void sourceAttach ( AutoContact* );
void targetAttach ( AutoContact* );
//inline void mergeUserConstraints ( const Interval& );
void mergeUserConstraints ( const Interval& );
inline void resetUserConstraints ();
inline void setOptimalMin ( DbU::Unit min );
inline void setOptimalMax ( DbU::Unit max );
inline void mergeNativeMin ( DbU::Unit min );
inline void mergeNativeMax ( DbU::Unit max );
inline void resetNativeConstraints ( DbU::Unit min, DbU::Unit max );
bool checkNotInvalidated () const;
inline void setParent ( AutoSegment* );
void revalidate ();
AutoSegment* makeDogleg ( AutoContact* );
Flags makeDogleg ( Interval, Flags flags=Flags::NoFlags );
Flags makeDogleg ( GCell* , Flags flags=Flags::NoFlags );
virtual Flags _makeDogleg ( GCell* , Flags flags ) = 0;
virtual bool moveULeft () = 0;
virtual bool moveURight () = 0;
bool slacken ( Flags flags );
virtual bool _slacken ( Flags flags ) = 0;
void _changeDepth ( unsigned int depth, Flags flags );
void changeDepth ( unsigned int depth, Flags flags );
bool moveUp ( Flags flags=Flags::NoFlags );
bool moveDown ( Flags flags=Flags::NoFlags );
bool reduceDoglegLayer ();
bool bloatStackedStrap ();
bool reduce ( Flags flags=Flags::WithPerpands );
bool raise ();
void expandToMinLength ( Interval );
void unexpandToMinLength ();
// Canonical Modifiers.
AutoSegment* canonize ( Flags flags=Flags::NoFlags );
virtual void invalidate ( Flags flags=Flags::Propagate );
void invalidate ( AutoContact* );
void computeOptimal ( set<AutoSegment*>& processeds );
void setAxis ( DbU::Unit, Flags flags=Flags::NoFlags );
bool toConstraintAxis ( Flags flags=Flags::Realignate );
bool toOptimalAxis ( Flags flags=Flags::Realignate );
// Collections & Filters.
AutoSegments getOnSourceContact ( Flags direction );
AutoSegments getOnTargetContact ( Flags direction );
AutoSegments getCachedOnSourceContact ( Flags direction );
AutoSegments getCachedOnTargetContact ( Flags direction );
AutoSegments getAligneds ( Flags flags=Flags::NoFlags );
AutoSegments getConnecteds ( Flags flags=Flags::NoFlags );
AutoSegments getPerpandiculars ( Flags flags=Flags::NoFlags );
size_t getAlignedContacts ( map<AutoContact*,int>& ) const ;
// Observers.
template< typename OwnerT >
inline OwnerT* getObserver ( size_t slot );
inline void setObserver ( size_t slot, BaseObserver* );
inline void notify ( unsigned int flags );
// Inspector Management.
virtual Record* _getRecord () const = 0;
virtual string _getString () const = 0;
virtual string _getTypeName () const = 0;
// Non-reviewed atomic modifiers.
bool _check () const;
#if THIS_IS_DISABLED
virtual void desalignate ( AutoContact* ) = 0;
bool shearUp ( GCell*
, AutoSegment*& movedUp
, float reserve
, Flags flags );
#endif
protected:
// Internal: Static Attributes.
static size_t _allocateds;
static size_t _globalsCount;
static bool _analogMode;
static bool _shortNetMode;
static bool _initialized;
static vector< array<DbU::Unit*,4> > _extensionCaps;
// Internal: Attributes.
const unsigned long _id;
GCell* _gcell;
uint64_t _flags;
unsigned int _depth : 8;
unsigned int _optimalMin :16;
unsigned int _optimalMax :16;
unsigned int _reduceds : 2;
unsigned int _rpDistance : 4;
DbU::Unit _sourcePosition;
DbU::Unit _targetPosition;
Interval _userConstraints;
Interval _nativeConstraints;
AutoSegment* _parent;
Observable _observers;
// Internal: Constructors & Destructors.
protected:
AutoSegment ( Segment* segment );
virtual ~AutoSegment ();
static void _preCreate ( AutoContact* source, AutoContact* target );
virtual void _postCreate ();
virtual void _preDestroy ();
static void _initialize ();
private:
AutoSegment ( const AutoSegment& );
AutoSegment& operator= ( const AutoSegment& );
protected:
void _invalidate ();
inline uint64_t _getFlags () const;
std::string _getStringFlags () const;
virtual void _setAxis ( DbU::Unit ) = 0;
public:
struct CompareId : public binary_function<AutoSegment*,AutoSegment*,bool> {
inline bool operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const;
};
public:
struct CompareByDepthLength : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public:
struct CompareByDepthAxis : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public:
struct CompareBySourceU : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public:
struct CompareByRevalidate : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
struct CompareByReduceds : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public:
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
typedef std::set<AutoSegment*,CompareId> IdSet;
// Static Utilities.
public:
static inline uint64_t swapSourceTargetFlags ( AutoSegment* );
static inline bool areAlignedsAndDiffLayer ( AutoSegment*, AutoSegment* );
static AutoSegment* getGlobalThroughDogleg ( AutoSegment* dogleg, AutoContact* from );
static bool isTopologicalBound ( AutoSegment* seed, Flags flags );
static inline bool arePerpandiculars ( AutoSegment* a, AutoSegment* b );
static inline bool arePerpandiculars ( bool isHorizontalA, AutoSegment* b );
static inline bool areAligneds ( AutoSegment* a, AutoSegment* b );
static Flags getPerpandicularState ( AutoContact* contact
, AutoSegment* source
, AutoSegment* current
, bool isHorizontalMaster
, const Layer* masterLayer=NULL
);
static inline Flags getPerpandicularState ( AutoContact* contact
, AutoSegment* source
, AutoSegment* current
, AutoSegment* master
);
static void getTopologicalInfos ( AutoSegment* seed
, vector<AutoSegment*>& collapseds
, vector< tuple<AutoSegment*,Flags> >&
perpandiculars
, DbU::Unit& leftBound
, DbU::Unit& rightBound
);
static int getTerminalCount ( AutoSegment* seed
, vector<AutoSegment*>& collapseds
);
static inline int getTerminalCount ( AutoSegment* seed );
static inline size_t getGlobalsCount ();
static inline size_t getAllocateds ();
static inline unsigned long getMaxId ();
};
// Inline Functions.
inline DbU::Unit AutoSegment::getViaToTopCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][0]) : 0; }
inline DbU::Unit AutoSegment::getViaToBottomCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][1]) : 0; }
inline DbU::Unit AutoSegment::getViaToSameCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][2]) : 0; }
inline DbU::Unit AutoSegment::getMinimalLength ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][3]) : 0; }
inline unsigned long AutoSegment::getId () const { return _id; }
inline Cell* AutoSegment::getCell () const { return base()->getCell(); }
inline Net* AutoSegment::getNet () const { return base()->getNet(); }
inline const Layer* AutoSegment::getLayer () const { return base()->getLayer(); }
inline Box AutoSegment::getBoundingBox () const { return base()->getBoundingBox(); }
inline Hook* AutoSegment::getSourceHook () { return base()->getSourceHook(); }
inline Hook* AutoSegment::getTargetHook () { return base()->getTargetHook(); }
inline Contact* AutoSegment::getSource () const { return static_cast<Contact*>(base()->getSource()); }
inline Contact* AutoSegment::getTarget () const { return static_cast<Contact*>(base()->getTarget()); }
inline Component* AutoSegment::getOppositeAnchor ( Component* anchor ) const { return base()->getOppositeAnchor(anchor); };
inline AutoSegment* AutoSegment::getParent () const { return _parent; }
inline DbU::Unit AutoSegment::getSourcePosition () const { return _sourcePosition; }
inline DbU::Unit AutoSegment::getTargetPosition () const { return _targetPosition; }
inline DbU::Unit AutoSegment::getSourceX () const { return base()->getSourceX(); }
inline DbU::Unit AutoSegment::getSourceY () const { return base()->getSourceY(); }
inline DbU::Unit AutoSegment::getTargetX () const { return base()->getTargetX(); }
inline DbU::Unit AutoSegment::getTargetY () const { return base()->getTargetY(); }
inline DbU::Unit AutoSegment::getWidth () const { return base()->getWidth(); }
inline DbU::Unit AutoSegment::getLength () const { return base()->getLength(); }
inline void AutoSegment::invert () { base()->invert(); }
inline GCell* AutoSegment::getGCell () const { return _gcell; }
inline AutoContact* AutoSegment::getAutoSource () const { return Session::lookup(getSource()); }
inline AutoContact* AutoSegment::getAutoTarget () const { return Session::lookup(getTarget()); }
inline bool AutoSegment::getConstraints ( Interval& i ) const { return getConstraints(i.getVMin(),i.getVMax()); }
inline AutoSegment* AutoSegment::getCanonical ( Interval& i ) { return getCanonical(i.getVMin(),i.getVMax()); }
inline unsigned int AutoSegment::getDepth () const { return _depth; }
inline unsigned int AutoSegment::getRpDistance () const { return _rpDistance; }
inline DbU::Unit AutoSegment::getPitch () const { return Session::getPitch(getDepth(),Flags::NoFlags); }
inline DbU::Unit AutoSegment::getAxis () const { return isHorizontal()?base()->getY():base()->getX(); }
inline DbU::Unit AutoSegment::getOrigin () const { return isHorizontal()?_gcell->getYMin():_gcell->getXMin(); }
inline DbU::Unit AutoSegment::getExtremity () const { return isHorizontal()?_gcell->getYMax():_gcell->getXMax(); }
inline DbU::Unit AutoSegment::getOptimalMin () const { return DbU::lambda(_optimalMin) + getOrigin(); }
inline DbU::Unit AutoSegment::getOptimalMax () const { return DbU::lambda(_optimalMax) + getOrigin(); }
inline DbU::Unit AutoSegment::getNativeMin () const { return _nativeConstraints.getVMin(); }
inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); }
inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; }
inline const Interval& AutoSegment::getNativeConstraints () const { return _nativeConstraints; }
inline uint32_t AutoSegment::getReduceds () const { return _reduceds; }
inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; }
inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); }
inline bool AutoSegment::isFixed () const { return _flags & SegFixed; }
inline bool AutoSegment::isFixedAxis () const { return _flags & SegFixedAxis; }
inline bool AutoSegment::isGlobal () const { return _flags & SegGlobal; }
inline bool AutoSegment::isWeakGlobal () const { return _flags & SegWeakGlobal; }
inline bool AutoSegment::isLongLocal () const { return _flags & SegLongLocal; }
inline bool AutoSegment::isLocal () const { return not (_flags & SegGlobal); }
inline bool AutoSegment::isUnbreakable () const { return _flags & SegUnbreakable; }
inline bool AutoSegment::isNonPref () const { return _flags & SegNonPref; }
inline bool AutoSegment::isNonPrefOnVSmall () const { return (_flags & SegNonPref) and (_flags & SegOnVSmall); }
inline bool AutoSegment::isBipoint () const { return _flags & SegBipoint; }
inline bool AutoSegment::isWeakTerminal () const { return (_rpDistance < 2); }
inline bool AutoSegment::isWeakTerminal1 () const { return (_rpDistance == 1); }
inline bool AutoSegment::isWeakTerminal2 () const { return (_rpDistance == 2); }
inline bool AutoSegment::isSourceTerminal () const { return _flags & SegSourceTerminal; }
inline bool AutoSegment::isTargetTerminal () const { return _flags & SegTargetTerminal; }
inline bool AutoSegment::isTerminal () const { return (_rpDistance == 0); }
inline bool AutoSegment::isDrag () const { return _flags & SegDrag; }
inline bool AutoSegment::isAtMinArea () const { return _flags & SegAtMinArea; }
inline bool AutoSegment::isNotSourceAligned () const { return _flags & SegNotSourceAligned; }
inline bool AutoSegment::isNotTargetAligned () const { return _flags & SegNotTargetAligned; }
inline bool AutoSegment::isNotAligned () const { return (_flags & SegNotAligned) == SegNotAligned; }
inline bool AutoSegment::isDogleg () const { return _flags & SegDogleg ; }
inline bool AutoSegment::isUnbound () const { return _flags & SegUnbound ; }
inline bool AutoSegment::isStrap () const { return _flags & SegStrap; }
inline bool AutoSegment::isLayerChange () const { return _flags & SegLayerChange; }
inline bool AutoSegment::isSpinTop () const { return ((_flags & SegSpinTop ) == SegSpinTop); }
inline bool AutoSegment::isSpinBottom () const { return ((_flags & SegSpinBottom) == SegSpinBottom); }
inline bool AutoSegment::isSpinTopOrBottom () const { return isSpinTop() or isSpinBottom(); }
inline bool AutoSegment::isReduced () const { return _flags & SegIsReduced; }
inline bool AutoSegment::isSlackened () const { return _flags & SegSlackened; }
inline bool AutoSegment::isCanonical () const { return _flags & SegCanonical; }
inline bool AutoSegment::isUnsetAxis () const { return not (_flags & SegAxisSet); }
inline bool AutoSegment::isInvalidated () const { return _flags & SegInvalidated; }
inline bool AutoSegment::isInvalidatedLayer () const { return _flags & SegInvalidatedLayer; }
inline bool AutoSegment::isCreated () const { return _flags & SegCreated; }
inline bool AutoSegment::isUserDefined () const { return _flags & SegUserDefined; }
inline bool AutoSegment::isAnalog () const { return _flags & SegAnalog; }
inline bool AutoSegment::isWide () const { return _flags & SegWide; }
inline bool AutoSegment::isShortNet () const { return _flags & SegShortNet; }
inline bool AutoSegment::isNoMoveUp () const { return _flags & SegNoMoveUp; }
inline void AutoSegment::setFlags ( uint64_t flags ) { _flags |= flags; }
inline void AutoSegment::unsetFlags ( uint64_t flags ) { _flags &= ~flags; }
inline uint64_t AutoSegment::getFlags () const { return _flags; }
inline uint64_t AutoSegment::_getFlags () const { return _flags; }
inline void AutoSegment::setRpDistance ( unsigned int distance ) { _rpDistance=distance; }
inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; }
inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; }
inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); _flags|=SegInvalidatedLayer; }
inline void AutoSegment::setWidth ( DbU::Unit width ) { base()->setWidth(width); }
inline void AutoSegment::setOptimalMin ( DbU::Unit min ) { _optimalMin = (unsigned int)DbU::getLambda(min-getOrigin()); }
inline void AutoSegment::setOptimalMax ( DbU::Unit max ) { _optimalMax = (unsigned int)DbU::getLambda(max-getOrigin()); }
inline void AutoSegment::mergeNativeMin ( DbU::Unit min ) { _nativeConstraints.getVMin() = std::max( min, _nativeConstraints.getVMin() ); }
inline void AutoSegment::mergeNativeMax ( DbU::Unit max ) { _nativeConstraints.getVMax() = std::min( max, _nativeConstraints.getVMax() ); }
inline void AutoSegment::resetNativeConstraints ( DbU::Unit min, DbU::Unit max ) { _nativeConstraints = Interval( min, max ); }
//inline void AutoSegment::mergeUserConstraints ( const Interval& constraints ) { _userConstraints.intersection(constraints); }
inline void AutoSegment::resetUserConstraints () { _userConstraints = Interval(false); }
inline DbU::Unit AutoSegment::getAnchoredLength () const { return std::abs(getTargetU() - getSourceU()); }
inline void AutoSegment::setLayer ( size_t depth )
{
RoutingLayerGauge* layerGauge = Session::getLayerGauge( depth );
base()->setLayer( layerGauge->getLayer () );
base()->setWidth( layerGauge->getWireWidth() );
_depth = depth;
_flags|=SegInvalidatedLayer;
}
inline DbU::Unit AutoSegment::getContactWidth () const
{ return getWidth() + Session::getViaWidth(getLayer()) - Session::getWireWidth(getLayer()); }
inline DbU::Unit AutoSegment::getSpanLength () const
{ return getAnchoredLength() + getExtensionCap( Flags::Source|Flags::LayerCapOnly|Flags::NoMinLength )
+ getExtensionCap( Flags::Target|Flags::LayerCapOnly|Flags::NoMinLength );
}
inline void AutoSegment::setParent ( AutoSegment* parent )
{
if ( parent == this ) {
cerr << "Parentage Looping: " << parent->_getString() << endl;
}
_parent = parent;
}
inline bool AutoSegment::CompareId::operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const
{ return lhs->getId() < rhs->getId(); }
inline uint64_t AutoSegment::swapSourceTargetFlags ( AutoSegment* segment )
{
uint64_t segFlags = segment->getFlags();
uint64_t swapFlags = segment->getFlags() & ~(SegSourceTop |SegTargetTop
|SegSourceBottom |SegTargetBottom
|SegSourceTerminal |SegTargetTerminal
|SegNotSourceAligned |SegNotTargetAligned
|SegInvalidatedSource|SegInvalidatedTarget
);
swapFlags |= (segFlags & SegSourceTop ) ? SegTargetTop : SegNoFlags;
swapFlags |= (segFlags & SegSourceBottom ) ? SegTargetBottom : SegNoFlags;
swapFlags |= (segFlags & SegSourceTerminal ) ? SegTargetTerminal : SegNoFlags;
swapFlags |= (segFlags & SegNotSourceAligned ) ? SegNotTargetAligned : SegNoFlags;
swapFlags |= (segFlags & SegInvalidatedSource) ? SegInvalidatedTarget : SegNoFlags;
swapFlags |= (segFlags & SegTargetTop ) ? SegSourceTop : SegNoFlags;
swapFlags |= (segFlags & SegTargetBottom ) ? SegSourceBottom : SegNoFlags;
swapFlags |= (segFlags & SegTargetTerminal ) ? SegSourceTerminal : SegNoFlags;
swapFlags |= (segFlags & SegNotTargetAligned ) ? SegNotSourceAligned : SegNoFlags;
swapFlags |= (segFlags & SegInvalidatedTarget) ? SegInvalidatedSource : SegNoFlags;
return swapFlags;
}
inline bool AutoSegment::areAlignedsAndDiffLayer ( AutoSegment* s1, AutoSegment* s2 )
{ return s1 and s2
and (s1->isHorizontal() == s2->isHorizontal())
and (s1->getLayer() != s2->getLayer()); }
inline bool AutoSegment::arePerpandiculars ( AutoSegment* a, AutoSegment* b )
{ return a and b and (a->isHorizontal() != b->isHorizontal()); }
inline bool AutoSegment::arePerpandiculars ( bool isHorizontalA, AutoSegment* b )
{ return b and (isHorizontalA != b->isHorizontal()); }
inline bool AutoSegment::areAligneds ( AutoSegment* a, AutoSegment* b )
{ return a and b and (a->isHorizontal() == b->isHorizontal()); }
inline Flags AutoSegment::getPerpandicularState ( AutoContact* contact
, AutoSegment* source
, AutoSegment* current
, AutoSegment* master )
{
return getPerpandicularState ( contact, source, current, master->isHorizontal(), master->getLayer() );
}
inline int AutoSegment::getTerminalCount ( AutoSegment* seed )
{
cdebug_log(145,0) << "getTerminalCount() - " << seed << endl;
vector<AutoSegment*> collapseds;
vector< tuple<AutoSegment*,Flags> >
perpandiculars;
DbU::Unit leftBound;
DbU::Unit rightBound;
getTopologicalInfos ( seed
, collapseds
, perpandiculars
, leftBound
, rightBound
);
return getTerminalCount ( seed, collapseds );
}
inline size_t AutoSegment::getGlobalsCount () { return _globalsCount; }
inline size_t AutoSegment::getAllocateds () { return _allocateds; }
inline void AutoSegment::setObserver ( size_t slot, BaseObserver* observer )
{ _observers.setObserver( slot, observer ); }
template<typename OwnerT>
inline OwnerT* AutoSegment::getObserver ( size_t slot )
{ return _observers.getObserver<OwnerT>(slot); }
inline void AutoSegment::notify ( unsigned int flags )
{ _observers.notify( flags ); }
inline AutoSegment::Observable::Observable () : StaticObservable<1>() { }
} // End of Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoSegment);

View File

@ -1,559 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoSegments.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_AUTOSEGMENTS_H
#define ANABATIC_AUTOSEGMENTS_H
#include <string>
#include <list>
#include <vector>
#include <array>
#include <map>
#include "hurricane/Collection.h"
#include "hurricane/DbU.h"
#include "hurricane/Box.h"
namespace Hurricane {
class Hook;
class Component;
class Contact;
class Segment;
class RoutingPad;
class Net;
}
namespace Anabatic {
using std::string;
using std::pair;
using std::list;
using std::vector;
using std::map;
using Hurricane::Record;
using Hurricane::DbU;
using Hurricane::Box;
using Hurricane::Hook;
using Hurricane::Entity;
using Hurricane::Component;
using Hurricane::Contact;
using Hurricane::Segment;
using Hurricane::RoutingPad;
using Hurricane::Net;
using Hurricane::Filter;
using Hurricane::Locator;
using Hurricane::Collection;
using Hurricane::GenericFilter;
using Hurricane::GenericLocator;
using Hurricane::GenericCollection;
class LocatorHelper;
class AutoContact;
class AutoContactTerminal;
class AutoSegment;
class GCell;
// -------------------------------------------------------------------
// Collections.
typedef Hurricane::Filter<AutoSegment*> AutoSegmentHF;
typedef Hurricane::Locator<AutoSegment*> AutoSegmentHL;
typedef Hurricane::Collection<AutoSegment*> AutoSegmentHC;
typedef GenericCollection<AutoSegment*> AutoSegments;
typedef GenericLocator<AutoSegment*> AutoSegmentLocator;
typedef GenericFilter<AutoSegment*> AutoSegmentFilter;
typedef map<Segment*,AutoSegment*,Entity::CompareById> AutoSegmentLut;
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegmentStack".
class AutoSegmentStack : protected list<pair<AutoContact*,AutoSegment*> > {
public:
inline bool isEmpty () const;
inline size_t getSize () const;
void push ( AutoContact*, AutoSegment* );
inline void pop ();
inline AutoContact* getAutoContact () const;
inline AutoSegment* getAutoSegment () const;
};
inline bool AutoSegmentStack::isEmpty () const { return empty(); };
inline size_t AutoSegmentStack::getSize () const { return size(); };
inline void AutoSegmentStack::pop () { if ( !empty() ) pop_back(); };
inline AutoContact* AutoSegmentStack::getAutoContact () const { return empty() ? NULL : back().first; };
inline AutoSegment* AutoSegmentStack::getAutoSegment () const { return empty() ? NULL : back().second; };
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegments_OnContact".
class AutoSegments_OnContact : public AutoSegmentHC {
public:
// Sub-Class: Locator.
class Locator : public AutoSegmentHL {
public:
Locator ( AutoSegment* master, Contact* contact );
inline Locator ( const Locator& );
virtual AutoSegment* getElement () const;
virtual AutoSegmentHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
AutoSegment* _master;
Hook* _hook;
AutoSegment* _element;
};
public:
// AutoSegments_OnContact Methods.
inline AutoSegments_OnContact ( AutoSegment* master, Contact* contact );
inline AutoSegments_OnContact ( const AutoSegments_OnContact& );
virtual AutoSegmentHC* getClone () const;
virtual AutoSegmentHL* getLocator () const;
virtual string _getString () const;
protected:
// AutoSegments_OnContact Attributes.
AutoSegment* _master;
Contact* _contact;
};
inline AutoSegments_OnContact::Locator::Locator ( const Locator &locator )
: AutoSegmentHL()
, _master(locator._master)
, _hook(locator._hook)
, _element(locator._element)
{ }
inline AutoSegments_OnContact::AutoSegments_OnContact ( AutoSegment* master, Contact* contact )
: AutoSegmentHC()
, _master(master)
, _contact(contact)
{ }
inline AutoSegments_OnContact::AutoSegments_OnContact ( const AutoSegments_OnContact& segments )
: AutoSegmentHC()
, _master(segments._master)
, _contact(segments._contact)
{ }
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegments_OnRoutingPad".
class AutoSegments_OnRoutingPad : public AutoSegmentHC {
public:
// Sub-Class: Locator.
class Locator : public AutoSegmentHL {
public:
Locator ( RoutingPad* rp, const AutoContactTerminal* contact );
inline Locator ( const Locator& );
virtual AutoSegment* getElement () const;
virtual AutoSegmentHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
std::array<AutoSegment*,4> _elements;
size_t _index;
};
public:
// AutoSegments_OnRoutingPad Methods.
AutoSegments_OnRoutingPad ( const AutoContact* contact );
inline AutoSegments_OnRoutingPad ( const AutoSegments_OnRoutingPad& );
virtual AutoSegmentHC* getClone () const;
virtual AutoSegmentHL* getLocator () const;
virtual string _getString () const;
protected:
// AutoSegments_OnRoutingPad Attributes.
RoutingPad* _routingPad;
const AutoContactTerminal* _contact;
};
inline AutoSegments_OnRoutingPad::Locator::Locator ( const Locator &locator )
: AutoSegmentHL()
, _elements(locator._elements)
, _index (locator._index)
{ }
inline AutoSegments_OnRoutingPad::AutoSegments_OnRoutingPad ( const AutoSegments_OnRoutingPad& segments )
: AutoSegmentHC()
, _routingPad(segments._routingPad)
, _contact (segments._contact)
{ }
// -------------------------------------------------------------------
// Class : "AutoSegments_Aligneds".
class AutoSegments_Aligneds : public AutoSegmentHC {
public:
// Sub-Class: Locator.
class Locator : public AutoSegmentHL {
public:
inline Locator ( AutoSegment* segment , Flags flags );
inline Locator ( const Locator &locator );
virtual AutoSegment* getElement () const;
virtual AutoSegmentHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
Flags _flags;
AutoSegment* _master;
AutoSegmentStack _stack;
};
public:
// AutoSegments_Aligneds Methods.
AutoSegments_Aligneds ( AutoSegment*, Flags flags );
AutoSegments_Aligneds ( const AutoSegments_Aligneds& );
virtual AutoSegmentHC* getClone () const;
virtual AutoSegmentHL* getLocator () const;
virtual string _getString () const;
protected:
// AutoSegments_Aligneds Attributes.
Flags _flags;
AutoSegment* _segment;
};
inline AutoSegments_Aligneds::Locator::Locator ( const Locator &locator )
: AutoSegmentHL()
, _flags (locator._flags)
, _master(locator._master)
, _stack (locator._stack)
{ }
inline AutoSegments_Aligneds::AutoSegments_Aligneds ( AutoSegment* segment, Flags flags )
: AutoSegmentHC()
, _flags (flags)
, _segment(segment)
{ }
inline AutoSegments_Aligneds::AutoSegments_Aligneds ( const AutoSegments_Aligneds& autosegments )
: AutoSegmentHC()
, _flags (autosegments._flags)
, _segment(autosegments._segment)
{ }
// -------------------------------------------------------------------
// Class : "AutoSegments_Connecteds".
class AutoSegments_Connecteds : public AutoSegmentHC {
public:
// Sub-Class: Locator.
class Locator : public AutoSegmentHL {
public:
inline Locator ( AutoSegment* segment, Flags flags );
inline Locator ( const Locator &locator );
virtual AutoSegment* getElement () const;
virtual AutoSegmentHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
AutoSegmentStack _stack;
};
public:
// AutoSegments_Connecteds Methods.
AutoSegments_Connecteds ( AutoSegment*, Flags flags );
AutoSegments_Connecteds ( const AutoSegments_Connecteds& );
virtual AutoSegmentHC* getClone () const;
virtual AutoSegmentHL* getLocator () const;
virtual string _getString () const;
protected:
// AutoSegments_Connecteds Attributes.
Flags _flags;
AutoSegment* _segment;
};
inline AutoSegments_Connecteds::Locator::Locator ( const Locator &locator )
: AutoSegmentHL()
, _stack (locator._stack)
{ }
inline AutoSegments_Connecteds::AutoSegments_Connecteds ( AutoSegment* segment, Flags flags )
: AutoSegmentHC()
, _flags (flags)
, _segment(segment)
{ }
inline AutoSegments_Connecteds::AutoSegments_Connecteds ( const AutoSegments_Connecteds& autosegments )
: AutoSegmentHC()
, _flags (autosegments._flags)
, _segment(autosegments._segment)
{ }
// -------------------------------------------------------------------
// Class : "AutoSegments_Perpandiculars".
class AutoSegments_Perpandiculars : public AutoSegmentHC {
public:
// Sub-Class: Locator.
class Locator : public AutoSegmentHL {
public:
Locator ( AutoSegment* master, Flags flags );
inline Locator ( const Locator& );
virtual AutoSegment* getElement () const;
virtual AutoSegmentHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
Flags _flags;
AutoSegment* _master;
AutoSegmentStack _stack;
vector<AutoSegment*> _perpandiculars;
};
public:
// AutoSegments_Perpandiculars Methods.
inline AutoSegments_Perpandiculars ( AutoSegment*, Flags flags=Flags::NoFlags );
inline AutoSegments_Perpandiculars ( const AutoSegments_Perpandiculars& );
virtual AutoSegmentHC* getClone () const;
virtual AutoSegmentHL* getLocator () const;
virtual string _getString () const;
protected:
// AutoSegments_Perpandiculars Attributes.
Flags _flags;
AutoSegment* _master;
};
inline AutoSegments_Perpandiculars::Locator::Locator ( const Locator& locator )
: AutoSegmentHL()
, _flags (locator._flags)
, _master (locator._master)
, _stack (locator._stack)
, _perpandiculars()
{ }
inline AutoSegments_Perpandiculars::AutoSegments_Perpandiculars
( AutoSegment* master, Flags flags )
: AutoSegmentHC()
, _flags (flags)
, _master(master)
{ }
inline AutoSegments_Perpandiculars::AutoSegments_Perpandiculars
( const AutoSegments_Perpandiculars& autosegments )
: AutoSegmentHC()
, _flags (autosegments._flags)
, _master(autosegments._master)
{ }
// -------------------------------------------------------------------
// Class : "AutoSegments_AnchorOnGCell".
class AutoSegments_AnchorOnGCell : public AutoSegmentHC {
public:
// Sub-Class: Locator.
class Locator : public AutoSegmentHL {
public:
Locator ( GCell* fcell, Flags flags );
inline Locator ( const Locator& );
virtual ~Locator ();
virtual AutoSegment* getElement () const;
virtual AutoSegmentHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
Flags _flags;
vector<AutoContact*>::const_iterator _itContact;
vector<AutoContact*>::const_iterator _itEnd;
Hurricane::Locator<Hook*>* _hookLocator;
AutoSegment* _element;
};
public:
// AutoSegments_Perpandiculars Methods.
inline AutoSegments_AnchorOnGCell ( GCell* fcell, Flags flags );
inline AutoSegments_AnchorOnGCell ( const AutoSegments_AnchorOnGCell& );
virtual AutoSegmentHC* getClone () const;
virtual AutoSegmentHL* getLocator () const;
virtual string _getString () const;
public:
// AutoSegments_Perpandiculars Attributes.
GCell* _fcell;
Flags _flags;
};
inline AutoSegments_AnchorOnGCell::Locator::Locator ( const Locator &locator )
: AutoSegmentHL()
, _flags (locator._flags)
, _itContact (locator._itContact)
, _itEnd (locator._itEnd)
, _hookLocator (locator._hookLocator->getClone())
, _element (locator._element)
{ }
inline AutoSegments_AnchorOnGCell::AutoSegments_AnchorOnGCell ( GCell* fcell, Flags flags )
: AutoSegmentHC()
, _fcell(fcell)
, _flags(flags)
{ }
inline AutoSegments_AnchorOnGCell::AutoSegments_AnchorOnGCell
( const AutoSegments_AnchorOnGCell& autosegments )
: AutoSegmentHC()
, _fcell(autosegments._fcell)
, _flags(autosegments._flags)
{ }
// -------------------------------------------------------------------
// Class : "AutoSegments_CachedOnContact".
class AutoSegments_CachedOnContact : public AutoSegmentHC {
public:
// Sub-Class: Locator.
class Locator : public AutoSegmentHL {
public:
Locator ( AutoContact* sourceAnchor, Flags direction );
inline Locator ( const Locator& );
virtual ~Locator ();
virtual AutoSegment* getElement () const;
virtual AutoSegmentHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
LocatorHelper* _helper;
};
// Constructors.
public:
// AutoSegments_CachedOnContact Methods.
inline AutoSegments_CachedOnContact ( AutoContact* sourceContact
, Flags direction=Flags::Horizontal|Flags::Vertical );
inline AutoSegments_CachedOnContact ( const AutoSegments_CachedOnContact& );
virtual AutoSegmentHC* getClone () const;
virtual AutoSegmentHL* getLocator () const;
virtual string _getString () const;
protected:
// AutoSegments_CachedOnContact Attributes.
Flags _direction;
AutoContact* _sourceContact;
};
inline AutoSegments_CachedOnContact::Locator::Locator ( const Locator &locator )
: AutoSegmentHL()
, _helper(locator._helper)
{ }
inline AutoSegments_CachedOnContact::AutoSegments_CachedOnContact
( AutoContact* sourceContact, Flags direction )
: AutoSegmentHC()
, _direction (direction)
, _sourceContact(sourceContact)
{
if (_direction & Flags::Vertical) _direction |= Flags::WithPerpands;
}
inline AutoSegments_CachedOnContact::AutoSegments_CachedOnContact
( const AutoSegments_CachedOnContact& autosegments )
: AutoSegmentHC()
, _direction (autosegments._direction)
, _sourceContact(autosegments._sourceContact)
{ }
// -------------------------------------------------------------------
// Class : "AutoSegments_IsAccountable".
class AutoSegments_IsAccountable : public AutoSegmentHF {
public:
virtual AutoSegmentHF* getClone () const;
virtual bool accept ( AutoSegment* ) const;
virtual string _getString () const;
};
// -------------------------------------------------------------------
// Class : "AutoSegments_InDirection".
class AutoSegments_InDirection : public AutoSegmentHF {
public:
inline AutoSegments_InDirection ( Flags direction );
inline AutoSegments_InDirection ( const AutoSegments_InDirection& );
virtual AutoSegmentHF* getClone () const;
virtual bool accept ( AutoSegment* segment ) const;
virtual string _getString () const;
protected:
Flags _direction;
};
inline AutoSegments_InDirection::AutoSegments_InDirection ( Flags direction )
: AutoSegmentHF()
, _direction(direction)
{}
inline AutoSegments_InDirection::AutoSegments_InDirection ( const AutoSegments_InDirection& filter )
: AutoSegmentHF()
, _direction(filter._direction)
{}
} // End of Anabatic namespace.
# endif

View File

@ -1,91 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2013, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/AutoVertical.h" |
// +-----------------------------------------------------------------+
#pragma once
#include "hurricane/Vertical.h"
#include "anabatic/AutoSegment.h"
namespace Anabatic {
// -------------------------------------------------------------------
// Class : "AutoVertical".
class AutoVertical : public AutoSegment {
friend class AutoSegment;
public:
// Predicates.
virtual bool _canSlacken () const;
virtual bool canMoveULeft ( float reserve=0.0 ) const;
virtual bool canMoveURight ( float reserve=0.0 ) const;
// Accessors.
virtual Segment* base ();
virtual Segment* base () const;
virtual Vertical* getVertical ();
virtual DbU::Unit getSourceU () const;
virtual DbU::Unit getTargetU () const;
virtual DbU::Unit getDuSource () const;
virtual DbU::Unit getDuTarget () const;
virtual Interval getSpanU () const;
virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const;
virtual Interval getSourceConstraints ( Flags flags=0 ) const;
virtual Interval getTargetConstraints ( Flags flags=0 ) const;
virtual Flags getDirection () const;
virtual bool getGCells ( vector<GCell*>& ) const;
// Modifiers.
virtual void setDuSource ( DbU::Unit );
virtual void setDuTarget ( DbU::Unit );
virtual void _setAxis ( DbU::Unit );
virtual void updateOrient ();
virtual void updatePositions ();
virtual void updateNativeConstraints ();
virtual bool checkPositions () const;
virtual bool checkConstraints () const;
virtual Flags _makeDogleg ( GCell*, Flags flags );
virtual bool moveULeft ();
virtual bool moveURight ();
virtual bool _slacken ( Flags flags );
#if THIS_IS_DISABLED
virtual void desalignate ( AutoContact* );
#endif
// Inspector Management.
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
protected:
// Internal: Attributes.
Vertical* _vertical;
// Constructors.
protected:
AutoVertical ( Vertical* );
virtual ~AutoVertical ();
virtual void _postCreate ();
virtual void _preDestroy ();
private:
AutoVertical ( const AutoVertical& );
AutoVertical& operator= ( const AutoVertical& );
};
} // End of Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::AutoVertical);

View File

@ -1,114 +0,0 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/ChipTools.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <string>
#include "hurricane/DbU.h"
#include "hurricane/Torus.h"
namespace Hurricane {
class Cell;
class Instance;
}
namespace Anabatic {
using Hurricane::Record;
using Hurricane::DbU;
using Hurricane::Box;
using Hurricane::Torus;
using Hurricane::Cell;
using Hurricane::Instance;
class ChipTools {
public:
ChipTools ( Cell* );
inline bool isChip () const;
inline Cell* getCell () const;
inline Instance* getCore () const;
inline Cell* getReferencePad () const;
inline DbU::Unit getPadWidth () const;
inline DbU::Unit getPadHeight () const;
inline DbU::Unit getPadPowerWidth () const;
inline DbU::Unit getPadClockWidth () const;
inline const Box& getChipBb () const;
inline const Box& getLeftPadsBb () const;
inline const Box& getRightPadsBb () const;
inline const Box& getTopPadsBb () const;
inline const Box& getBottomPadsBb () const;
inline const Torus& getCorona () const;
inline const Box& getCoronaBb () const;
inline bool intersectVPads ( const Box& ) const;
inline bool intersectHPads ( const Box& ) const;
inline bool vPadsEnclosed ( const Box& ) const;
inline bool hPadsEnclosed ( const Box& ) const;
public:
Record* _getRecord () const;
std::string _getString () const;
inline std::string _getTypeName () const;
private:
Cell* _cell;
Instance* _core;
Cell* _referencePad;
bool _isChip;
Box _chipBb;
Box _leftPadsBb;
Box _rightPadsBb;
Box _topPadsBb;
Box _bottomPadsBb;
Torus _chipCorona;
DbU::Unit _padWidth;
DbU::Unit _padHeight;
DbU::Unit _padPowerWidth;
DbU::Unit _padClockWidth;
};
// Inline Functions.
inline bool ChipTools::isChip () const { return _isChip; }
inline Cell* ChipTools::getCell () const { return _cell; }
inline Instance* ChipTools::getCore () const { return _core; }
inline Cell* ChipTools::getReferencePad () const { return _referencePad; }
inline DbU::Unit ChipTools::getPadWidth () const { return _padWidth; }
inline DbU::Unit ChipTools::getPadHeight () const { return _padHeight; }
inline DbU::Unit ChipTools::getPadPowerWidth () const { return _padPowerWidth; }
inline DbU::Unit ChipTools::getPadClockWidth () const { return _padClockWidth; }
inline const Box& ChipTools::getChipBb () const { return _chipBb; }
inline const Box& ChipTools::getLeftPadsBb () const { return _leftPadsBb; };
inline const Box& ChipTools::getRightPadsBb () const { return _rightPadsBb; };
inline const Box& ChipTools::getTopPadsBb () const { return _topPadsBb; };
inline const Box& ChipTools::getBottomPadsBb () const { return _bottomPadsBb; };
inline const Torus& ChipTools::getCorona () const { return _chipCorona; };
inline const Box& ChipTools::getCoronaBb () const { return _chipCorona.getOuterBox(); }
inline std::string ChipTools::_getTypeName () const { return "ChipTools"; }
inline bool ChipTools::intersectVPads ( const Box& box ) const
{ return _leftPadsBb.intersect(box) or _rightPadsBb.intersect(box); }
inline bool ChipTools::intersectHPads ( const Box& box ) const
{ return _topPadsBb.intersect(box) or _bottomPadsBb.intersect(box); }
inline bool ChipTools::vPadsEnclosed ( const Box& box ) const
{ return _leftPadsBb.contains(box) or _rightPadsBb.contains(box); }
inline bool ChipTools::hPadsEnclosed ( const Box& box ) const
{ return _topPadsBb.contains(box) or _bottomPadsBb.contains(box); }
} // Anabatic namespace.
INSPECTOR_PR_SUPPORT(Anabatic::ChipTools);

View File

@ -1,212 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "Configuration.h<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) Sorbonne Université 2016-2022, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/Configuration.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <string>
#include <vector>
#include "hurricane/DbU.h"
namespace Hurricane {
class Layer;
class Cell;
class RoutingPad;
}
namespace CRL {
class CellGauge;
class RoutingGauge;
class RoutingLayerGauge;
}
#include "anabatic/Constants.h"
namespace Anabatic {
using std::string;
using Hurricane::Record;
using Hurricane::Name;
using Hurricane::Layer;
using Hurricane::DbU;
using Hurricane::RoutingPad;
using Hurricane::Cell;
using CRL::CellGauge;
using CRL::RoutingGauge;
using CRL::RoutingLayerGauge;
// -------------------------------------------------------------------
// Class : "Anabatic::Configuration".
class Configuration {
public:
static const size_t ndepth = (size_t)-1;
public:
// Constructor & Destructor.
Configuration ( const CellGauge* cg=NULL, const RoutingGauge* rg=NULL );
Configuration ( const Configuration& );
virtual ~Configuration ();
virtual Configuration* clone () const;
// Methods.
inline bool isGLayer ( const Layer* ) const;
bool isGMetal ( const Layer* ) const;
bool isGContact ( const Layer* ) const;
bool isTwoMetals () const;
bool isHybrid () const;
bool isHV () const;
bool isVH () const;
inline std::string getNetBuilderStyle () const;
inline StyleFlags getRoutingStyle () const;
const Layer* getGContactLayer () const;
const Layer* getGHorizontalLayer () const;
const Layer* getGVerticalLayer () const;
inline size_t getGVerticalDepth () const;
inline DbU::Unit getGVerticalPitch () const;
inline size_t getGHorizontalDepth () const;
inline DbU::Unit getGHorizontalPitch () const;
inline size_t getDVerticalDepth () const;
inline const Layer* getDVerticalLayer () const;
inline DbU::Unit getDVerticalWidth () const;
inline DbU::Unit getDPVerticalWidth () const;
inline DbU::Unit getDVerticalPitch () const;
inline DbU::Unit getDVerticalOffset () const;
inline size_t getDHorizontalDepth () const;
inline const Layer* getDHorizontalLayer () const;
inline DbU::Unit getDHorizontalWidth () const;
inline DbU::Unit getDPHorizontalWidth () const;
inline DbU::Unit getDHorizontalPitch () const;
inline DbU::Unit getDHorizontalOffset () const;
inline size_t getDContactDepth () const;
inline const Layer* getDContactLayer () const;
inline DbU::Unit getDContactWidth () const;
inline DbU::Unit getDContactPitch () const;
size_t getDepth () const;
size_t getAllowedDepth () const;
size_t getLayerDepth ( const Layer* ) const;
CellGauge* getCellGauge () const;
RoutingGauge* getRoutingGauge () const;
RoutingLayerGauge* getLayerGauge ( size_t depth ) const;
const Layer* getRoutingLayer ( size_t depth ) const;
Layer* getContactLayer ( size_t depth ) const;
DbU::Unit getSliceHeight () const;
DbU::Unit getSliceStep () const;
DbU::Unit getPitch ( size_t depth, Flags flags ) const;
DbU::Unit getOffset ( size_t depth ) const;
DbU::Unit getWireWidth ( size_t depth ) const;
DbU::Unit getPWireWidth ( size_t depth ) const;
DbU::Unit getExtensionCap ( size_t depth ) const;
Flags getDirection ( size_t depth ) const;
DbU::Unit getPitch ( const Layer*, Flags flags ) const;
DbU::Unit getOffset ( const Layer* ) const;
DbU::Unit getWireWidth ( const Layer* ) const;
DbU::Unit getPWireWidth ( const Layer* ) const;
DbU::Unit getExtensionCap ( const Layer* ) const;
Flags getDirection ( const Layer* ) const;
float getSaturateRatio () const;
size_t getSaturateRp () const;
inline std::string getDiodeName () const;
inline DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getAntennaDiodeMaxWL () const;
DbU::Unit getGlobalThreshold () const;
void setAllowedDepth ( size_t );
void setSaturateRatio ( float );
void setSaturateRp ( size_t );
void setGlobalThreshold ( DbU::Unit );
DbU::Unit getEdgeLength () const;
DbU::Unit getEdgeWidth () const;
float getEdgeCostH () const;
float getEdgeCostK () const;
float getEdgeHInc () const;
float getEdgeHScaling () const;
int getGlobalIterations () const;
DbU::Unit isOnRoutingGrid ( RoutingPad* ) const;
bool selectRpComponent ( RoutingPad* ) const;
inline void setRoutingStyle ( StyleFlags );
inline void resetRoutingStyle ( StyleFlags );
virtual void print ( Cell* ) const;
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
protected:
// Attributes.
const Layer* _gmetalh;
const Layer* _gmetalv;
const Layer* _gcontact;
size_t _gdepthv;
size_t _gdepthh;
size_t _ddepthv;
size_t _ddepthh;
size_t _ddepthc;
std::string _netBuilderStyle;
StyleFlags _routingStyle;
CellGauge* _cg;
RoutingGauge* _rg;
std::vector<DbU::Unit> _extensionCaps;
float _saturateRatio;
size_t _saturateRp;
DbU::Unit _globalThreshold;
size_t _allowedDepth;
DbU::Unit _edgeLength;
DbU::Unit _edgeWidth;
float _edgeCostH;
float _edgeCostK;
float _edgeHInc;
float _edgeHScaling;
int _globalIterations;
std::string _diodeName;
DbU::Unit _antennaGateMaxWL;
DbU::Unit _antennaDiodeMaxWL;
private:
Configuration& operator= ( const Configuration& ) = delete;
void _setTopRoutingLayer ( Name name );
};
inline std::string Configuration::getNetBuilderStyle () const { return _netBuilderStyle; }
inline StyleFlags Configuration::getRoutingStyle () const { return _routingStyle; }
inline bool Configuration::isGLayer ( const Layer* layer ) const { return isGMetal(layer) or isGContact(layer); }
inline size_t Configuration::getGHorizontalDepth () const { return _gdepthh; }
inline size_t Configuration::getGVerticalDepth () const { return _gdepthv; }
inline DbU::Unit Configuration::getGHorizontalPitch () const { return getPitch( getGHorizontalDepth(), Flags::NoFlags ); }
inline DbU::Unit Configuration::getGVerticalPitch () const { return getPitch( getGVerticalDepth (), Flags::NoFlags ); }
inline size_t Configuration::getDVerticalDepth () const { return _ddepthv; }
inline const Layer* Configuration::getDVerticalLayer () const { return getRoutingLayer( getDVerticalDepth() ); }
inline DbU::Unit Configuration::getDVerticalWidth () const { return getWireWidth ( getDVerticalDepth() ); }
inline DbU::Unit Configuration::getDPVerticalWidth () const { return getPWireWidth ( getDVerticalDepth() ); }
inline DbU::Unit Configuration::getDVerticalPitch () const { return getPitch ( getDVerticalDepth(), Flags::NoFlags ); }
inline DbU::Unit Configuration::getDVerticalOffset () const { return getOffset ( getDVerticalDepth() ); }
inline size_t Configuration::getDHorizontalDepth () const { return _ddepthh; }
inline const Layer* Configuration::getDHorizontalLayer () const { return getRoutingLayer( getDHorizontalDepth() ); }
inline DbU::Unit Configuration::getDHorizontalWidth () const { return getWireWidth ( getDHorizontalDepth() ); }
inline DbU::Unit Configuration::getDPHorizontalWidth () const { return getPWireWidth ( getDHorizontalDepth() ); }
inline DbU::Unit Configuration::getDHorizontalPitch () const { return getPitch ( getDHorizontalDepth(), Flags::NoFlags ); }
inline DbU::Unit Configuration::getDHorizontalOffset () const { return getOffset ( getDHorizontalDepth() ); }
inline size_t Configuration::getDContactDepth () const { return _ddepthc; }
inline const Layer* Configuration::getDContactLayer () const { return getContactLayer( getDContactDepth() ); }
inline DbU::Unit Configuration::getDContactWidth () const { return getWireWidth ( getDContactDepth() ); }
inline DbU::Unit Configuration::getDContactPitch () const { return getPitch ( getDContactDepth(), Flags::NoFlags ); }
inline std::string Configuration::getDiodeName () const { return _diodeName; }
inline DbU::Unit Configuration::getAntennaGateMaxWL () const { return _antennaGateMaxWL; }
inline DbU::Unit Configuration::getAntennaDiodeMaxWL () const { return _antennaDiodeMaxWL; }
inline void Configuration::setRoutingStyle ( StyleFlags flags ) { _routingStyle = flags; }
inline void Configuration::resetRoutingStyle ( StyleFlags flags ) { _routingStyle &= ~flags; }
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::Configuration);

View File

@ -1,193 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "Constants.h<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/Constants.h" |
// +-----------------------------------------------------------------+
#pragma once
#include "hurricane/Flags.h"
namespace Anabatic {
// -------------------------------------------------------------------
// Class : "Anabatic::Flags".
class Flags : public Hurricane::BaseFlags {
public:
static const BaseFlags NoFlags ; // = 0;
// Flags used for both objects states & functions arguments.
static const BaseFlags Horizontal ; // = (1 << 0);
static const BaseFlags Vertical ; // = (1 << 1);
static const BaseFlags Source ; // = (1 << 2);
static const BaseFlags Target ; // = (1 << 3);
static const BaseFlags Invalidated ; // = (1 << 4);
// Flags for GCell objects states only.
static const BaseFlags DeviceGCell ; // = (1 << 5);
static const BaseFlags HChannelGCell ; // = (1 << 6);
static const BaseFlags VChannelGCell ; // = (1 << 7);
static const BaseFlags StrutGCell ; // = (1 << 8);
static const BaseFlags MatrixGCell ; // = (1 << 9);
static const BaseFlags IoPadGCell ; // = (1 << 10);
static const BaseFlags Saturated ; // = (1 << 11);
static const BaseFlags StdCellRow ; // = (1 << 12);
static const BaseFlags ChannelRow ; // = (1 << 13);
static const BaseFlags HRailGCell ; // = (1 << 14);
static const BaseFlags VRailGCell ; // = (1 << 15);
static const BaseFlags GoStraight ; // = (1 << 16);
// Flags for Edge objects states only.
static const BaseFlags NullCapacity ; // = (1 << 5);
static const BaseFlags InfiniteCapacity ; // = (1 << 6);
// Flags for Anabatic objects states only.
static const BaseFlags DemoMode ; // = (1 << 5);
static const BaseFlags WarnOnGCellOverload ; // = (1 << 6);
static const BaseFlags DestroyGCell ; // = (1 << 7);
static const BaseFlags DestroyBaseContact ; // = (1 << 8);
static const BaseFlags DestroyBaseSegment ; // = (1 << 9);
static const BaseFlags DisableCanonize ; // = (1 << 10);
// Flags for NetDatas objects states only.
static const BaseFlags GlobalFixed ; // = (1 << 5);
static const BaseFlags GlobalEstimated ; // = (1 << 6);
static const BaseFlags GlobalRouted ; // = (1 << 7);
static const BaseFlags DetailRouted ; // = (1 << 8);
static const BaseFlags ExcludeRoute ; // = (1 << 9);
// Masks.
static const BaseFlags WestSide ; // = Horizontal|Target;
static const BaseFlags EastSide ; // = Horizontal|Source;
static const BaseFlags SouthSide ; // = Vertical |Target;
static const BaseFlags NorthSide ; // = Vertical |Source;
static const BaseFlags AllSides ; // = WestSide|EastSide|SouthSide|NorthSide ;
static const BaseFlags EndsMask ; // = Source|Target;
static const BaseFlags DirectionMask ; // = Horizontal|Vertical;
static const BaseFlags DestroyMask ; // = DestroyGCell|DestroyBaseContact|DestroyBaseSegment;
static const BaseFlags GCellTypeMask ; // = DeviceGCell|HChannelGCell|VChannelGCell|StrutGCell|MatrixGCell|IoPadGCell|HRailGCell|VRailGCell;
static const BaseFlags RowGCellMask ; // = StdCellRow|ChannelRow;
static const BaseFlags AnalogGCellMask ; // = DeviceGCell|HChannelGCell|VChannelGCell|StrutGCell|HRailGCell|VRailGCell;
static const BaseFlags EdgeCapacityMask ; // = Horizontal|Vertical|NullCapacity|InfiniteCapacity ;
// Flags for functions arguments only.
static const BaseFlags Create ; // = (1 << 5);
static const BaseFlags WithPerpands ;
static const BaseFlags WithDoglegs ;
static const BaseFlags WithSelf ;
static const BaseFlags AboveLayer ;
static const BaseFlags BelowLayer ;
static const BaseFlags OpenSession ;
static const BaseFlags Realignate ;
static const BaseFlags NativeConstraints ;
static const BaseFlags ForceMove ;
static const BaseFlags WarnOnError ;
static const BaseFlags Topology ;
static const BaseFlags GlobalSegment ;
static const BaseFlags AllowTerminal ;
static const BaseFlags AllowLocal ;
static const BaseFlags IgnoreContacts ;
static const BaseFlags Propagate ;
static const BaseFlags Superior ;
static const BaseFlags DoglegOnLeft ;
static const BaseFlags DoglegOnRight ;
static const BaseFlags WithNeighbors ;
static const BaseFlags NoCheckLayer ;
static const BaseFlags HalfSlacken ;
static const BaseFlags NoGCellShrink ;
static const BaseFlags CParanoid ;
static const BaseFlags CheckLowDensity ;
static const BaseFlags CheckLowUpDensity ;
static const BaseFlags NoUpdate ;
static const BaseFlags NorthPath ;
static const BaseFlags UseNonPref ;
static const BaseFlags Force ;
static const BaseFlags LayerCapOnly ;
static const BaseFlags NoMinLength ;
static const BaseFlags NoSegExt ;
static const BaseFlags NullLength ;
static const BaseFlags OnVSmall ;
public:
inline Flags ( uint64_t flags = NoFlags );
inline Flags ( const Hurricane::BaseFlags& );
virtual ~Flags ();
virtual std::string asString ( uint32_t mode ) const;
virtual std::string _getTypeName () const;
virtual std::string _getString () const;
};
Flags::Flags ( uint64_t flags ) : BaseFlags(flags) { }
Flags::Flags ( const Hurricane::BaseFlags& flags ) : BaseFlags(flags) { }
// -------------------------------------------------------------------
// Class : "Anabatic::StyleFlags".
class StyleFlags : public Hurricane::BaseFlags {
public:
static const BaseFlags NoStyle; // = 0;
static const BaseFlags HV ; // = (1 << 0);
static const BaseFlags VH ; // = (1 << 1);
static const BaseFlags OTH ; // = (1 << 2);
static const BaseFlags Channel; // = (1 << 3);
static const BaseFlags Hybrid ; // = (1 << 4);
public:
inline StyleFlags ( std::string );
inline StyleFlags ( uint64_t flags = NoStyle );
inline StyleFlags ( const Hurricane::BaseFlags& );
virtual ~StyleFlags ();
static StyleFlags toFlag ( std::string );
StyleFlags from ( std::string );
virtual std::string asString () const;
virtual std::string _getTypeName () const;
virtual std::string _getString () const;
};
StyleFlags::StyleFlags ( std::string textFlags ) : BaseFlags(NoStyle) { from(textFlags); }
StyleFlags::StyleFlags ( uint64_t flags ) : BaseFlags(flags) { }
StyleFlags::StyleFlags ( const Hurricane::BaseFlags& flags ) : BaseFlags(flags) { }
// -------------------------------------------------------------------
// Misc. enums.
enum FlagsMode { FlagsFunction = 1
};
enum EngineState { EngineCreation = 1
, EngineGlobalLoaded = 2
, EngineActive = 3
, EngineDriving = 4
, EnginePreDestroying = 5
, EngineGutted = 6
};
enum EngineAlgorithm { EngineLoadGrByNet = (1 << 0)
, EngineLoadGrByGCell = (1 << 1)
, EngineLayerAssignByLength = (1 << 2)
, EngineLayerAssignByTrunk = (1 << 3)
, EngineLayerAssignNoGlobalM2V = (1 << 4)
, EngineNoNetLayerAssign = (1 << 5)
};
inline Flags perpandicularTo ( Flags direction )
{
if (direction & Flags::Horizontal) return Flags::Vertical;
if (direction & Flags::Vertical ) return Flags::Horizontal;
return Flags::NoFlags;
}
} // Anabatic namespace.
INSPECTOR_PR_SUPPORT(Anabatic::Flags);

View File

@ -1,606 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "Dijkstra.h<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/Dijkstra.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <set>
#include <iomanip>
#include "hurricane/Observer.h"
namespace Hurricane {
class Net;
class RoutingPad;
}
#include "anabatic/GCell.h"
namespace Anabatic {
using std::set;
using std::multiset;
using Hurricane::Observer;
using Hurricane::Net;
using Hurricane::RoutingPad;
using Hurricane::Plug;
class AnabaticEngine;
// -------------------------------------------------------------------
// Class : "Anabatic::IntervalC".
class IntervalC
{
public:
enum iFlag { None = 0
, iFHorizontal = (1<<0)
, iFVertical = (1<<1)
, iSet = (1<<2)
};
public:
IntervalC();
IntervalC(const IntervalC&);
IntervalC(IntervalC&);
IntervalC( DbU::Unit, DbU::Unit, DbU::Unit );
~IntervalC();
void set ( DbU::Unit, DbU::Unit, DbU::Unit );
void setRange ( DbU::Unit, DbU::Unit );
void extendMin ( DbU::Unit );
void extendMax ( DbU::Unit );
void print () const;
inline bool isH () const;
inline bool isV () const;
inline void setAsH ();
inline void setAsV ();
inline DbU::Unit getMin () const;
inline DbU::Unit getMax () const;
inline DbU::Unit getCenter () const;
DbU::Unit getAxis () const;
inline void setAxis ( DbU::Unit );
inline void setiSet ();
inline bool isiSet () const;
void reset ();
Flags getFlags () const;
void setFlags (Flags);
private:
Flags _flags;
DbU::Unit _min;
DbU::Unit _max;
DbU::Unit _axis;
};
inline void IntervalC::setAsH () { _flags = ((_flags & ~(0x3)) | iFHorizontal); }
inline void IntervalC::setAsV () { _flags = ((_flags & ~(0x3)) | iFVertical ); }
inline void IntervalC::setAxis ( DbU::Unit axis ) { _axis = axis; }
inline DbU::Unit IntervalC::getAxis () const { return _axis; }
inline DbU::Unit IntervalC::getCenter() const { return getMin()+getMax(); }
inline DbU::Unit IntervalC::getMin () const { return _min; }
inline DbU::Unit IntervalC::getMax () const { return _max; }
inline void IntervalC::setiSet () { _flags |= iSet; }
inline bool IntervalC::isiSet () const { return _flags & iSet; }
inline bool IntervalC::isH () const { return _flags & iFHorizontal; }
inline bool IntervalC::isV () const { return _flags & iFVertical ; }
inline void IntervalC::setFlags ( Flags flags ) { _flags = flags; }
inline Flags IntervalC::getFlags () const { return _flags; }
// -------------------------------------------------------------------
// Class : "Anabatic::GRAData".
class GRAData
{
private:
GRAData();
~GRAData();
public:
static GRAData* create();
//////////////////////////////////////// GRDATA
inline bool isiSet () const;
inline IntervalC getInterv () const;
inline IntervalC getIntervFrom () const;
inline DbU::Unit getIAxis () const;
inline DbU::Unit getIMax () const;
inline DbU::Unit getIMin () const;
inline DbU::Unit getPIAxis () const;
inline DbU::Unit getPIMax () const;
inline DbU::Unit getPIMin () const;
inline IntervalC getIntervFrom2 () const;
inline DbU::Unit getPIMax2 () const;
inline DbU::Unit getPIMin2 () const;
inline DbU::Unit getPIAxis2 () const;
inline void setInterv ( DbU::Unit, DbU::Unit, DbU::Unit );
inline void setIntervfrom ( DbU::Unit, DbU::Unit, DbU::Unit );
inline void setIntervfrom2 ( DbU::Unit, DbU::Unit, DbU::Unit );
void resetIntervals ();
void clearFrom2 ();
inline Edge* getFrom2 () const;
inline void setFrom2 ( Edge* );
inline void printInterv () const;
inline void printIntervfrom () const;
private:
IntervalC _intervfrom;
IntervalC _interv;
Edge* _from2;
IntervalC _intervfrom2;
};
inline bool GRAData::isiSet () const { return _interv.isiSet() ; }
inline IntervalC GRAData::getInterv () const { return _interv; }
inline IntervalC GRAData::getIntervFrom() const { return _intervfrom; }
inline DbU::Unit GRAData::getIAxis () const { return _interv.getAxis() ; }
inline DbU::Unit GRAData::getIMax () const { return _interv.getMax() ; }
inline DbU::Unit GRAData::getIMin () const { return _interv.getMin() ; }
inline DbU::Unit GRAData::getPIAxis () const { return _intervfrom.getAxis(); }
inline DbU::Unit GRAData::getPIMax () const { return _intervfrom.getMax() ; }
inline DbU::Unit GRAData::getPIMin () const { return _intervfrom.getMin() ; }
inline DbU::Unit GRAData::getPIMax2 () const { return _intervfrom2.getMax() ; }
inline DbU::Unit GRAData::getPIMin2 () const { return _intervfrom2.getMin() ; }
inline DbU::Unit GRAData::getPIAxis2 () const { return _intervfrom2.getAxis(); }
inline IntervalC GRAData::getIntervFrom2 () const { return _intervfrom2; }
inline void GRAData::setInterv ( DbU::Unit min, DbU::Unit max, DbU::Unit axis ) { _interv.set(min, max, axis); }
inline void GRAData::setIntervfrom ( DbU::Unit min, DbU::Unit max, DbU::Unit axis ) { _intervfrom.set(min, max, axis); }
inline void GRAData::setIntervfrom2( DbU::Unit min, DbU::Unit max, DbU::Unit axis ) { _intervfrom2.set(min, max, axis); }
inline Edge* GRAData::getFrom2 () const { return _from2; }
inline void GRAData::setFrom2 ( Edge* from ) { _from2 = from; }
inline void GRAData::printInterv () const { _interv.print() ; }
inline void GRAData::printIntervfrom () const { _intervfrom.print(); }
// -------------------------------------------------------------------
// Class : "Anabatic::Vertex".
class Vertex {
public:
static inline std::string getValueString ( DbU::Unit );
public:
class CompareById {
public:
inline bool operator() ( const Vertex* lhs, const Vertex* rhs ) const;
};
public:
enum FlagR { NoRestriction = 0
, NRestricted = (1<<0)
, SRestricted = (1<<1)
, ERestricted = (1<<2)
, WRestricted = (1<<3)
, AxisTarget = (1<<4)
, From2Mode = (1<<5)
, UseFromFrom2 = (1<<6)
, iHorizontal = (1<<7)
, iVertical = (1<<8)
, iSet = (1<<9)
, Driver = (1<<10)
};
public:
static DbU::Unit unreached;
static DbU::Unit unreachable;
public:
static void notify ( Vertex*, unsigned flags );
static inline Vertex* lookup ( GCell* );
public:
inline Vertex ( GCell* );
//inline Vertex ( size_t id );
inline ~Vertex ();
inline bool isDriver () const;
inline bool isAnalog () const;
inline bool hasDoneAllRps () const;
inline Contact* hasGContact ( Net* ) const;
inline unsigned int getId () const;
inline GCell* getGCell () const;
inline Box getBoundingBox () const;
inline Edges getEdges ( Flags sides=Flags::AllSides ) const;
inline AnabaticEngine* getAnabatic () const;
inline Contact* getGContact ( Net* );
bool hasValidStamp () const;
inline Point getCenter () const;
inline DbU::Unit getDistance () const;
inline int getStamp () const;
inline int getBranchId () const;
inline int getConnexId () const;
inline int getDegree () const;
inline int getRpCount () const;
Edge* getFrom () const;
inline Vertex* getPredecessor () const;
inline Vertex* getNeighbor ( Edge* ) const;
inline void setDriver ( bool state );
inline void setDistance ( DbU::Unit );
inline void setStamp ( int );
inline void setConnexId ( int );
inline void setBranchId ( int );
inline void setDegree ( int );
inline void incDegree ( int delta=1 );
inline void setRpCount ( int );
inline void incRpCount ( int delta=1 );
inline void setFrom ( Edge* );
inline void add ( RoutingPad* );
inline void clearRps ();
inline Contact* breakGoThrough ( Net* );
// Analog related methods.
inline bool isNorth ( const Vertex* ) const;
inline bool isSouth ( const Vertex* ) const;
inline bool isEast ( const Vertex* ) const;
inline bool isWest ( const Vertex* ) const;
inline bool isNRestricted () const;
inline bool isSRestricted () const;
inline bool isERestricted () const;
inline bool isWRestricted () const;
inline bool hasRestrictions () const;
void setRestricted ();
void clearRestriction ();
inline void setNRestricted ();
inline void setSRestricted ();
inline void setERestricted ();
inline void setWRestricted ();
bool hasRP ( Net* ) const;
bool hasVRP ( Net* ) const;
bool hasHRP ( Net* ) const;
static bool isRestricted ( const Vertex* v1, const Vertex* v2, const Edge* e, DbU::Unit hpitch = 0, DbU::Unit vpitch = 0, Net* net = NULL);
bool areSameSide ( const Vertex*, const Vertex* ) const;
inline bool isFromFrom2 () const;
inline bool isFrom2Mode () const;
inline bool isAxisTarget () const;
inline bool isiHorizontal () const;
inline bool isiVertical () const;
inline void setFlags ( uint32_t );
inline void unsetFlags ( uint32_t );
bool isH () const;
bool isV () const;
inline void createAData ();
Point getStartPathPoint ( const Vertex* next ) const;
Point getNextPathPoint ( Point, const Vertex* ) const;
void setIntervals ( Vertex* );
inline bool hasAData () const;
bool isiSet () const;
DbU::Unit getIAxis () const;
DbU::Unit getIMax () const;
DbU::Unit getIMin () const;
DbU::Unit getPIAxis () const;
DbU::Unit getPIMax () const;
DbU::Unit getPIMin () const;
void setInterv ( DbU::Unit, DbU::Unit, DbU::Unit );
void setIntervfrom ( DbU::Unit, DbU::Unit, DbU::Unit );
void setIntervfrom2 ( DbU::Unit, DbU::Unit, DbU::Unit );
void resetIntervals ();
void clearFrom2 ();
Edge* getFrom2 () const;
void setFrom2 ( Edge* );
DbU::Unit getPIMax2 () const;
DbU::Unit getPIMin2 () const;
DbU::Unit getPIAxis2 () const;
IntervalC getIntervFrom2 () const;
IntervalC getIntervFrom ( uint32_t criteria=0 ) const;
IntervalC getInterv () const;
void printInterv () const;
void printIntervfrom () const;
GCell* getGPrev ( uint32_t criteria=0 ) const;
// Inspector support.
string _getString () const;
private:
Vertex ( const Vertex& );
Vertex& operator= ( const Vertex& );
private:
size_t _id;
GCell* _gcell;
Observer<Vertex> _observer;
int _connexId;
int _branchId;
int _degree : 8;
int _rpCount : 8;
int _stamp;
DbU::Unit _distance;
Edge* _from;
uint32_t _flags;
GRAData* _adata;
};
inline Vertex::Vertex ( GCell* gcell )
: _id (gcell->getId())
, _gcell (gcell)
, _observer(this)
, _connexId(-1)
, _branchId( 0)
, _degree ( 0)
, _rpCount ( 0)
, _stamp (-1)
, _distance(unreached)
, _from (NULL)
, _flags (NoRestriction)
, _adata (NULL)
{
gcell->setObserver( GCell::Observable::Vertex, &_observer );
}
inline Vertex* Vertex::lookup ( GCell* gcell ) { return gcell->getObserver<Vertex>(GCell::Observable::Vertex); }
inline Vertex::~Vertex () { _gcell->setObserver( GCell::Observable::Vertex, NULL ); }
inline bool Vertex::isDriver () const { return _flags & Driver; }
inline bool Vertex::isAnalog () const { return _gcell->isAnalog(); }
inline Box Vertex::getBoundingBox () const { return _gcell->getBoundingBox(); }
inline Edges Vertex::getEdges ( Flags sides ) const { return _gcell->getEdges(sides); }
inline Contact* Vertex::hasGContact ( Net* net ) const { return _gcell->hasGContact(net); }
inline unsigned int Vertex::getId () const { return _id; }
inline GCell* Vertex::getGCell () const { return _gcell; }
inline AnabaticEngine* Vertex::getAnabatic () const { return _gcell->getAnabatic(); }
inline Contact* Vertex::getGContact ( Net* net ) { return _gcell->getGContact(net); }
inline Point Vertex::getCenter () const { return _gcell->getBoundingBox().getCenter(); }
inline DbU::Unit Vertex::getDistance () const { return hasValidStamp() ? _distance : unreached; }
inline int Vertex::getStamp () const { return _stamp; }
inline int Vertex::getConnexId () const { return hasValidStamp() ? _connexId : -1; }
inline int Vertex::getBranchId () const { return hasValidStamp() ? _branchId : 0; }
inline int Vertex::getDegree () const { return hasValidStamp() ? _degree : 0; }
inline int Vertex::getRpCount () const { return hasValidStamp() ? _rpCount : 0; }
//inline Edge* Vertex::getFrom () const { return _from; }
inline void Vertex::setDistance ( DbU::Unit distance ) { _distance=distance; }
inline void Vertex::setFrom ( Edge* from ) { _from=from; }
inline void Vertex::setStamp ( int stamp ) { _stamp=stamp; }
inline void Vertex::setConnexId ( int id ) { _connexId=id; }
inline void Vertex::setBranchId ( int id ) { _branchId=id; }
inline void Vertex::setDegree ( int degree ) { _degree=degree; }
inline void Vertex::incDegree ( int delta ) { _degree+=delta; }
inline void Vertex::setRpCount ( int count ) { _rpCount=count; }
inline void Vertex::incRpCount ( int delta ) { _rpCount+=delta; }
inline Contact* Vertex::breakGoThrough ( Net* net ) { return _gcell->breakGoThrough(net); }
inline Vertex* Vertex::getPredecessor () const
{ return (hasValidStamp() and _from) ? _from->getOpposite(_gcell)->getObserver<Vertex>(GCell::Observable::Vertex) : NULL; }
inline Vertex* Vertex::getNeighbor ( Edge* edge ) const
{
GCell* gcell = edge->getOpposite( getGCell() );
return (gcell) ? gcell->getObserver<Vertex>(GCell::Observable::Vertex) : NULL;
}
inline void Vertex::setDriver ( bool state )
{
if (state) _flags |= Driver;
else _flags &= ~Driver;
}
inline bool Vertex::CompareById::operator() ( const Vertex* lhs, const Vertex* rhs ) const
{ return lhs->getId() < rhs->getId(); }
typedef set<Vertex*,Vertex::CompareById> VertexSet;
inline bool Vertex::isNorth ( const Vertex* v ) const { return _gcell->isNorth(v->getGCell()); }
inline bool Vertex::isSouth ( const Vertex* v ) const { return _gcell->isSouth(v->getGCell()); }
inline bool Vertex::isEast ( const Vertex* v ) const { return _gcell->isEast (v->getGCell()); }
inline bool Vertex::isWest ( const Vertex* v ) const { return _gcell->isWest (v->getGCell()); }
inline bool Vertex::isNRestricted () const { return (_flags & NRestricted); }
inline bool Vertex::isSRestricted () const { return (_flags & SRestricted); }
inline bool Vertex::isERestricted () const { return (_flags & ERestricted); }
inline bool Vertex::isWRestricted () const { return (_flags & WRestricted); }
inline bool Vertex::hasRestrictions () const { return ( isNRestricted()||isSRestricted()||isERestricted()||isWRestricted()) ; }
inline bool Vertex::hasAData () const { return (_adata !=NULL)? true : false; }
//inline void Vertex::setRestricted () { _flags |= 0xF; }
//inline void Vertex::clearRestriction () { _flags &= ~(0xF); }
inline void Vertex::setNRestricted () { _flags |= NRestricted; }
inline void Vertex::setSRestricted () { _flags |= SRestricted; }
inline void Vertex::setERestricted () { _flags |= ERestricted; }
inline void Vertex::setWRestricted () { _flags |= WRestricted; }
inline bool Vertex::isFromFrom2 () const { return (_flags & Vertex::UseFromFrom2); }
inline bool Vertex::isFrom2Mode () const { return (_flags & Vertex::From2Mode ); }
inline bool Vertex::isAxisTarget () const { return (_flags & Vertex::AxisTarget ); }
inline bool Vertex::isiHorizontal() const { return (_flags & Vertex::iHorizontal ); }
inline bool Vertex::isiVertical () const { return (_flags & Vertex::iVertical ); }
inline void Vertex::setFlags ( uint32_t mask ) { _flags |= mask ; }
inline void Vertex::unsetFlags ( uint32_t mask ) { _flags &= ~mask; }
inline std::string Vertex::getValueString ( DbU::Unit distance )
{
if (distance == Vertex::unreachable) return "unreachable";
if (distance == Vertex::unreached ) return "unreached";
return DbU::getValueString( distance );
}
// -------------------------------------------------------------------
// Class : "Anabatic::PriorityQueue".
class PriorityQueue {
public:
inline PriorityQueue ();
inline ~PriorityQueue ();
inline bool empty () const;
inline size_t size () const;
inline void push ( Vertex* );
inline void erase ( Vertex* );
inline Vertex* top ();
inline void pop ();
inline void clear ();
inline void dump () const;
inline void setAttractor ( const Point& );
inline const Point& getAttractor () const;
inline bool hasAttractor () const;
private:
class CompareByDistance {
public:
inline CompareByDistance ();
bool operator() ( const Vertex* lhs, const Vertex* rhs ) const;
static inline void setQueue ( PriorityQueue* );
private:
static PriorityQueue* _pqueue;
};
private:
bool _hasAttractor;
Point _attractor;
multiset<Vertex*,CompareByDistance> _queue;
};
inline PriorityQueue::CompareByDistance::CompareByDistance () { }
inline void PriorityQueue::CompareByDistance::setQueue ( PriorityQueue* pqueue ) { _pqueue = pqueue; }
inline PriorityQueue::PriorityQueue () : _hasAttractor(false), _attractor(), _queue() { PriorityQueue::CompareByDistance::setQueue(this); }
inline PriorityQueue::~PriorityQueue () { }
inline bool PriorityQueue::empty () const { return _queue.empty(); }
inline size_t PriorityQueue::size () const { return _queue.size(); }
inline void PriorityQueue::push ( Vertex* v ) { _queue.insert(v); }
inline Vertex* PriorityQueue::top () { return _queue.empty() ? NULL : *_queue.begin(); }
inline void PriorityQueue::clear () { _queue.clear(); _hasAttractor=false; }
inline void PriorityQueue::setAttractor ( const Point& p ) { _attractor=p; _hasAttractor=true; }
inline bool PriorityQueue::hasAttractor () const { return _hasAttractor; }
inline const Point& PriorityQueue::getAttractor () const { return _attractor; }
inline void PriorityQueue::pop ()
{
cdebug_log(112,0) << "Pop: (size:" << _queue.size() << ") " << *_queue.begin() << std::endl;
_queue.erase(_queue.begin());
}
inline void PriorityQueue::erase ( Vertex* v )
{
for ( auto ivertex = _queue.begin() ; ivertex != _queue.end() ; ++ivertex ) {
if (*ivertex == v) { _queue.erase( ivertex ); break; }
}
}
inline void PriorityQueue::dump () const
{
if (cdebug.enabled(112)) {
cdebug_log(112,1) << "PriorityQueue::dump() size:" << size() << std::endl;
size_t order = 0;
for ( Vertex* v : _queue )
cdebug_log(112,0) << "[" << tsetw(3) << order++ << "] " << v << std::endl;
cdebug_tabw(112,-1);
}
}
// -------------------------------------------------------------------
// Class : "Anabatic::Dijkstra".
class Dijkstra {
public:
// Mode sub-classe.
class Mode : public Hurricane::BaseFlags {
public:
enum Flag { NoMode = 0
, Standart = (1<<0)
, Monotonic = (1<<1)
, AxisTarget = (1<<2)
};
public:
inline Mode ( Flag flags=NoMode );
inline Mode ( BaseFlags );
virtual ~Mode ();
virtual std::string _getTypeName () const;
virtual std::string _getString () const;
};
public:
typedef std::function<DbU::Unit(const Vertex*,const Vertex*,const Edge*)> distance_t;
public:
Dijkstra ( AnabaticEngine* );
~Dijkstra ();
public:
inline bool isBipoint () const;
inline bool isSourceVertex ( Vertex* ) const;
inline Net* getNet () const;
inline bool isTargetVertex ( Vertex* ) const;
DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getSearchAreaHalo () const;
template<typename DistanceT>
inline DistanceT* setDistance ( DistanceT );
inline void setSearchAreaHalo ( DbU::Unit );
void load ( Net* net );
void loadFixedGlobal ( Net* net );
void run ( Mode mode=Mode::Standart );
inline const VertexSet& getSources () const;
private:
Dijkstra ( const Dijkstra& );
Dijkstra& operator= ( const Dijkstra& );
static DbU::Unit _distance ( const Vertex*, const Vertex*, const Edge* );
Point _getPonderedPoint () const;
void _cleanup ();
bool _propagate ( Flags enabledSides );
void _traceback ( Vertex* );
void _materialize ();
void _selectFirstSource ();
void _toSources ( Vertex*, int connexId );
void _getConnecteds ( Vertex*, VertexSet& );
void _checkEdges () const;
void _createSelfSymSeg ( Segment* );
inline void setAxisTarget ();
inline bool needAxisTarget () const;
inline void setFlags ( Flags );
inline void unsetFlags ( Flags );
void setAxisTargets ();
void unsetAxisTargets ();
bool _attachSymContactsHook ( RoutingPad* );
void _limitSymSearchArea ( RoutingPad* rp );
void _setSourcesGRAData ( Vertex*, RoutingPad*);
bool _checkFrom2 ( Edge*, Vertex* );
bool _isDistance2Shorter ( DbU::Unit&, Vertex*, Vertex*, Edge* );
void _pushEqualDistance ( DbU::Unit, bool, Vertex*, Vertex*, Edge* );
void _updateGRAData ( Vertex*, bool, Vertex* );
void _initiateUpdateIntervals ( Vertex* );
bool _updateIntervals ( bool&, Vertex*, bool&, int&, Edge* );
void _updateRealOccupancy ( Vertex* );
private:
AnabaticEngine* _anabatic;
vector<Vertex*> _vertexes;
distance_t _distanceCb;
Mode _mode;
Net* _net;
int _stamp;
VertexSet _sources;
VertexSet _targets;
Box _searchArea;
DbU::Unit _searchAreaHalo;
int _connectedsId;
PriorityQueue _queue;
Flags _flags;
};
inline Dijkstra::Mode::Mode ( Dijkstra::Mode::Flag flags ) : BaseFlags(flags) { }
inline Dijkstra::Mode::Mode ( BaseFlags base ) : BaseFlags(base) { }
inline bool Dijkstra::isBipoint () const { return _net and (_targets.size()+_sources.size() == 2); }
inline bool Dijkstra::isSourceVertex ( Vertex* v ) const { return (_sources.find(v) != _sources.end()); }
inline bool Dijkstra::isTargetVertex ( Vertex* v ) const { return (_targets.find(v) != _targets.end()); }
inline Net* Dijkstra::getNet () const { return _net; }
inline DbU::Unit Dijkstra::getSearchAreaHalo () const { return _searchAreaHalo; }
inline void Dijkstra::setSearchAreaHalo ( DbU::Unit halo ) { _searchAreaHalo = halo; }
template<typename DistanceT>
inline DistanceT* Dijkstra::setDistance ( DistanceT cb ) { _distanceCb = cb; return _distanceCb.target<DistanceT>(); }
inline void Dijkstra::setFlags ( Flags mask ) { _flags |= mask; }
inline bool Dijkstra::needAxisTarget () const { return (_flags & Mode::AxisTarget); }
inline void Dijkstra::unsetFlags ( Flags mask ) { _flags &= ~mask; }
inline const VertexSet& Dijkstra::getSources () const { return _sources; }
} // Anabatic namespace.
GETSTRING_POINTER_SUPPORT(Anabatic::Vertex);
IOSTREAM_POINTER_SUPPORT(Anabatic::Vertex);
INSPECTOR_PR_SUPPORT(Anabatic::Dijkstra::Mode);

View File

@ -1,168 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "Edge.h<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/Edge.h" |
// +-----------------------------------------------------------------+
#pragma once
#include <string>
#include "hurricane/Name.h"
#include "hurricane/Interval.h"
#include "hurricane/Box.h"
#include "hurricane/ExtensionGo.h"
namespace Hurricane {
class Segment;
}
#include "anabatic/Constants.h"
#include "anabatic/EdgeCapacity.h"
#include "anabatic/Edges.h"
namespace Anabatic {
using std::string;
using Hurricane::Name;
using Hurricane::Record;
using Hurricane::DbU;
using Hurricane::Interval;
using Hurricane::Box;
using Hurricane::Segment;
using Hurricane::Net;
using Hurricane::Cell;
using Hurricane::ExtensionGo;
class GCell;
class AnabaticEngine;
class Edge : public ExtensionGo {
public:
typedef ExtensionGo Super;
public:
static DbU::Unit unity;
public:
static Edge* create ( GCell* source, GCell* target, Flags flags=Flags::NoFlags );
virtual void destroy ();
public:
inline bool isVertical () const;
inline bool isHorizontal () const;
inline bool hasNet ( const Net* ) const;
inline unsigned int getCapacity () const;
inline unsigned int getRawCapacity () const;
inline unsigned int getReservedCapacity () const;
inline unsigned int getCapacity ( size_t depth ) const;
inline unsigned int getRealOccupancy () const;
inline float getEstimateOccupancy () const;
inline float getHistoricCost () const;
DbU::Unit getDistance () const;
inline GCell* getSource () const;
inline GCell* getTarget () const;
GCell* getOpposite ( const GCell* ) const;
AnabaticEngine* getAnabatic () const;
inline DbU::Unit getAxis () const;
DbU::Unit getAxisMin () const;
Interval getSide () const;
Segment* getSegment ( const Net* ) const;
inline const vector<Segment*>& getSegments () const;
//inline void setCapacity ( int );
//inline void incCapacity ( int );
inline void forceCapacity ( int );
inline void reserveCapacity ( int );
inline void setRealOccupancy ( int );
void incRealOccupancy ( int );
void incRealOccupancy2 ( int );
inline void incEstimateOccupancy ( float );
inline void setHistoricCost ( float );
bool isEnding ( Segment* ) const;
void add ( Segment* );
void remove ( Segment* );
void replace ( Segment* orig, Segment* repl );
size_t ripup ();
inline const Flags& flags () const;
inline Flags& flags ();
inline void revalidate () const;
bool isMaxCapacity ( Net* net = NULL ) const;
inline Flags& setFlags ( Flags mask );
void _setSource ( GCell* );
void _setTarget ( GCell* );
public:
// ExtensionGo support.
inline const Name& staticGetName ();
virtual const Name& getName () const;
virtual void translate ( const DbU::Unit&, const DbU::Unit& );
virtual Box getBoundingBox () const;
virtual void invalidate ( bool propagateFlag=true );
virtual void materialize ();
public:
// Inspector support.
virtual string _getTypeName () const;
virtual string _getString () const;
virtual Record* _getRecord () const;
protected:
Edge ( GCell* source, GCell* target, Flags flags );
virtual ~Edge ();
virtual void _postCreate ();
virtual void _preDestroy ();
private:
Edge ( const Edge& );
Edge& operator= ( const Edge& );
private:
static Name _extensionName;
Flags _flags;
EdgeCapacity* _capacities;
unsigned int _reservedCapacity;
unsigned int _realOccupancy;
float _estimateOccupancy;
float _historicCost;
GCell* _source;
GCell* _target;
DbU::Unit _axis;
vector<Segment*> _segments;
};
inline const Name& Edge::staticGetName () { return _extensionName; }
inline bool Edge::isVertical () const { return _flags.isset(Flags::Vertical); }
inline bool Edge::isHorizontal () const { return _flags.isset(Flags::Horizontal); }
inline bool Edge::hasNet ( const Net* owner ) const { return getSegment(owner); }
inline unsigned int Edge::getCapacity ( size_t depth ) const { return (_capacities) ? _capacities->getCapacity(depth) : 0; }
inline unsigned int Edge::getRawCapacity () const { return (_capacities) ? _capacities->getCapacity() : 0; }
inline unsigned int Edge::getReservedCapacity () const { return _reservedCapacity; }
inline unsigned int Edge::getRealOccupancy () const { return _realOccupancy; }
inline float Edge::getEstimateOccupancy () const { return _estimateOccupancy; }
inline float Edge::getHistoricCost () const { return _historicCost; }
inline GCell* Edge::getSource () const { return _source; }
inline GCell* Edge::getTarget () const { return _target; }
inline DbU::Unit Edge::getAxis () const { return _axis; }
inline const vector<Segment*>& Edge::getSegments () const { return _segments; }
inline void Edge::forceCapacity ( int capacity ) { if (_capacities) _capacities->forceCapacity(capacity); }
//inline void Edge::incCapacity ( int delta ) { _capacity = ((int)_capacity+delta > 0) ? _capacity+delta : 0; }
//inline void Edge::setCapacity ( int c ) { _capacity = ((int) c > 0) ? c : 0; }
inline void Edge::setRealOccupancy ( int c ) { _realOccupancy = ((int) c > 0) ? c : 0; }
inline void Edge::setHistoricCost ( float hcost ) { _historicCost = hcost; }
inline void Edge::incEstimateOccupancy ( float delta ) { _estimateOccupancy += delta; }
inline const Flags& Edge::flags () const { return _flags; }
inline Flags& Edge::flags () { return _flags; }
inline Flags& Edge::setFlags ( Flags mask ) { _flags |= mask; return _flags; }
inline void Edge::reserveCapacity ( int delta ) { _reservedCapacity = ((int)_reservedCapacity+delta > 0) ? _reservedCapacity+delta : 0; }
inline unsigned int Edge::getCapacity () const
{
if (not _capacities) return 0;
return (_capacities->getCapacity() > (int)_reservedCapacity) ? _capacities->getCapacity()-_reservedCapacity : 0;
}
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::Edge);

View File

@ -1,99 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "EdgeCapacity.h<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2018-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/EdgeCapacity.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_EDGE_CAPACITY_H
#define ANABATIC_EDGE_CAPACITY_H
#include <string>
#include <set>
#include "hurricane/Interval.h"
#include "anabatic/Constants.h"
namespace Anabatic {
using Hurricane::Record;
using Hurricane::DbU;
using Hurricane::Interval;
class AnabaticEngine;
// -------------------------------------------------------------------
// Class : "EdgeCapacity".
class EdgeCapacity {
public:
class Compare {
public:
inline bool operator() ( const EdgeCapacity*, const EdgeCapacity* ) const;
};
public:
EdgeCapacity ( AnabaticEngine*, Flags, Interval, size_t depth );
inline size_t incref ();
inline size_t decref ();
inline size_t getref () const;
inline AnabaticEngine* getAnabatic () const;
inline const Interval& getSpan () const;
inline int getCapacity () const;
inline int getCapacity ( size_t depth ) const;
void forceCapacity ( unsigned int );
std::string _getString () const;
Record* _getRecord () const;
private:
private:
AnabaticEngine* _anabatic;
size_t _refCount;
Flags _flags;
size_t _depth;
Interval _span;
std::vector<int> _capacities;
};
inline size_t EdgeCapacity::incref () { return ++_refCount; }
inline size_t EdgeCapacity::decref () { if (_refCount < 2) { delete this; return 0; } return --_refCount; }
inline size_t EdgeCapacity::getref () const { return _refCount; }
inline AnabaticEngine* EdgeCapacity::getAnabatic () const { return _anabatic; }
inline const Interval& EdgeCapacity::getSpan () const { return _span; }
inline int EdgeCapacity::getCapacity ( size_t depth ) const { return (depth<_depth) ? _capacities[depth] : 0; }
inline int EdgeCapacity::getCapacity () const
{
int full = 0;
for ( size_t depth=0; depth<_depth ; ++depth ) full += _capacities[depth];
return full;
}
inline bool EdgeCapacity::Compare::operator() ( const EdgeCapacity* lhs, const EdgeCapacity* rhs ) const
{
if ( (lhs->_flags & Flags::Horizontal) and not (rhs->_flags & Flags::Horizontal)) return true;
if (not (lhs->_flags & Flags::Horizontal) and (rhs->_flags & Flags::Horizontal)) return false;
DbU::Unit dmin = lhs->getSpan().getVMin() - rhs->getSpan().getVMin();
if (dmin < 0) return true;
if (dmin > 0) return false;
return lhs->getSpan().getVMax() < rhs->getSpan().getVMax();
}
typedef std::set<EdgeCapacity*,EdgeCapacity::Compare> EdgeCapacityLut;
} // Anabatic namespace.
INSPECTOR_P_SUPPORT(Anabatic::EdgeCapacity);
#endif // ANABATIC_EDGE_CAPACITY_H

View File

@ -1,193 +0,0 @@
// -*- mode: C++; explicit-buffer-name: "Edges.h<anabatic>" -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2016-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | A n a b a t i c - Global Routing Toolbox |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./anabatic/Edges.h" |
// +-----------------------------------------------------------------+
#ifndef ANABATIC_EDGES_H
#define ANABATIC_EDGES_H
#include <string>
#include <vector>
#include "hurricane/DbU.h"
#include "hurricane/Collection.h"
#include "anabatic/Constants.h"
namespace Anabatic {
using std::string;
using std::vector;
using Hurricane::DbU;
using Hurricane::Record;
using Hurricane::Filter;
using Hurricane::Locator;
using Hurricane::Collection;
using Hurricane::GenericFilter;
using Hurricane::GenericLocator;
using Hurricane::GenericCollection;
class Edge;
class GCell;
// -------------------------------------------------------------------
// Collections.
typedef Hurricane::Filter<Edge*> EdgesHF;
typedef Hurricane::Locator<Edge*> EdgesHL;
typedef Hurricane::Collection<Edge*> EdgesHC;
typedef GenericCollection<Edge*> Edges;
typedef GenericLocator<Edge*> EdgesLocator;
typedef GenericFilter<Edge*> EdgesFilter;
class GCell;
// -------------------------------------------------------------------
// Class : "GCell_Edges".
class GCell_Edges : public EdgesHC {
public:
// Sub-Class: Locator.
class Locator : public EdgesHL {
public:
Locator ( const GCell* gcell, Flags filterFlags );
inline Locator ( const Locator& );
virtual Edge* getElement () const;
virtual EdgesHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
const GCell* _gcell;
Flags _stateFlags;
Flags _filterFlags;
size_t _iedge;
};
// GCell_Edges.
public:
inline GCell_Edges ( const GCell* gcell, Flags filterFlags=Flags::AllSides );
inline GCell_Edges ( const GCell_Edges& );
virtual EdgesHC* getClone () const;
virtual EdgesHL* getLocator () const;
virtual string _getString () const;
protected:
const GCell* _gcell;
Flags _filterFlags;
};
inline GCell_Edges::Locator::Locator ( const Locator &locator )
: EdgesHL()
, _gcell (locator._gcell)
, _stateFlags (locator._stateFlags)
, _filterFlags(locator._filterFlags)
, _iedge (locator._iedge)
{
// cdebug_log(110,0) << "GCell_Edges::Locator::Locator(const Locator&)" << std::endl;
}
inline GCell_Edges::GCell_Edges ( const GCell* gcell, Flags filterFlags )
: EdgesHC()
, _gcell (gcell)
, _filterFlags(filterFlags)
{ }
inline GCell_Edges::GCell_Edges ( const GCell_Edges& edges )
: EdgesHC()
, _gcell (edges._gcell)
, _filterFlags(edges._filterFlags)
{ }
// -------------------------------------------------------------------
// Class : "Path_Edges".
class Path_Edges : public EdgesHC {
public:
// Sub-Class: Locator.
class Locator : public EdgesHL {
public:
Locator ( const GCell* source, const GCell* target, Flags pathFlags );
inline Locator ( const Locator& );
virtual Edge* getElement () const;
virtual EdgesHL* getClone () const;
virtual bool isValid () const;
virtual void progress ();
virtual string _getString () const;
protected:
const GCell* _source;
const GCell* _target;
Flags _stateFlags;
DbU::Unit _uprobe;
Edge* _edge;
};
// GCell_Edges.
public:
inline Path_Edges ( const GCell* source, const GCell* target, Flags pathFlags=Flags::NorthPath );
inline Path_Edges ( const Path_Edges& );
virtual EdgesHC* getClone () const;
virtual EdgesHL* getLocator () const;
virtual string _getString () const;
protected:
const GCell* _source;
const GCell* _target;
Flags _pathFlags;
};
inline Path_Edges::Locator::Locator ( const Locator &locator )
: EdgesHL()
, _source (locator._source)
, _target (locator._target)
, _stateFlags(locator._stateFlags)
, _uprobe (locator._uprobe)
, _edge (locator._edge)
{
// cdebug_log(110,0) << "GCell_Edges::Locator::Locator(const Locator&)" << std::endl;
}
inline Path_Edges::Path_Edges ( const GCell* source, const GCell* target, Flags pathFlags )
: EdgesHC()
, _source (source)
, _target (target)
, _pathFlags(pathFlags)
{ }
inline Path_Edges::Path_Edges ( const Path_Edges& path )
: EdgesHC()
, _source (path._source)
, _target (path._target)
, _pathFlags(path._pathFlags)
{ }
} // Anabatic namespace.
GETSTRING_POINTER_SUPPORT(Anabatic::GCell_Edges);
GETSTRING_POINTER_SUPPORT(Anabatic::GCell_Edges::Locator);
GETSTRING_POINTER_SUPPORT(Anabatic::Path_Edges);
GETSTRING_POINTER_SUPPORT(Anabatic::Path_Edges::Locator);
IOSTREAM_POINTER_SUPPORT(Anabatic::GCell_Edges);
IOSTREAM_POINTER_SUPPORT(Anabatic::GCell_Edges::Locator);
IOSTREAM_POINTER_SUPPORT(Anabatic::Path_Edges);
IOSTREAM_POINTER_SUPPORT(Anabatic::Path_Edges::Locator);
#endif // ANABATIC_EDGES_H

Some files were not shown because too many files have changed in this diff Show More